【问题标题】:How can I stop pillow from inserting a black frame into my animated gif如何阻止枕头在我的动画 gif 中插入黑框
【发布时间】:2018-11-03 04:52:21
【问题描述】:

我正在开发一个程序,该程序采用动画 gif 并将 gif 的 asciified 版本作为不同的动画 gif 返回 例子

asciify(foo.gif)
bar.gif has been created

在我制作 gif 并打开它后,动画开始处总是有一个黑框,这使得循环观看非常烦人。

我尝试将创建的 gif 的 alpha 通道设置为 0,并且只将 ascii_image_gifs[1,-1] 附加到输出 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')

【问题讨论】:

  • 仅仅提供所谓的“相关功能”是不够的。请edit您的问题并使其成为其他人可以运行以重现问题并测试他们的解决方案的东西。
  • 好的,抱歉,我已经这样做了。谢谢
  • 哦,如果有人决定运行它,您将希望将 new_width 参数设置得非常小(25)帧,否则它将永远持续下去.
  • 检查任何地方都为时已晚,但我似乎记得您需要 127 的 alpha 值才能在 GIF 中透明。
  • @MarkSetchell 我刚刚尝试了您的建议,但没有成功。不过谢谢。感觉这个参数append_images=ascii_image_gifs 正在将该图像列表附加到现有的全黑图像中。几天前,当我不小心将新创建的 gif 附加到原始 gif 上时,这发生在我身上,帧的长度和数量增加了一倍。但是我浏览了文档并找不到创建该黑色图像的原因。

标签: python python-imaging-library


【解决方案1】:

感觉这个参数 append_images=ascii_image_gifs 正在将该图像列表附加到现有的全黑图像。

你是 100% 正确的。

致电image.save("test.gif", append_images=images)。那么image 是第一帧,images 是所有额外/附加帧的列表。

因此,改为使用images[0] 作为第一帧,并附加其余帧 (images[1:])。


在您的代码中save_as 是黑框的原因。所以改为删除它,只使用ascii_image_gifs

 ascii_image_gifs[0].save('temp.gif', save_all=True, append_images=ascii_image_gifs[1:], loop=0, fps=24)

这可能有点令人费解,但这就是它与 PIL 的工作方式。

【讨论】:

  • 这不是太复杂,它实际上很有意义,我只是没有想到它哈哈。非常感谢!
猜你喜欢
  • 2020-11-27
  • 2014-01-25
  • 1970-01-01
  • 2017-07-05
  • 2013-03-16
  • 2012-12-19
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多