[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