- 楔子
想来很多人对这种风格的代码截图都很熟悉了:
vscode里有不少插件可以直接生成,比如我在用的CodeSnap,也有一些公开免费的网站,比如:carbon,甚至于carbon网站可以直接通过URL传递代码内容和截图风格的参数。
- 正文
这种代码截图排版不乱、带语法高亮,非常适合代码传播和“抄”代码。我在搭建微信机器人后,实际体验中遇到的一个困扰,就是我在提问代码的时候,排版显得非常乱,于是我想到这个代码截图,试图通过程序的方式生成类似的图片。
最开始是找到了别人借助carbon网站做的api接口Carbon-API 和carbon-api。优点自不必说,排版精美、语法高亮支持性好、使用方便,唯一的缺点就是需要良好的网络支持。虽然官网没有被墙,但是由于我的小鸡宝网络不佳,实际使用中时不时会生成失败。
所以我开始寻找本地生成的方案,就是各种pygments做语法高亮+图片工具。过程就不再赘述了,虽然效果不如人家专业的精美,不过总算差强人意。最后把使用code2img代码给大家分享一下:
code2img.py
import pygments
from pygments.styles import get_style_by_name
from pygments.formatters import ImageFormatter
from pygments.lexers import get_lexer_for_filename,get_lexer_by_name
from PIL import Image, ImageDraw, ImageFilter, ImageEnhance
import io,os
def add_shadow_and_gradient(image_data):
def add_gradient(size):
gradient = Image.new('RGBA', size, color=0)
draw = ImageDraw.Draw(gradient)
start = (253, 46, 216)
end = (23, 214, 255)
deltas = [(b - a) / gradient.width / 2 for a, b in zip(start, end)]
for i, color in enumerate(range(gradient.width * 2)):
color = [round(s + d * i) for s,d in zip(start, deltas)]
draw.line([(i, 0), (0, i)], tuple(color), width=1)
return gradient
image = Image.open(io.BytesIO(image_data))
image = ImageEnhance.Color(image).enhance(2)
pad_x, pad_y, offset_x, offset_y = 30, 30, 8, 8
width, height = image.size
bottom_canvas = add_gradient((width+pad_x, height+pad_y))
shadow = Image.new('RGBA', (width, height), (20, 20, 20, 255))
bottom_canvas.paste(shadow, (pad_x//2+offset_x,pad_y//2+offset_y))
bottom_canvas = bottom_canvas.filter(ImageFilter.GaussianBlur(6))
bottom_canvas.paste(image, (pad_x//2,pad_y//2))
return bottom_canvas
def code2img(code_snippets, language):
try:
lexer = get_lexer_by_name(language)
except:
lexer = get_lexer_by_name("python")
style = get_style_by_name('material')
formatter = ImageFormatter(
font_name = 'YaHei Consolas Hybrid', # 一个对中英文混合代码字体比较友好的字体
font_size = 30,
style = style,
line_pad = 10,
line_number_bold = True,
line_number_italic = True,
line_number_bg = style.background_color,
image_pad = 20,
full = True
)
result = pygments.highlight(code_snippets, lexer, formatter)
result = add_shadow_and_gradient(result)
outname = os.getcwd() + '\\assets\\code-snippets.png'
with open(outname, 'wb') as f:
if isinstance(result, Image.Image):
result.save(f)
else:
f.write(result)
-
提问对话:
-
检测内容并生成代码截图:
-
实际应用场景
内网限制或者其他限制导致只能从手机“抄”代码的时候