【问题标题】:Saving animated GIFs using PIL (image saved does not animate)使用 PIL 保存动画 GIF(保存的图像不动画)
【发布时间】:2011-01-10 03:14:59
【问题描述】:

我有 Apache2 + PIL + Django + X-sendfile。我的问题是当我保存动画 GIF 时,当我通过浏览器输出时它不会“动画”。

这是我的代码,用于显示位于公共可访问目录之外的图像。

def raw(request,uuid):
    target = str(uuid).split('.')[:-1][0]
    image = Uploads.objects.get(uuid=target)

    path = image.path
    filepath = os.path.join(path,"%s.%s" % (image.uuid,image.ext))

    response = HttpResponse(mimetype=mimetypes.guess_type(filepath)) 
    response['Content-Disposition']='filename="%s"'\
                                    %smart_str(image.filename)
    response["X-Sendfile"] = filepath
    response['Content-length'] = os.stat(filepath).st_size

    return response

更新

事实证明它有效。我的问题是当我尝试通过 URL 上传图像时。它可能不会保存整个 GIF?

def handle_url_file(request):
    """
    Open a file from a URL.
    Split the file to get the filename and extension.
    Generate a random uuid using rand1()
    Then save the file.
    Return the UUID when successful.
    """

    try:
        file = urllib.urlopen(request.POST['url'])
        randname = rand1(settings.RANDOM_ID_LENGTH)
        newfilename = request.POST['url'].split('/')[-1]
        ext = str(newfilename.split('.')[-1]).lower()
        im = cStringIO.StringIO(file.read()) # constructs a StringIO holding the image
        img = Image.open(im)

        filehash = checkhash(im)

        image = Uploads.objects.get(filehash=filehash)
        uuid = image.uuid

        return "%s" % (uuid)

    except Uploads.DoesNotExist:

        img.save(os.path.join(settings.UPLOAD_DIRECTORY,(("%s.%s")%(randname,ext))))
        del img

        filesize = os.stat(os.path.join(settings.UPLOAD_DIRECTORY,(("%s.%s")%(randname,ext)))).st_size
        upload = Uploads(
            ip          = request.META['REMOTE_ADDR'],
            filename    = newfilename,
            uuid        = randname,
            ext         = ext,
            path        = settings.UPLOAD_DIRECTORY,
            views       = 1,
            bandwidth   = filesize,
            source      = request.POST['url'],
            size        = filesize,
            filehash    = filehash,
        )

        upload.save()
        #return uuid
        return "%s" % (upload.uuid)
    except IOError, e:
        raise e

有什么想法吗?

谢谢!

温伯特

【问题讨论】:

  • 通过响应正常发送数据时是否出现动画?
  • Ignacio,我刚刚发现“def raw(request)”确实有效。并且在handle_url_file() 定义中发现了问题。它不会保存整个 GIF?

标签: django apache x-sendfile


【解决方案1】:

Image 类从何而来,Image.open 做了什么?

我的猜测是它对图像数据进行了一些清理(这是一件好事),但只保存了 Gif 的第一帧。

编辑:

我确信这是 PIL 的问题。 PIL documentation on GIF 说:

PIL 读取 GIF 文件格式的 GIF87a 和 GIF89a 版本。该库写入运行长度编码的 GIF87a 文件。

为了验证,您可以将im的内容直接写入磁盘并与源图像进行比较。

【讨论】:

  • 它来自“import Image”——某种python图像库。我忘了什么。 ://
  • 我认为 im = cStringIO.StringIO(file.read()) 只是保存了 gif 文件的一部分
  • 我把事情复杂化了。 bob2 (irc #python) 建议我只使用:“with open(path_to_save, 'wb') as output: output.write(data)”
  • 是否有替代方法来解决 PIL 的限制?
【解决方案2】:

问题是保存图像的 PIL 打开版本。当你通过 PIL 保存时,它只会保存第一帧。

但是,有一个简单的解决方法:制作文件的临时副本,使用 PIL 打开它,然后如果检测到它是动画 GIF,则只需保存原始文件,而不是 PIL 打开的版本。

如果您保存原始的动画 GIF 文件,然后将其流式传输回您的 HTTP 响应,它将通过动画传输到浏览器。

检测您的 PIL 对象是否为动画 GIF 的示例代码:

def image_is_animated_gif(image):
    # verify image format
    if image.format.lower() != 'gif':
        return False

    # verify GIF is animated by attempting to seek beyond the initial frame
    try:
        image.seek(1)
    except EOFError:
        return False
    else:
        return True

【讨论】:

    猜你喜欢
    • 2020-08-30
    • 2019-08-11
    • 2012-02-26
    • 1970-01-01
    • 2014-09-01
    • 2021-06-24
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    相关资源
    最近更新 更多