mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 10:46:16 +03:00
Merge pull request #7650 from radarhere/tiff
Allow uncompressed TIFF images to be saved in chunks
This commit is contained in:
commit
bd7e709141
|
@ -484,13 +484,13 @@ class TestFileTiff:
|
|||
outfile = str(tmp_path / "temp.tif")
|
||||
with Image.open("Tests/images/ifd_tag_type.tiff") as im:
|
||||
exif = im.getexif()
|
||||
exif[256] = 100
|
||||
exif[264] = 100
|
||||
|
||||
im.save(outfile, exif=exif)
|
||||
|
||||
with Image.open(outfile) as im:
|
||||
exif = im.getexif()
|
||||
assert exif[256] == 100
|
||||
assert exif[264] == 100
|
||||
|
||||
def test_reload_exif_after_seek(self):
|
||||
with Image.open("Tests/images/multipage.tiff") as im:
|
||||
|
@ -781,6 +781,27 @@ class TestFileTiff:
|
|||
4001,
|
||||
]
|
||||
|
||||
def test_tiff_chunks(self, tmp_path):
|
||||
tmpfile = str(tmp_path / "temp.tif")
|
||||
|
||||
im = hopper()
|
||||
with open(tmpfile, "wb") as fp:
|
||||
for y in range(0, 128, 32):
|
||||
chunk = im.crop((0, y, 128, y + 32))
|
||||
if y == 0:
|
||||
chunk.save(
|
||||
fp,
|
||||
"TIFF",
|
||||
tiffinfo={
|
||||
TiffImagePlugin.IMAGEWIDTH: 128,
|
||||
TiffImagePlugin.IMAGELENGTH: 128,
|
||||
},
|
||||
)
|
||||
else:
|
||||
fp.write(chunk.tobytes())
|
||||
|
||||
assert_image_equal_tofile(im, tmpfile)
|
||||
|
||||
def test_close_on_load_exclusive(self, tmp_path):
|
||||
# similar to test_fd_leak, but runs on unixlike os
|
||||
tmpfile = str(tmp_path / "temp.tif")
|
||||
|
|
|
@ -164,6 +164,7 @@ def test_change_stripbytecounts_tag_type(tmp_path):
|
|||
|
||||
# Resize the image so that STRIPBYTECOUNTS will be larger than a SHORT
|
||||
im = im.resize((500, 500))
|
||||
info[TiffImagePlugin.IMAGEWIDTH] = im.width
|
||||
|
||||
# STRIPBYTECOUNTS can be a SHORT or a LONG
|
||||
info.tagtype[TiffImagePlugin.STRIPBYTECOUNTS] = TiffTags.SHORT
|
||||
|
|
|
@ -1704,28 +1704,27 @@ def _save(im, fp, filename):
|
|||
colormap += [0] * (256 - colors)
|
||||
ifd[COLORMAP] = colormap
|
||||
# data orientation
|
||||
stride = len(bits) * ((im.size[0] * bits[0] + 7) // 8)
|
||||
w, h = ifd[IMAGEWIDTH], ifd[IMAGELENGTH]
|
||||
stride = len(bits) * ((w * bits[0] + 7) // 8)
|
||||
if ROWSPERSTRIP not in ifd:
|
||||
# aim for given strip size (64 KB by default) when using libtiff writer
|
||||
if libtiff:
|
||||
im_strip_size = encoderinfo.get("strip_size", STRIP_SIZE)
|
||||
rows_per_strip = (
|
||||
1 if stride == 0 else min(im_strip_size // stride, im.size[1])
|
||||
)
|
||||
rows_per_strip = 1 if stride == 0 else min(im_strip_size // stride, h)
|
||||
# JPEG encoder expects multiple of 8 rows
|
||||
if compression == "jpeg":
|
||||
rows_per_strip = min(((rows_per_strip + 7) // 8) * 8, im.size[1])
|
||||
rows_per_strip = min(((rows_per_strip + 7) // 8) * 8, h)
|
||||
else:
|
||||
rows_per_strip = im.size[1]
|
||||
rows_per_strip = h
|
||||
if rows_per_strip == 0:
|
||||
rows_per_strip = 1
|
||||
ifd[ROWSPERSTRIP] = rows_per_strip
|
||||
strip_byte_counts = 1 if stride == 0 else stride * ifd[ROWSPERSTRIP]
|
||||
strips_per_image = (im.size[1] + ifd[ROWSPERSTRIP] - 1) // ifd[ROWSPERSTRIP]
|
||||
strips_per_image = (h + ifd[ROWSPERSTRIP] - 1) // ifd[ROWSPERSTRIP]
|
||||
if strip_byte_counts >= 2**16:
|
||||
ifd.tagtype[STRIPBYTECOUNTS] = TiffTags.LONG
|
||||
ifd[STRIPBYTECOUNTS] = (strip_byte_counts,) * (strips_per_image - 1) + (
|
||||
stride * im.size[1] - strip_byte_counts * (strips_per_image - 1),
|
||||
stride * h - strip_byte_counts * (strips_per_image - 1),
|
||||
)
|
||||
ifd[STRIPOFFSETS] = tuple(
|
||||
range(0, strip_byte_counts * strips_per_image, strip_byte_counts)
|
||||
|
|
Loading…
Reference in New Issue
Block a user