Merge pull request #5848 from radarhere/sampleformat

Pass SAMPLEFORMAT to libtiff
This commit is contained in:
Hugo van Kemenade 2021-12-28 10:03:16 +02:00 committed by GitHub
commit 1806cf5607
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 7 deletions

View File

@ -9,7 +9,7 @@ from ctypes import c_float
import pytest import pytest
from PIL import Image, ImageFilter, TiffImagePlugin, TiffTags, features from PIL import Image, ImageFilter, TiffImagePlugin, TiffTags, features
from PIL.TiffImagePlugin import STRIPOFFSETS, SUBIFD from PIL.TiffImagePlugin import SAMPLEFORMAT, STRIPOFFSETS, SUBIFD
from .helper import ( from .helper import (
assert_image_equal, assert_image_equal,
@ -825,6 +825,17 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, "Tests/images/copyleft.png", mode="RGB") assert_image_equal_tofile(im, "Tests/images/copyleft.png", mode="RGB")
def test_sampleformat_write(self, tmp_path):
im = Image.new("F", (1, 1))
out = str(tmp_path / "temp.tif")
TiffImagePlugin.WRITE_LIBTIFF = True
im.save(out)
TiffImagePlugin.WRITE_LIBTIFF = False
with Image.open(out) as reloaded:
assert reloaded.mode == "F"
assert reloaded.getexif()[SAMPLEFORMAT] == 3
def test_lzw(self): def test_lzw(self):
with Image.open("Tests/images/hopper_lzw.tif") as im: with Image.open("Tests/images/hopper_lzw.tif") as im:
assert im.mode == "RGB" assert im.mode == "RGB"

View File

@ -1676,8 +1676,6 @@ def _save(im, fp, filename):
# optional types for non core tags # optional types for non core tags
types = {} types = {}
# SAMPLEFORMAT is determined by the image format and should not be copied
# from legacy_ifd.
# STRIPOFFSETS and STRIPBYTECOUNTS are added by the library # STRIPOFFSETS and STRIPBYTECOUNTS are added by the library
# based on the data in the strip. # based on the data in the strip.
# The other tags expect arrays with a certain length (fixed or depending on # The other tags expect arrays with a certain length (fixed or depending on
@ -1686,7 +1684,6 @@ def _save(im, fp, filename):
# SUBIFD may also cause a segfault. # SUBIFD may also cause a segfault.
blocklist += [ blocklist += [
REFERENCEBLACKWHITE, REFERENCEBLACKWHITE,
SAMPLEFORMAT,
STRIPBYTECOUNTS, STRIPBYTECOUNTS,
STRIPOFFSETS, STRIPOFFSETS,
TRANSFERFUNCTION, TRANSFERFUNCTION,
@ -1702,9 +1699,14 @@ def _save(im, fp, filename):
legacy_ifd = {} legacy_ifd = {}
if hasattr(im, "tag"): if hasattr(im, "tag"):
legacy_ifd = im.tag.to_v2() legacy_ifd = im.tag.to_v2()
for tag, value in itertools.chain(
ifd.items(), getattr(im, "tag_v2", {}).items(), legacy_ifd.items() # SAMPLEFORMAT is determined by the image format and should not be copied
): # from legacy_ifd.
supplied_tags = {**getattr(im, "tag_v2", {}), **legacy_ifd}
if SAMPLEFORMAT in supplied_tags:
del supplied_tags[SAMPLEFORMAT]
for tag, value in itertools.chain(ifd.items(), supplied_tags.items()):
# Libtiff can only process certain core items without adding # Libtiff can only process certain core items without adding
# them to the custom dictionary. # them to the custom dictionary.
# Custom items are supported for int, float, unicode, string and byte # Custom items are supported for int, float, unicode, string and byte
@ -1729,6 +1731,9 @@ def _save(im, fp, filename):
else: else:
atts[tag] = value atts[tag] = value
if SAMPLEFORMAT in atts and len(atts[SAMPLEFORMAT]) == 1:
atts[SAMPLEFORMAT] = atts[SAMPLEFORMAT][0]
logger.debug("Converted items: %s" % sorted(atts.items())) logger.debug("Converted items: %s" % sorted(atts.items()))
# libtiff always expects the bytes in native order. # libtiff always expects the bytes in native order.