[Image-SIG] problem with PIL's Image.save() on TIFFs
lists+Image_SIG at hoech.org
Fri Feb 29 12:21:02 CET 2008
PIL 1.1.6 still seems to have a bug regarding its interpretation of
TIFFTAG_RESOLUTIONUNIT, which could lead to "strange" values being
written to the TIFF file.
I and Gary Bloom posted fixes to the list awhile ago. For convenience,
here's the diff patch for TiffImagePlugin.py again, containing both mine
(reading) and Gary's (writing) fix:
< xdpi = getscalar(X_RESOLUTION, (1, 1))
< ydpi = getscalar(Y_RESOLUTION, (1, 1))
> xres = getscalar(X_RESOLUTION, (1, 1))
> yres = getscalar(Y_RESOLUTION, (1, 1))
< if xdpi and ydpi and getscalar(RESOLUTION_UNIT, 1) == 1:
< xdpi = xdpi / (xdpi or 1)
< ydpi = ydpi / (ydpi or 1)
< self.info["dpi"] = xdpi, ydpi
> if xres and yres:
> xres = xres / (xres or 1)
> yres = yres / (yres or 1)
> resunit = getscalar(RESOLUTION_UNIT, 1)
> if resunit == 2: # dots per inch
> self.info["dpi"] = xres, yres
> elif resunit == 3: # dots per centimeter. convert to dpi
> self.info["dpi"] = xres * 2.54, yres * 2.54
> else: # No absolute unit of measurement. Used for images
have a non-square aspect ratio, but no meaningful absolute dimensions.
> self.info["resolution"] = xres, yres
< ifd[RESOLUTION_UNIT] = 1
> ifd[RESOLUTION_UNIT] = 2
To explain what the patch does: Without the fix, PIL's interpretation of
RESOLUTION_UNIT is "off by one", e.g. RESOLUTION_UNIT 1 (no absolute
unit of measurement) is treated as RESOLUTION_UNIT 2 (dots per inch).
The patch solves this and also takes into account RESOLUTION_UNIT 3
(dots per centimeters) by converting to dots per inch and setting
info["dpi"] accordingly. In the case of RESOLUTION_UNIT other than 2 or
3, there may be no meaningful resolution set in the image. After
applying the patch, this case can be checked for in your code if needed
with yourimage.info.has_key("dpi") and if that returns False, checking
The fix currently has the small drawback that, if RESOLUTION_UNIT was 3
(dpc) in the input image, when saving the TIFF file the resolution unit
will always be dpi.
Guy K. Kloss schrieb:
> I've just had some problems with PIL's implementation of the Image.save()
> method when writing TIFF files. Apparently some internal tags on resolution
> are totally out of the normal. Using the TIFFs from libtiff later on produces
> some warning on a tag with bad information.
> This is what libtiff's warning handler produces:
> _TIFFVSetField: diag.tif: Bad value 47088 for "ResolutionUnit".
> diag.tif: Warning, "YResolution": Information lost writing value
> (-2.94176e-05) as (unsigned) RATIONAL.
> According to Graeme Gill's information (who implements Argyll CMS, that's
> using libtiff for its purposes)
> [...] According to the TIFF spec, the ResolutionUnit tag can have one of three
> values: (From tiff/libtiff/tiff.h)
> #define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */
> #define RESUNIT_NONE 1 /* no meaningful units */
> #define RESUNIT_INCH 2 /* english */
> #define RESUNIT_CENTIMETER 3 /* metric */
> It seems like the implementation in PIL.Image for save() puts a non standard
> value (here 47088) into the field ResolutionUnit, and there also seems to be
> something funny with the YResolution field in the TIFF file.
> To me this very much sounds like an issue with uninitialised variables in some
> structures, as the values tend to be different on different runs, as well as
> the fact that they're well out of whack indicates this.
More information about the Image-SIG