rawspeed icon indicating copy to clipboard operation
rawspeed copied to clipboard

LJpegDecompressor predictor mode 6 support

Open LebedevRI opened this issue 5 years ago • 11 comments

Comes up in Blackmagic cameras, Magic Lantern DNG's.

./Blackmagic/Pocket Cinema Camera/Blackmagic_Pocket_Cinema_Camera_1_2016-09-17_0053_C0022_000007.dng failed: ../src/librawspeed/decompressors/AbstractDngDecompressor.cpp:208: void rawspeed::AbstractDngDecompressor::decompress() const: Too many errors encountered. Giving up. First Error:
../src/librawspeed/decompressors/LJpegDecompressor.cpp:88: virtual void rawspeed::LJpegDecompressor::decodeScan(): Unsupported predictor mode: 6
./Blackmagic/URSA 4K/Blackmagic URSA_1_1999-12-31_2153_C0003_000001.dng failed: ../src/librawspeed/decompressors/AbstractDngDecompressor.cpp:208: void rawspeed::AbstractDngDecompressor::decompress() const: Too many errors encountered. Giving up. First Error:
../src/librawspeed/decompressors/LJpegDecompressor.cpp:88: virtual void rawspeed::LJpegDecompressor::decodeScan(): Unsupported predictor mode: 6
./Canon/EOS 5D Mark III/compress.dng failed: ../src/librawspeed/decompressors/AbstractDngDecompressor.cpp:208: void rawspeed::AbstractDngDecompressor::decompress() const: Too many errors encountered. Giving up. First Error:
../src/librawspeed/decompressors/LJpegDecompressor.cpp:88: virtual void rawspeed::LJpegDecompressor::decodeScan(): Unsupported predictor mode: 6
./Canon/EOS 60D/M14-1451_000085_cDNG_compressed.dng failed: ../src/librawspeed/decompressors/AbstractDngDecompressor.cpp:208: void rawspeed::AbstractDngDecompressor::decompress() const: Too many errors encountered. Giving up. First Error:
../src/librawspeed/decompressors/LJpegDecompressor.cpp:88: virtual void rawspeed::LJpegDecompressor::decodeScan(): Unsupported predictor mode: 6

LebedevRI avatar Jun 30 '19 14:06 LebedevRI

Even w/ the predictor implemented, there is still some way to go - seems to be the BlackMagick TIFF tile tags vs LJpeg SOF3 frame geometry is a bit wonky/unexpected compared to "normal" CFA lossless DNGs?

[rawspeed] (Blackmagic - URSA 4K - 12bit (16_9).dng) C:/msys64/home/kmilos/darktable/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.cpp:217: void rawspeed::AbstractDngDecompressor::decompress() const: Too many errors encountered. Giving up. First Error:
C:/msys64/home/kmilos/darktable/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.cpp:112: virtual void rawspeed::LJpegDecompressor::decodeScan(): LJpeg frame (1008, 1096) is smaller than expected (504, 2192)

kmilos avatar Dec 30 '21 21:12 kmilos

Yep, unlike Adobe's "normal" lossless mode that has an SOF3 w/ H x W/2 x 2ch and matching TIFF tiles of H x W after reshaping, the Blackmagic SOF3 in the URSA 4K really is FF D8 FF C3 00 0B 0C 04 48 03 F0 01 00 11 00, i.e. 1096 x 1008 x 1ch, while the TIFF tags are

Exif.Image.TileWidth                          504
Exif.Image.TileLength                         2192

Not sure which one of them is wrong and how to reshape, could be that it is H/2 x 2W x 1 -> H x W? In any case this test/assumption breaks.

kmilos avatar Jan 03 '22 09:01 kmilos

Did a quick test of manually changing the TIFF tags, and the results is not good (output image is sliced up incorrectly), so it really does seem the "special" reshaping needs to be done at the SOF3 decoding stage.

kmilos avatar Jan 03 '22 09:01 kmilos

