Repository navigation
Reading and converting 16-bit pixels #452
Description
Activity
That image isn't coming up as a signed tiff for me. I'm seeing a SampleFormat of 1, not 2. If you look at the tiff spec, http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf page 80, the SampleFormat tag can take one of 4 values:
1 = unsigned integer data 2 = two’s complement signed integer data 3 = IEEE floating point data [IEEE] 4 = undefined data formatWe do read the sample format tag and act on it -- the values are in PIL/TiffImagePlugin.py around line 140. If this had a sample format of 2, we'd be getting this line: (MM, 1, 2, 1, (16,), ()): ("I;16BS", "I;16BS"), where currently we're getting: (MM, 1, 1, 1, (16,), ()): ("I;16B", "I;16B"),
*** Summary *** - compression: raw - photometric_interpretation: 1 - planar_configuration: 1 - fill_order: 1 - size: (64, 64) format key: ('MM', 1, 1, 1, (16,), ()) - raw mode: I;16B - pil mode: I;16B tiles: [('raw', (0, 0, 64, 64), 3089, ('I;16B', 0, 1))]Imagemagick agrees:
(vpy27)erics:~/16bit$ identify -verbose pil_pillow_16_bit_bug.tif Image: pil_pillow_16_bit_bug.tif Format: TIFF (Tagged Image File Format) Class: DirectClass Geometry: 64x64+0+0 Resolution: 72x72 Print size: 0.888889x0.888889 Units: PixelsPerInch Type: Grayscale Base type: Grayscale Endianess: MSB Colorspace: RGB Depth: 16-bit Channel depth: gray: 16-bit Channel statistics: Gray: min: 32768 (0.500008) max: 32771 (0.500053) mean: 32769.5 (0.500031) standard deviation: 0.949615 (1.44902e-05) kurtosis: 389103 skewness: -3.10189 Histogram: 846: (32768,32768,32768) #800080008000 rgb(50.0008%,50.0008%,50.0008%) 807: (32769,32769,32769) #800180018001 rgb(50.0023%,50.0023%,50.0023%) 1954: (32770,32770,32770) #800280028002 rgb(50.0038%,50.0038%,50.0038%) 489: (32771,32771,32771) #800380038003 rgb(50.0053%,50.0053%,50.0053%) Rendering intent: Undefined Interlace: None Background color: white Border color: rgb(223,223,223) Matte color: grey74 Transparent color: black Compose: Over Page geometry: 64x64+0+0 Dispose: Undefined Iterations: 0 Compression: None Orientation: TopLeft Properties: comment: ImageJ=1.48k cf=0 c0=-32768.0 c1=1.0 vunit=Gray Value min=32768.0 max=32771.0 date:create: 2013-12-19T08:36:22-08:00 date:modify: 2013-12-19T08:36:22-08:00 signature: b4b86b8ead068a453a9d05af84c2c460e918bade85b48b6b8bf930141ce6815b tiff:endian: msb tiff:photometric: min-is-black tiff:rows-per-strip: 64 Artifacts: verbose: true Tainted: False Filesize: 11.3KBB Number pixels: 4.1KB Pixels per second: 410KB User time: 0.000u Elapsed time: 0:01.010Of course its not coming up as a signed tiff. Its not a signed tiff - your ImageMagick dump, my tiffdump, tiffinfo, and ImageJ are all in complete agreement about that. Its only a signed tiff when read by Image.open(), which is the whole problem and basis for this bug report. The mode is reported correctly as unsigned, but the pixel values are negative!
As far as conversion goes, I would expect the same numerical values as I convert from unsigned 16-bit to unsigned 32-bit, and back to unsigned 16-bit (I;16B -> I -> I;16). This should be true regardless of the numerical range because the first conversion is an up-cast, and the second conversion is a down-cast to the original numeric type. The output above clearly shows that this is not the case.
So PR #416 and #417 are not part of the 2.2.2 release which looked to me happened after their merge into master? From my looking at them (which I did before submitting this report, but maybe not in sufficient detail), they deal with 12-bit tiffs stored as 16-bit, where you wouldn't encounter numerical values high enough to run into signedness bugs. If these were not merged into the 2.2.2 release, and as they are your PRs and you already have the test file in hand, can you quickly check what pixel values get reported for this file using your codebase?
Lastly, tiffdump does not report a SampleFormat tag for this file, so a SampleFormat tag value of 1 (unsigned) is only implied by its absence. Or, did you read the SampleFormat tag from the file? I always considered tiffdump the last word on what tags are present in a tiff file, but at this point I'm ready to consider any possibility.
Finally, in case your branch isn't merged with master at this repo, I installed pillow from your 12-bit-tiff branch like so:
pip uninstall pillow pip install https://github.com/wiredfool/Pillow/archive/12-bit-tiff.zipAnd the output is still exactly the same as above. Are we there yet?
Sorry, I misread your report as the image not showing up as signed. I'll take a closer look.
It looks like the pixel access functions are using int16 and int32 instead of uint*s. Check out #455.
- changed the title
[-]reading and converting 16-bit pixels[/-][+]Reading and converting 16-bit pixels[/+]on Nov 22, 2021
Note no 'S' in mode.
Then,
Two problems: Other than using the extended SampleFormat tag (339, 0x0153), there is no way to store a signed value in a tiff file. The value stored in this image at 0,0 is 32768, and this file has no SampleFormat tag, so only unsigned integers are possible. Instead the value reported is the two's complement of the actual value.
Second problem unrelated to tiff peculiarities, you have an unsigned image mode with a signed pixel value.
Moving on,
This is the correct value.
Even more surprising is when we convert this 32-bit, presumably unsigned image back to unsigned 16 bit:
???. Even better, a pixel at 32,16 has a value of 32769:
Correct in the 32-bit unsigned image (is it really unsigned, BTW? didn't check), but in the 16-bit image converted from it, this pixel is still 32767!
In fact, all of the pixels in the converted image are clipped to 32767. In the image as-read, this value is -32767 (two's complement of 32769):
Does the problem originate from the fact that we went over the signed 16-bit max even though we were supposed to be dealing with unsigned values? Is the convert problem related to the tiff reader problem?
Sample file for the above: pil_pillow_16_bit_bug.tif