[Image-SIG] problem with PIL's Image.save() on TIFFs
Florian Höch
lists+Image_SIG at hoech.org
Fri Feb 29 12:21:02 CET 2008
Hello Guy,
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:
577,578c577,578
< xdpi = getscalar(X_RESOLUTION, (1, 1))
< ydpi = getscalar(Y_RESOLUTION, (1, 1))
---
> xres = getscalar(X_RESOLUTION, (1, 1))
> yres = getscalar(Y_RESOLUTION, (1, 1))
580,583c580,589
< if xdpi and ydpi and getscalar(RESOLUTION_UNIT, 1) == 1:
< xdpi = xdpi[0] / (xdpi[1] or 1)
< ydpi = ydpi[0] / (ydpi[1] or 1)
< self.info["dpi"] = xdpi, ydpi
---
> if xres and yres:
> xres = xres[0] / (xres[1] or 1)
> yres = yres[0] / (yres[1] 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
that may
have a non-square aspect ratio, but no meaningful absolute dimensions.
> self.info["resolution"] = xres, yres
721c727
< 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
yourimage.info["resolution"].
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.
Regards,
Florian
Guy K. Kloss schrieb:
> Hi,
>
> 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.
>
> Guy
More information about the Image-SIG
mailing list