Yay, more Ljpeg fun - predictor 6 just popped up in DJI Mavic 3 Pro DNGs as well...

TileWidth                       : 4000
TileLength                      : 3000

w/

SOF3 (8000x1500): FF C3 00 0B 10 05 DC 1F 40 01 00 11 00 SOS: FF DA 00 08 01 00 00 06 00 00

Edit: This is the same 2W x H/2 scatter/gather as Blackmagic.

kmilos avatar Jun 09 '23 15:06 kmilos

While the Sony ARW case was somewhat straightforward (we know a priori how to reshape the TIFF tiles, decompress, and then deinterleave back because it is the sole ARW lossless mode), it is not so for these Blackmagic/DJI/MLV CinemaDNGs - the tiling in the DngDecoder is done before any LJpeg parsing, and there is no other way to tell one needs the tile reshaping and subsequent deinterleaving compared to "traditional" DNGs.

So the ideal flow after refactoring should be:

  1. Parse LJpeg SOF3 first to get frame.h, frame.w, and frame.cps
  2. Ensure that frame.cps * frame.w * frame.h == tilew * tileh (* spp?)
  3. DngDecoder reshapes tilew = frame.cps * frame.w (/spp?), tileh = frame.h
  4. Only then get DngTilingDescription
  5. Decompress
  6. Deinterleave if reshaped previously

Right now, the DNG tiling (coming first) and LJpeg parsing are completely independent.

kmilos avatar Jun 17 '23 14:06 kmilos

Apologies if i have asked this before, but do we have example DNG's with predictor=0, with such an LJpeg structure (that requires reshaping)?

LebedevRI avatar Jun 18 '23 00:06 LebedevRI

predictor=0 is not really valid/supported, did you mean 6? If so, then, yes, we do have several samples on RPU.

Please also note that I have updated the diagram - I now believe the reshaping and deinterleaving works out to be the same as the Sony case, despite the MCU difference.

kmilos avatar Jun 18 '23 07:06 kmilos

predictor=0 is not really valid/supported, did you mean 6? If so, then, yes, we do have several samples on RPU.

Err, i meant whatever we currently already support, i.e. predictor=1.

LebedevRI avatar Jun 18 '23 14:06 LebedevRI

i meant whatever we currently already support, i.e. predictor=1

The known predictor=1 files (at least to me) are:

  • Adobe lossless DNGs (MCU has 2 components, and we already support tilew = 2 * frame.w "reshaping" so to speak)
  • various LinerRaw DNGs (trivial, as many components as color planes, no reshaping needed)
  • now Sony ARWs (MCU has 4 components, we reshape to tilew*2 x tileh/2, then deinterlace)

All others seem to require either predictor 6 or 7 supported AFAIK...

So, chicken and egg it would seem ;) As mentioned above - I have managed to decompress successfully w/ my "dumb" predictor patch (and by fudging the tiles in TIFF metadata manually), but the image comes out interlaced of course.

kmilos avatar Jun 18 '23 16:06 kmilos

@LebedevRI Note that the TIFF tile <-> JPEG SOF reshaping takes place for the lossy DNG mode as well, so ljpeg is probably not the place to address that in the abstraction hierarchy.

This is from the Blackmagic Pocket Cinema Camera 4K 3:1 lossy DNG:

TileWidth                       : 1032
TileLength                      : 2176

w/ SOF1 (lossy 2064x1088): FF C1 00 0B 0C 04 40 08 10 01 01 11 00 SOS: FF DA 00 08 01 01 00 00 3F 00

kmilos avatar Feb 26 '24 10:02 kmilos

Ah, turns out the reshaping for Blackmagic is even simpler than I thought: it's still 2W x H/2, but instead of flattening 2x2 pixel CFA macroblock into 4x1, it is just deinterleaving entire 2 rows, so one just needs to decode it into an appropriate buffer and it's done! I updated the diagram accordingly.

kmilos avatar Feb 27 '24 10:02 kmilos