-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pass IFDs to libtiff as TIFF_LONG8 #8529
base: main
Are you sure you want to change the base?
Conversation
Thanks. It fixes the regression, but it doesn't seem to get IFD right still, at least on PowerPC: ____________________________________________________ TestFileLibTiff.test_exif_ifd ____________________________________________________
self = <Tests.test_file_libtiff.TestFileLibTiff object at 0xf60a0c90>
def test_exif_ifd(self) -> None:
out = io.BytesIO()
with Image.open("Tests/images/tiff_adobe_deflate.tif") as im:
assert im.tag_v2[34665] == 125456
im.save(out, "TIFF")
with Image.open(out) as reloaded:
assert 34665 not in reloaded.tag_v2
> im.save(out, "TIFF", tiffinfo={34665: 125456})
Tests/test_file_libtiff.py:709:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src/PIL/Image.py:2605: in save
save_handler(self, fp, filename)
src/PIL/TiffImagePlugin.py:1954: in _save
encoder = Image._getencoder(im.mode, "libtiff", a, encoderconfig)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
mode = 'RGB', encoder_name = 'libtiff'
args = ('RGB', 'tiff_adobe_deflate', 0, '', [(254, 0), (256, 278), (257, 374), (258, 8), (259, 8), (262, 2), ...], {254: 4, 273: 4, 279: 4, 305: 2, ...})
extra = ()
def _getencoder(
mode: str, encoder_name: str, args: Any, extra: tuple[Any, ...] = ()
) -> core.ImagingEncoder | ImageFile.PyEncoder:
# tweak arguments
if args is None:
args = ()
elif not isinstance(args, tuple):
args = (args,)
try:
encoder = ENCODERS[encoder_name]
except KeyError:
pass
else:
return encoder(mode, *args + extra)
try:
# get encoder
encoder = getattr(core, f"{encoder_name}_encoder")
except AttributeError as e:
msg = f"encoder {encoder_name} not available"
raise OSError(msg) from e
> return encoder(mode, *args + extra)
E RuntimeError: Error setting from dictionary
src/PIL/Image.py:467: RuntimeError
-------------------------------------------------------- Captured stderr call ---------------------------------------------------------
_TIFFVSetField: : Bad LONG8 or IFD8 value 538833550496960 for "EXIFIFDOffset" tag 34665 in ClassicTIFF. Tag won't be written to file. |
Hmm:
So it's still getting some junk? |
Yes, I jumped the gun slightly. I've updated the commit. Please try again. |
Thanks! With this change, all tests pass for me now. |
src/encode.c
Outdated
@@ -959,6 +959,10 @@ PyImaging_LibTiffEncoderNew(PyObject *self, PyObject *args) { | |||
status = ImagingLibTiffSetField( | |||
&encoder->state, (ttag_t)key_int, (FLOAT64)PyFloat_AsDouble(value) | |||
); | |||
} else if (type == TIFF_LONG8) { | |||
status = ImagingLibTiffSetField( | |||
&encoder->state, (ttag_t)key_int, PyLong_AsLongLong(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps the return value of PyLong_AsLongLong(value)
should also be force-casted like (almost) all the others, to make it obvious what type is expected (and make it easier to find wrong modifications of the code in the future).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a commit to cast to uint64_t
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, looks good.
Resolves #8522
#7053 found that "EXIFIFDOffset" tag 34665 was being unexpectedly treated as a TIFF_LONG8 by libtiff. To fix this, it cast many TIFF_LONGs to 64-bits.
This reverts that change. Instead, I found https://gitlab.com/libtiff/libtiff/-/blob/master/libtiff/tif_dirinfo.c#L152-164 explaining that this is special behaviour for the IFD tags.
This PR passes the EXIF, GPSInfo and Interop IFDs to libtiff as TIFF_LONG8.