使用 PIL 保存动画 GIF(保存的图像没有动画效果)

发布于 2024-10-11 01:22:14 字数 2304 浏览 13 评论 0原文

我有 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

有什么想法吗?

谢谢!

温伯特

I have Apache2 + PIL + Django + X-sendfile. My problem is that when I save an animated GIF, it won't "animate" when I output through the browser.

Here is my code to display the image located outside the public accessible directory.

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

UPDATE

It turns out that it works. My problem is when I try to upload an image via URL. It probably doesn't save the entire 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

Any ideas?

Thanks!

Wenbert

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

神经暖 2024-10-18 01:22:14

Image 类从何而来,Image.open 有何作用?

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

编辑:

我确信这是 PIL 的问题。 GIF 上的 PIL 文档 说:

PIL 读取 GIF 文件格式的 GIF87a 和 GIF89a 版本。该库写入游程编码的 GIF87a 文件。

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

Where does that Image class come from and what does Image.open do?

My guess is that it does some sanitizing of the image data (which is a good thing), but does only save the first frame of the Gif.

Edit:

I'm convinced this is an issue with PIL. The PIL documentation on GIF says:

PIL reads GIF87a and GIF89a versions of the GIF file format. The library writes run-length encoded GIF87a files.

To verify, you can write the contents of im directly to disk and compare with the source image.

长梦不多时 2024-10-18 01:22:14

问题是保存图像的 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

The problem is saving a PIL-opened version of the image. When you save it out via PIL, it will only save the first frame.

However, there's an easy workaround: Make a temp copy of the file, open that with PIL, and then if you detect that it's an animated GIF, then just save the original file, not the PIL-opened version.

If you save the original animated GIF file and then stream it back into your HTTP response, it will come through animated to the browser.

Example code to detect if your PIL object is an animated 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文