diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 19c952ae4..2ddb2263a 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -8,6 +8,7 @@ import io import logging import itertools import os +import distutils.version from PIL import Image, TiffImagePlugin, TiffTags @@ -236,7 +237,15 @@ class TestFileLibTiff(LibTiffTestCase): 37000: 4, 37001: 4.2 } - for libtiff in [False, True]: + + libtiff_version = TiffImagePlugin._libtiff_version() + + libtiffs = [False] + if distutils.version.StrictVersion(libtiff_version) >= \ + distutils.version.StrictVersion("4.0"): + libtiffs.append(True) + + for libtiff in libtiffs: TiffImagePlugin.WRITE_LIBTIFF = libtiff im = hopper() diff --git a/Tests/versions.py b/Tests/versions.py index abc1a3be9..835865b37 100644 --- a/Tests/versions.py +++ b/Tests/versions.py @@ -10,6 +10,7 @@ def version(module, version): version(Image, "jpeglib") version(Image, "zlib") +version(Image, "libtiff") try: from PIL import ImageFont diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index c2b09e294..2b4ddb038 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -54,6 +54,7 @@ import os import struct import sys import warnings +import distutils.version from .TiffTags import TYPES @@ -284,6 +285,10 @@ def _limit_rational(val, max_val): return n_d[::-1] if inv else n_d +def _libtiff_version(): + return Image.core.libtiff_version.split("\n")[0].split("Version ")[1] + + ## # Wrapper for TIFF IFDs. @@ -1501,9 +1506,11 @@ def _save(im, fp, filename): # Libtiff can only process certain core items without adding # them to the custom dictionary. Support has only been been added # for int and float values - if tag not in TiffTags.LIBTIFF_CORE and not \ - (isinstance(value, int) or isinstance(value, float)): - continue + if tag not in TiffTags.LIBTIFF_CORE: + if (distutils.version.StrictVersion(_libtiff_version()) < + distutils.version.StrictVersion("4.0")) \ + or not (isinstance(value, int) or isinstance(value, float)): + continue if tag not in atts and tag not in blocklist: if isinstance(value, str if py3 else unicode): atts[tag] = value.encode('ascii', 'replace') + b"\0" diff --git a/src/_imaging.c b/src/_imaging.c index 474444348..5b8ccb8ad 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -3849,6 +3849,13 @@ setup_module(PyObject* m) { } #endif +#ifdef HAVE_LIBTIFF + { + extern const char * ImagingTiffVersion(void); + PyDict_SetItemString(d, "libtiff_version", PyUnicode_FromString(ImagingTiffVersion())); + } +#endif + PyDict_SetItemString(d, "PILLOW_VERSION", PyUnicode_FromString(version)); return 0; diff --git a/src/libImaging/TiffDecode.c b/src/libImaging/TiffDecode.c index bfab4b79e..64ac86e6a 100644 --- a/src/libImaging/TiffDecode.c +++ b/src/libImaging/TiffDecode.c @@ -406,13 +406,20 @@ int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_typ TIFFSTATE *clientstate = (TIFFSTATE *)state->context; char field_name[10]; uint32 n; + int status = 0; const TIFFFieldInfo info[] = { { key, 0, 1, field_type, FIELD_CUSTOM, 1, 0, field_name } }; n = sizeof(info) / sizeof(info[0]); - return TIFFMergeFieldInfo(clientstate->tiff, info, n); + // Test for libtiff 4.0 or later, excluding libtiff 3.9.6 and 3.9.7 +#if TIFFLIB_VERSION >= 20111221 && TIFFLIB_VERSION != 20120218 && TIFFLIB_VERSION != 20120922 + status = TIFFMergeFieldInfo(clientstate->tiff, info, n); +#else + TIFFMergeFieldInfo(clientstate->tiff, info, n); +#endif + return status; } int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...){ @@ -514,4 +521,11 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int state->errcode = IMAGING_CODEC_END; return 0; } + +const char* +ImagingTiffVersion(void) +{ + return TIFFGetVersion(); +} + #endif