我正在开发一个程序,可以将动态gif转换成字符画风格的动态gif并返回,例如:
当我制作gif并打开它时,动画的开头总是有一个黑色帧,这使得循环播放相当烦人。
我尝试将创建的gif的alpha通道设置为0,并且仅将
演示:
原始gif: trippy circles 输出gif: trippy ascii circles elongated 编辑:我刚刚有所突破!
下面是程序,相关函数为
asciify(foo.gif)
bar.gif has been created
当我制作gif并打开它时,动画的开头总是有一个黑色帧,这使得循环播放相当烦人。
我尝试将创建的gif的alpha通道设置为0,并且仅将
ascii_image_gifs[1,-1]
附加到输出gif中,但我已经没有更多的想法了。演示:
原始gif: trippy circles 输出gif: trippy ascii circles elongated 编辑:我刚刚有所突破!
gifify()
中的这行代码是罪魁祸首:save_as = Image.new('RGBA', (self._nw*3, self._nh*8), (0, 0, 0, 0))
如果我将其更改为save_as = Image.new('RGBA', (self._nw*3, self._nh*8), 'white')
黑色框架变成白色,所以我的问题变成:在保存/创建输出图像时如何忽略由Image.new()
创建的图像?下面是程序,相关函数为
gifify()
。from PIL import Image, ImageFont, ImageDraw
__author__ = 'Nikolas'
ASCII_SHADING_CHARS = ['M', 'W', 'N', 'Q', 'B', 'H', 'K', 'R', '#', 'E', 'D', 'F', 'X', 'O', 'A', 'P', 'G', 'U', 'S',
'V', 'Z', 'Y', 'C', 'L', 'T', 'J', '$', 'I', '*', ':', '.', ' '] # from darkest to lightest 32
#ASCII_SHADING_CHARS = ASCII_SHADING_CHARS[::-1]
class Asciify:
def __init__(self, img, new_width=500):
self.width, self.height = img.size # image.size returns a 2 tuple (width, height) in pixels
self._nw = new_width
self._nh = int(new_width * self.height / self.width)
self.im = img
def grayify_and_resize(self):
"""
Split the GIF into individual frames. Resize and convert each frame to monochrome.
:returns: a list of resized black&white Image objects
"""
new_width = self._nw
new_height = self._nh
num_frames = self.im.n_frames # number of frames in the .gif animation
result_list = []
for i in range(0, num_frames - 1):
# convert to mode L (b&w); resize to new dimensions
result_list.append(self.im.convert('L').resize((int(new_width), new_height)))
self.im.seek(self.im.tell() + 1) # move to the next frame in the gif animation
return result_list
def ascii_map(self, im_list, color_width=int(255 / len(ASCII_SHADING_CHARS))):
"""
Maps an ascii shading character to a pixel of each frame of the GIF
:param im_list: a list of black and white Image objects
:param color_width: determines the color intensity of each pixel
:returns: a list of each frame of the gif converted to ascii pixels
"""
ascii_image_list = [] # unformatted ascii images; needs to be broken into proper rows and columns
result_list = [] # ascii_image_list broken into proper rows and columns; how convinient
for image in im_list:
pixels = image.getdata() # color data on every pixel per image
append_list = [] # temporary list to append to ascii_image_list
for pixel_value in pixels:
index = int(pixel_value // color_width)
if index >= len(ASCII_SHADING_CHARS):
append_list.append(ASCII_SHADING_CHARS[-1])
else:
append_list.append(ASCII_SHADING_CHARS[index]) # 'replace' pixel with ascii char
ascii_image_list.append(append_list) # adds an element to ascii_image_list containing every pixel for image
for ascii_image in ascii_image_list:
ascii_string = "".join(ascii_image)
result_list.append([ascii_string[index:index + self._nw]
for index in range(0, len(ascii_string), self._nw)])
return result_list
def gifify(self, ascii_image_list):
"""
Return the ascii strings to .gif format for use in a traditional image viewer.
:param ascii_image_list: A list of ascii 'pixel' images
:returns: None
"""
# 7 = nw*4, nh*10
# 5 = nw*3, nh*8
font = ImageFont.truetype('ascii.ttf', 5) # set font and font size
ascii_image_strings = ['\n'.join(image) for image in ascii_image_list]
ascii_image_gifs = []
for image in ascii_image_strings:
#print(image)
if image == ascii_image_strings[0]:
continue
temp_image = Image.new('RGBA', (self._nw*3, self._nh*8), (255,255,255,0)) # should be transparent, didn't work
image_draw = ImageDraw.Draw(temp_image)
image_draw.text((0, 0), image, font=font, fill='black')
temp_image.resize((self._nw, self._nh))
ascii_image_gifs.append(temp_image)
if image == ascii_image_strings[-1]:
save_as = Image.new('RGBA', (self._nw*3, self._nh*8), (0, 0, 0, 0)) # should also be transparent, didn't work
save_as.save('temp.gif', save_all=True, append_images=ascii_image_gifs, loop=0, fps=24)
save_as.close()
if __name__ == "__main__":
im = Image.open("trippy.gif")
asciify_im = Asciify(im, 110)
gif_list = asciify_im.grayify_and_resize()
ascii_images = asciify_im.ascii_map(gif_list)
asciify_im.gifify(ascii_images)
# Debugging ascii image creation #
# outfile = open("outfile.txt", 'w')
# for image in ascii_images:
# outfile.write("\n".join(image) + '\n\n')
append_images=ascii_image_gifs
是将那个图像列表附加到一个全黑的现有图像上。几天前我也遇到过这种情况,当时我不小心将新创建的 gif 附加到原始 gif 上,导致帧数和长度翻倍。但是我已经浏览了文档,找不到是什么造成了那个黑色图像。 - percepmoidresize()
返回已调整大小图像的拷贝。 - Mark Setchell