ImpulseAdventure / JPEGsnoop

JPEGsnoop: JPEG decoder and detailed analysis
http://www.impulseadventure.com/photo/jpeg-snoop.html
GNU General Public License v2.0
519 stars 86 forks source link

Lossless JPEG #21

Open ImpulseAdventure opened 7 years ago

ImpulseAdventure commented 7 years ago

Decode lossless JPEG files

[2010/10/16] First created at https://sourceforge.net/p/jpegsnoop/feature-requests/24/

MarcusJohnson91 commented 4 years ago

I'm trying to understand how the DHT table is composed for Lossless JPEG, it'd be great if you could add support for the SOS header in SOF3 mode

Here is a sample image I'm using: https://www.dropbox.com/s/2vxl1h6wmo97lse/Lossless.jpg?dl=0

lclevy commented 4 years ago

https://github.com/lclevy/libcraw2/blob/master/docs/cr2_lossless.pdf

ImpulseAdventure commented 4 years ago

Thank you Laurent -- that is an excellent summary you created.

MarcusJohnson91 commented 4 years ago

I'm not understanding how a code is mapped to a pixel value?

from the image I posted earlier, the Huffman table is: 2[4, 5, 6] 4[2, 3, 7] 5[0] 6[1] 7[8] 8[A] 9[9] 10[B] 11[C]

where the number outside of the brackets is the number of bits, and the number(s) inside the brackets are the values.

how do I find out which pixel 11[C] maps to?

11[C] would be what binary string, and what would that binary string map to pixel wise?

ImpulseAdventure commented 4 years ago

Hello Marcus!

First, I must caveat this by saying that I have not spent much time decoding lossless JPEG images in detail, but perhaps this may help you get started with your question.

Unlike BMP-formatted images, a singular JPEG Huffman code doesn't directly map to a pixel value. I would recommend starting with a read through my JPEG Huffman coding tutorial first, as the differential coding scheme is covered in moderate detail with a simple two-block example. You will find that each Huffman code basically describes the "change in value" from a previous block or predicted block.

More specific to your question: Your Huffman code "11[C]" is mapped as follows (according to JPEGsnoop with DHT Expand option enabled):

     Codes of length 11 bits:
      11111111110 = 0C                   (Total Len = 23)

Once you encounter the bit sequence 11111111110 during decode, the next 12 bits will represent a signed "difference" value. In lossy compression modes, this difference value would typically describe the change in the luminance (since you have a single-channel image) for the DC coefficient versus the previous "block" or the change in an AC frequency coefficient. Thus one doesn't really convert a single coefficient (or huffman code) into a "pixel value". The DC / AC coefficients are based on a frequency-domain representation of your image (see FFT), which is quite removed from the concept of a pixel value.

In the case of lossless JPEG images, the changes are based not on the previous DCT block but a predicted value from neighboring blocks. See https://en.wikipedia.org/wiki/Lossless_JPEG

Hope that helps!