Saving animated GIFs using PIL (image saved does not animate)
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_si开发者_开发技巧ze
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
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.
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
精彩评论