-
-
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
TIFFReadScanline: scanline oriented access is not supported for downsampled JPEG compressed images, consider enabling TIFF_JPEGCOLORMODE as JPEGCOLORMODE_RGB #2926
Comments
Fixes: TIFFReadScanline: scanline oriented access is not supported for downsampled JPEG compressed images, consider enabling TIFF_JPEGCOLORMODE as JPEGCOLORMODE_RGB.. Traceback (most recent call last): ... File ".../lib/didjvu.py", line 277, in encode_one image = gamera.load_image(image_filename) File ".../lib/gamera_support.py", line 93, in load_image pil_image = pil_image.convert('RGB') File ".../site-packages/PIL/Image.py", line 877, in convert self.load() File ".../site-packages/PIL/TiffImagePlugin.py", line 1039, in load return self._load_libtiff() File ".../site-packages/PIL/TiffImagePlugin.py", line 1131, in _load_libtiff raise IOError(err) IOError: -2 Work-around for: python-pillow/Pillow#2926
'This used to work until Pillow 4.3.0' - Just to be clear, while this sentence would indicate that 4.3.0 is also problematic, this is not the case, and you are just finding this issue with 5.0.0. |
Indeed, Pillow 4.3.0 was happy with this file. |
There was a change in 5.0 from using the internal JPEG decoder for JPEG encoded TIFFs to the libtiff decoder because the internal decoder was returning incorrect images. (Actually, it's more that we shifted the remaining three internally provided compression modes -- jpeg, packbits, and lzw, because 2 of the 3 were incorrect). Your test file does appear to work on my machine though, which is using libtiff 4.0.8 from homebrew. |
I tested this with |
pillow-wheels was recently updated from libtiff 4.0.8 to 4.0.9: python-pillow/pillow-wheels#70 |
This is reproducible with Pillow-5.0.0-cp36-cp36m-win_amd64, which is also using libtiff 4.0.9. |
I am having this problem in the Loris application when using Pillow 5.0.0 via pip. For now, I think we'll fall back to using Pillow 4.3.0, since I can confirm that my TIFs are being handled correctly in 4.3.0, but it sounds like that might not be the best long-term solution. Does anyone know what the actual technical problem is? A bug in libtiff or something else? |
Is the JPEGColorMode section relevant on https://au.mathworks.com/help/matlab/ref/tiff-class.html?requestedDomain=true#property_d119e1061246? |
So the error says "TIFFReadScanline: scanline oriented access is not supported for downsampled JPEG compressed images, consider enabling TIFF_JPEGCOLORMODE as JPEGCOLORMODE_RGB"... I wondered how one might enable TIFF_JPEGCOLORMODE as JPEGCOLORMODE_RGB... and I saw an example of it at https://github.com/ImageMagick/tiff/blob/master/tools/ppm2tiff.c#L169. This line is also relevant: https://github.com/ImageMagick/tiff/blob/master/tools/ppm2tiff.c#L223 I'm not that familiar with image processing in general or Pillow, but that looks like what we want to be doing in Pillow. So I cloned the ImageMagick/tiff repo and searched for "TIFFTAG_JPEGCOLORMODE" and found it to correspond to the integer 65538. I used https://pillow.readthedocs.io/en/latest/reference/TiffTags.html to dump all the Tiff Tags that Pillow knows about... and didn't find the integer 65538. I don't know if that means that Pillow can't use it... or if it's just not in that dictionary. But this all seems relevant... |
Looking again at the ImageMagick code... I can see that the constant JPEGCOLORMODE_RGB is 0x0001. So I'm going to see if I can just go ahead and set that with the "tag" method... |
Hmm I can't even use the "save" method for my TIFF anyway... |
According to http://maptools-org.996276.n3.nabble.com/JPEG-compressed-RGB-tiled-TIFF-with-chroma-subsampling-td14062.html and the ImageMagick code, I might need to set TIFFTAG_PHOTOMETRIC to PHOTOMETRIC_YCBCR which means... TIFFTAG_PHOTOMETRIC is 262 (otherwise known as PhotometricInterpretation in Pillow) Hmm... It looks like tag 262 is already set to 6... damn. |
I'm guessing @wiredfool might be able to take it from here based on the work on #344 and #291 It looks like libtiff is aware of the 65538 tag... https://github.com/vadz/libtiff/blob/master/libtiff/tiff.h |
Ah this is interesting... it's not a tag but a pseudo tag... https://github.com/vadz/libtiff/blob/master/libtiff/tiff.h#L538 |
So I'm able to use Image.open() to open my TIFF but then I try to save it and I get the following: TIFFReadScanline: scanline oriented access is not supported for downsampled JPEG compressed images, consider enabling TIFF_JPEGCOLORMODE as JPEGCOLORMODE_RGB.. It looks like the error is being generated by a decoder... which is using some IO object of some kind... I don't know why we didn't get this error during Image.open() but whatever. Ignoring that for now. I see the decoder here: decoder = Image._getdecoder(self.mode, 'libtiff', tuple(args), Not really seeing anything about decoderconfig in the code... but I reckon that might be useful. Because me setting those pseudo-tags where I am is probably doing nothing I imagine. In the case of ImageMagick, they're setting those for their new TIFF that they're going to write out to... whereas we have an existing TIFF that we need to read... but we need to set these pseudocodes before it can properly read it I think? |
Ahh reading through Image.py and I'm seeing that Image.open is a lazy method, which is probably why I don't get an error... Ah yup. When I do a im.rotate(45), now I get the error as it's actually trying to decode the TIFF... |
I'm guessing that we might need to update "src/libImaging/TiffDecode.c"? I'd say probably using ImagingLibTiffSetField to set the tags mentioned above around https://github.com/python-pillow/Pillow/blob/master/src/libImaging/TiffDecode.c#L220? I think the error is being generated at https://github.com/python-pillow/Pillow/blob/master/src/libImaging/TiffDecode.c#L238, so I think that's a reasonable suggestion. |
Everything I'm seeing in the ImageMagick code seems to suggest this, so I'm thinking that this is probably the right direction. I'm tempted to write a patch myself. I was going to leave it for you folk in the project, but I think I have a VM that I probably could use to test this on... |
Ok harder than anticipated finding the right spot... but I know I'm calling the decoder here at least:
|
Wow... I think I may have done it. I need to add some more if statements but... I was able to load the TIFF without getting that error. |
Hmm so I could use the load() method but using the save() method generated an error: Encoding line bt lineTIFFScanlineSize64: Invalid YCbCr subsampling. Might just need the same bit of code for the encoder as the decoder though... |
So enabling TIFF_JPEGCOLORMODE as JPEGCOLORMODE_RGB did prevent the fatal error from occuring. However, when I run "pilconvert.py -r old.tif tmp.png", I wind up with a PNG file which has some horrifically bad colours. It went from a black background with a brown/white foreground to a green background with a fuchsia foreground. Same goes when outputting to a jpeg instead of a png. |
By setting the TIFF_JPEGCOLORMODE to JPEGCOLORMODE_RGB, I think we go down this branch: https://github.com/leapmotion/FreeImage/blob/master/Source/LibTIFF4/tif_jpeg.c#L1131 "pilconvert.py old.tif tmp.png" gives this error: "pilconvert.py -g old.tif tmp.jpg" looks pretty good... "pilconvert.py -p old.tif tmp.png" looks bad.. the same as -r Hoping that it was just pilconvert.py... I just tried it in Loris and it looks bad there too. |
For what it's worth, I'm on Ubuntu 16.04.03 and using libtiff5 version 4.0.6-1ubuntu0.2... |
So comparing Pillow 5.1.0.dev0 against Pillow 4.3.0... Both are handling grayscale fine for transforming TIFF to other formats. But converting the TIFF to color JPEG/PNG isn't working for Pillow 5.1.0.dev0 (with my modifications) but it's working perfectly for Pillow 4.3.0... I'm thinking there is something I must be missing in the conversion process somewhere... possibly on the JPEG/PNG end since the grayscale is fine so it looks like the TIFF is being read correctly? |
Ok this is interesting... look at https://en.wikipedia.org/wiki/YCbCr "A color image and its Y, CB and CR components. The Y image is essentially a greyscale copy of the main image." The Y image is a perfect greyscale version. The CR version looks like green in the background and fuchsia in the foreground... pretty much exactly what I'm seeing when converting to JPEG/PNG. The original error message is coming from https://github.com/leapmotion/FreeImage/blob/master/Source/LibTIFF4/tif_jpeg.c#L1299, so maybe the issue is in tif_jpeg.c? |
I've commented on http://bugzilla.maptools.org/show_bug.cgi?id=2140. I should get my code sample up so that others can review it... |
Ok there you go: I followed these instructions for the most part: Basically I installed all the external libraries, uninstalled Pillow with "pip uninstall Pillow" and then installed my Git version using "pip install ./Pillow". It was easy. |
That maptools bug is 8 years old, and very likely not directly related to this. There were several cases where YCbCr images were being returned as RGB from Pillow's internal jpeg decoder in 4.3.0, and switching to the libtiff decoder fixed them, but broke a different subset. I think what's happening here is that you're telling libjpeg to use RGB mode for JPEGs, regardless of the actual encoding of the image. |
Looking back, I realise that I forgot to say that I thought the libtiff/maptools bug wasn't directly related, but interesting that the same error message has been around so long. Mmm, that sounds like a plausible explanation, but according to https://github.com/leapmotion/FreeImage/blob/master/Source/LibTIFF4/tif_jpeg.c#L1132 it should be converting YCbCr to RGB. I suppose I haven't looked to make sure it is following that branch though... |
It looks like the TIFFs where I've encountered errors are test data and our project shouldn't involve any TIFFs containing JPEGs, so I might not end up having to worry about this in practice... but I admit that this bug really has me curious and has got me intrigued in image processing... |
Is there a solution to this problem? I'm just trying to load the TIF via skimage.io.imread. |
This is a real issue, but is going to take work in the tiff decoder to fix, or we have to revert the changed that fixed color issues on jpeg encoded tiffs. |
the proposed patch apparently fixes the issue |
Depend on pillow >= 5.3.0 to mitigate python-pillow/Pillow#2926
Pillow 5.0.0 can no longer read JPEG-compressed TIFFs:
(I presume
TIFF_JPEGCOLORMODE
is a typo forTIFFTAG_JPEGCOLORMODE
.)This used to work until Pillow 4.3.0.
The text was updated successfully, but these errors were encountered: