|
| 1 | +import os, imageio |
| 2 | +from PIL import Image, ImageDraw, ImageFont |
| 3 | + |
| 4 | +# 拆分 gif 将每一帧处理成字符画 |
| 5 | +def gif2pic(file, ascii_chars, isgray, font, scale): |
| 6 | + ''' |
| 7 | + file: gif 文件 |
| 8 | + ascii_chars: 灰度值对应的字符串 |
| 9 | + isgray: 是否黑白 |
| 10 | + font: ImageFont 对象 |
| 11 | + scale: 缩放比例 |
| 12 | + ''' |
| 13 | + im = Image.open(file) |
| 14 | + path = os.getcwd() |
| 15 | + if(not os.path.exists(path+"/tmp")): |
| 16 | + os.mkdir(path+"/tmp") |
| 17 | + os.chdir(path+"/tmp") |
| 18 | + # 清空 tmp 目录下内容 |
| 19 | + for f in os.listdir(path+"/tmp"): |
| 20 | + os.remove(f) |
| 21 | + try: |
| 22 | + while 1: |
| 23 | + current = im.tell() |
| 24 | + name = file.split('.')[0]+'_tmp_'+str(current)+'.png' |
| 25 | + # 保存每一帧图片 |
| 26 | + im.save(name) |
| 27 | + # 将每一帧处理为字符画 |
| 28 | + img2ascii(name, ascii_chars, isgray, font, scale) |
| 29 | + # 继续处理下一帧 |
| 30 | + im.seek(current+1) |
| 31 | + except: |
| 32 | + os.chdir(path) |
| 33 | + |
| 34 | +# 将不同的灰度值映射为 ASCII 字符 |
| 35 | +def get_char(ascii_chars, r, g, b): |
| 36 | + length = len(ascii_chars) |
| 37 | + gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) |
| 38 | + return ascii_chars[int(gray/(256/length))] |
| 39 | + |
| 40 | + |
| 41 | +# 将图片处理成字符画 |
| 42 | +def img2ascii(img, ascii_chars, isgray, font, scale): |
| 43 | + scale = scale |
| 44 | + # 将图片转换为 RGB 模式 |
| 45 | + im = Image.open(img).convert('RGB') |
| 46 | + # 设定处理后的字符画大小 |
| 47 | + raw_width = int(im.width * scale) |
| 48 | + raw_height = int(im.height * scale) |
| 49 | + # 获取设定的字体的尺寸 |
| 50 | + font_x, font_y = font.getsize(' ') |
| 51 | + # 确定单元的大小 |
| 52 | + block_x = int(font_x * scale) |
| 53 | + block_y = int(font_y * scale) |
| 54 | + # 确定长宽各有几个单元 |
| 55 | + w = int(raw_width/block_x) |
| 56 | + h = int(raw_height/block_y) |
| 57 | + # 将每个单元缩小为一个像素 |
| 58 | + im = im.resize((w, h), Image.NEAREST) |
| 59 | + # txts 和 colors 分别存储对应块的 ASCII 字符和 RGB 值 |
| 60 | + txts = [] |
| 61 | + colors = [] |
| 62 | + for i in range(h): |
| 63 | + line = '' |
| 64 | + lineColor = [] |
| 65 | + for j in range(w): |
| 66 | + pixel = im.getpixel((j, i)) |
| 67 | + lineColor.append((pixel[0], pixel[1], pixel[2])) |
| 68 | + line += get_char(ascii_chars, pixel[0], pixel[1], pixel[2]) |
| 69 | + txts.append(line) |
| 70 | + colors.append(lineColor) |
| 71 | + # 创建新画布 |
| 72 | + img_txt = Image.new('RGB', (raw_width, raw_height), (255, 255, 255)) |
| 73 | + # 创建 ImageDraw 对象以写入 ASCII |
| 74 | + draw = ImageDraw.Draw(img_txt) |
| 75 | + for j in range(len(txts)): |
| 76 | + for i in range(len(txts[0])): |
| 77 | + if isgray: |
| 78 | + draw.text((i * block_x, j * block_y), txts[j][i], (119,136,153)) |
| 79 | + else: |
| 80 | + draw.text((i * block_x, j * block_y), txts[j][i], colors[j][i]) |
| 81 | + img_txt.save(img) |
| 82 | + |
| 83 | +# 读取 tmp 目录下文件合成 gif |
| 84 | +def pic2gif(dir_name, out_name, duration): |
| 85 | + path = os.getcwd() |
| 86 | + os.chdir(dir_name) |
| 87 | + dirs = os.listdir() |
| 88 | + images = [] |
| 89 | + num = 0 |
| 90 | + for d in dirs: |
| 91 | + images.append(imageio.imread(d)) |
| 92 | + num += 1 |
| 93 | + os.chdir(path) |
| 94 | + imageio.mimsave(out_name + '_ascii.gif',images,duration = duration) |
| 95 | + |
| 96 | + |
| 97 | +if __name__ == "__main__": |
| 98 | + ascii_chars = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ") |
| 99 | + fname = 'g2' |
| 100 | + font = ImageFont.truetype('Courier-New.ttf', size=int(6)) |
| 101 | + gif2pic(fname + '.gif', ascii_chars, False, font, 1) |
| 102 | + pic2gif('tmp', fname, 0.2) |
0 commit comments