Fix IOError when saving progressive JPEGs.

when the jpeg encoder sees the flags optimize or progressive (or progression)
it will write the full image in one shot.

The bufsize needs to be big enough to hold the entire image. The current heuristic
is that the entire compressed image will fit in width * height bytes, but this
heuristic is only applied to save operations with the flag "optimize" and not to
save operations with the flag "progressive".

This patch fixes this oversight.

(Btw, it will probably be a good idea to have a loop that retries with a bigger
bufsize in case this guess is not big enough.)
This commit is contained in:
Joaquín Cuenca Abela 2013-08-02 14:36:46 +02:00
parent dcb6eef590
commit c68044bf7f
2 changed files with 23 additions and 11 deletions

View File

@ -561,11 +561,11 @@ def _save(im, fp, filename):
# is a value that's been used in a django patch.
# https://github.com/jdriscoll/django-imagekit/issues/50
bufsize=0
if "optimize" in info:
if "optimize" in info or "progressive" in info or "progression" in info:
bufsize = im.size[0]*im.size[1]
# The exif info needs to be written as one block, + APP1, + one spare byte.
# Ensure that our buffer is big enough
# Ensure that our buffer is big enough
bufsize = max(ImageFile.MAXBLOCK, bufsize, len(info.get("exif",b"")) + 5 )
ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)], bufsize)

View File

@ -114,17 +114,29 @@ def test_optimize():
assert_true(im1.bytes >= im2.bytes)
def test_optimize_large_buffer():
#https://github.com/python-imaging/Pillow/issues/148
f = tempfile('temp.jpg')
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096,4096), 0xff3333)
im.save(f, format="JPEG", optimize=True)
#https://github.com/python-imaging/Pillow/issues/148
f = tempfile('temp.jpg')
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096,4096), 0xff3333)
im.save(f, format="JPEG", optimize=True)
def test_progressive():
im1 = roundtrip(lena())
im2 = roundtrip(lena(), progressive=True)
assert_image_equal(im1, im2)
assert_true(im1.bytes >= im2.bytes)
def test_progressive_large_buffer():
f = tempfile('temp.jpg')
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096,4096), 0xff3333)
im.save(f, format="JPEG", progressive=True)
def test_large_exif():
#https://github.com/python-imaging/Pillow/issues/148
f = tempfile('temp.jpg')
im = lena()
im.save(f,'JPEG', quality=90, exif=b"1"*65532)
#https://github.com/python-imaging/Pillow/issues/148
f = tempfile('temp.jpg')
im = lena()
im.save(f,'JPEG', quality=90, exif=b"1"*65532)
def test_progressive():
im1 = roundtrip(lena())