mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-06-06 14:13:15 +03:00
Merge pull request #5655 from radarhere/whiteiszero
Allow saving 1 and L mode TIFF with PhotometricInterpretation 0
This commit is contained in:
commit
2d01f7d022
|
@ -447,6 +447,15 @@ class TestFileTiff:
|
||||||
im.seek(1)
|
im.seek(1)
|
||||||
assert im.getexif()[273] == (1408, 1907)
|
assert im.getexif()[273] == (1408, 1907)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("mode", ("1", "L"))
|
||||||
|
def test_photometric(self, mode, tmp_path):
|
||||||
|
filename = str(tmp_path / "temp.tif")
|
||||||
|
im = hopper(mode)
|
||||||
|
im.save(filename, tiffinfo={262: 0})
|
||||||
|
with Image.open(filename) as reloaded:
|
||||||
|
assert reloaded.tag_v2[262] == 0
|
||||||
|
assert_image_equal(im, reloaded)
|
||||||
|
|
||||||
def test_seek(self):
|
def test_seek(self):
|
||||||
filename = "Tests/images/pil136.tiff"
|
filename = "Tests/images/pil136.tiff"
|
||||||
with Image.open(filename) as im:
|
with Image.open(filename) as im:
|
||||||
|
|
|
@ -48,7 +48,7 @@ from collections.abc import MutableMapping
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from numbers import Number, Rational
|
from numbers import Number, Rational
|
||||||
|
|
||||||
from . import Image, ImageFile, ImagePalette, TiffTags
|
from . import Image, ImageFile, ImageOps, ImagePalette, TiffTags
|
||||||
from ._binary import o8
|
from ._binary import o8
|
||||||
from .TiffTags import TYPES
|
from .TiffTags import TYPES
|
||||||
|
|
||||||
|
@ -1487,7 +1487,9 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
ifd = ImageFileDirectory_v2(prefix=prefix)
|
ifd = ImageFileDirectory_v2(prefix=prefix)
|
||||||
|
|
||||||
compression = im.encoderinfo.get("compression", im.info.get("compression"))
|
encoderinfo = im.encoderinfo
|
||||||
|
encoderconfig = im.encoderconfig
|
||||||
|
compression = encoderinfo.get("compression", im.info.get("compression"))
|
||||||
if compression is None:
|
if compression is None:
|
||||||
compression = "raw"
|
compression = "raw"
|
||||||
elif compression == "tiff_jpeg":
|
elif compression == "tiff_jpeg":
|
||||||
|
@ -1505,7 +1507,7 @@ def _save(im, fp, filename):
|
||||||
ifd[IMAGELENGTH] = im.size[1]
|
ifd[IMAGELENGTH] = im.size[1]
|
||||||
|
|
||||||
# write any arbitrary tags passed in as an ImageFileDirectory
|
# write any arbitrary tags passed in as an ImageFileDirectory
|
||||||
info = im.encoderinfo.get("tiffinfo", {})
|
info = encoderinfo.get("tiffinfo", {})
|
||||||
logger.debug("Tiffinfo Keys: %s" % list(info))
|
logger.debug("Tiffinfo Keys: %s" % list(info))
|
||||||
if isinstance(info, ImageFileDirectory_v1):
|
if isinstance(info, ImageFileDirectory_v1):
|
||||||
info = info.to_v2()
|
info = info.to_v2()
|
||||||
|
@ -1534,7 +1536,7 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
# preserve ICC profile (should also work when saving other formats
|
# preserve ICC profile (should also work when saving other formats
|
||||||
# which support profiles as TIFF) -- 2008-06-06 Florian Hoech
|
# which support profiles as TIFF) -- 2008-06-06 Florian Hoech
|
||||||
icc = im.encoderinfo.get("icc_profile", im.info.get("icc_profile"))
|
icc = encoderinfo.get("icc_profile", im.info.get("icc_profile"))
|
||||||
if icc:
|
if icc:
|
||||||
ifd[ICCPROFILE] = icc
|
ifd[ICCPROFILE] = icc
|
||||||
|
|
||||||
|
@ -1550,10 +1552,10 @@ def _save(im, fp, filename):
|
||||||
(ARTIST, "artist"),
|
(ARTIST, "artist"),
|
||||||
(COPYRIGHT, "copyright"),
|
(COPYRIGHT, "copyright"),
|
||||||
]:
|
]:
|
||||||
if name in im.encoderinfo:
|
if name in encoderinfo:
|
||||||
ifd[key] = im.encoderinfo[name]
|
ifd[key] = encoderinfo[name]
|
||||||
|
|
||||||
dpi = im.encoderinfo.get("dpi")
|
dpi = encoderinfo.get("dpi")
|
||||||
if dpi:
|
if dpi:
|
||||||
ifd[RESOLUTION_UNIT] = 2
|
ifd[RESOLUTION_UNIT] = 2
|
||||||
ifd[X_RESOLUTION] = dpi[0]
|
ifd[X_RESOLUTION] = dpi[0]
|
||||||
|
@ -1568,7 +1570,18 @@ def _save(im, fp, filename):
|
||||||
if format != 1:
|
if format != 1:
|
||||||
ifd[SAMPLEFORMAT] = format
|
ifd[SAMPLEFORMAT] = format
|
||||||
|
|
||||||
ifd[PHOTOMETRIC_INTERPRETATION] = photo
|
if PHOTOMETRIC_INTERPRETATION not in ifd:
|
||||||
|
ifd[PHOTOMETRIC_INTERPRETATION] = photo
|
||||||
|
elif im.mode in ("1", "L") and ifd[PHOTOMETRIC_INTERPRETATION] == 0:
|
||||||
|
if im.mode == "1":
|
||||||
|
inverted_im = im.copy()
|
||||||
|
px = inverted_im.load()
|
||||||
|
for y in range(inverted_im.height):
|
||||||
|
for x in range(inverted_im.width):
|
||||||
|
px[x, y] = 0 if px[x, y] == 255 else 255
|
||||||
|
im = inverted_im
|
||||||
|
else:
|
||||||
|
im = ImageOps.invert(im)
|
||||||
|
|
||||||
if im.mode in ["P", "PA"]:
|
if im.mode in ["P", "PA"]:
|
||||||
lut = im.im.getpalette("RGB", "RGB;L")
|
lut = im.im.getpalette("RGB", "RGB;L")
|
||||||
|
@ -1605,8 +1618,8 @@ def _save(im, fp, filename):
|
||||||
ifd.setdefault(tag, value)
|
ifd.setdefault(tag, value)
|
||||||
|
|
||||||
if libtiff:
|
if libtiff:
|
||||||
if "quality" in im.encoderinfo:
|
if "quality" in encoderinfo:
|
||||||
quality = im.encoderinfo["quality"]
|
quality = encoderinfo["quality"]
|
||||||
if not isinstance(quality, int) or quality < 0 or quality > 100:
|
if not isinstance(quality, int) or quality < 0 or quality > 100:
|
||||||
raise ValueError("Invalid quality setting")
|
raise ValueError("Invalid quality setting")
|
||||||
if compression != "jpeg":
|
if compression != "jpeg":
|
||||||
|
@ -1695,7 +1708,7 @@ def _save(im, fp, filename):
|
||||||
tags = list(atts.items())
|
tags = list(atts.items())
|
||||||
tags.sort()
|
tags.sort()
|
||||||
a = (rawmode, compression, _fp, filename, tags, types)
|
a = (rawmode, compression, _fp, filename, tags, types)
|
||||||
e = Image._getencoder(im.mode, "libtiff", a, im.encoderconfig)
|
e = Image._getencoder(im.mode, "libtiff", a, encoderconfig)
|
||||||
e.setimage(im.im, (0, 0) + im.size)
|
e.setimage(im.im, (0, 0) + im.size)
|
||||||
while True:
|
while True:
|
||||||
# undone, change to self.decodermaxblock:
|
# undone, change to self.decodermaxblock:
|
||||||
|
@ -1715,7 +1728,7 @@ def _save(im, fp, filename):
|
||||||
)
|
)
|
||||||
|
|
||||||
# -- helper for multi-page save --
|
# -- helper for multi-page save --
|
||||||
if "_debug_multipage" in im.encoderinfo:
|
if "_debug_multipage" in encoderinfo:
|
||||||
# just to access o32 and o16 (using correct byte order)
|
# just to access o32 and o16 (using correct byte order)
|
||||||
im._debug_multipage = ifd
|
im._debug_multipage = ifd
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user