Search code examples
cjpeg

JPEG category encode bitwise operation


In the Cryx note about JPEG compression, categories are described as "the minimum size in bits in which we can keep that value". It goes on to say that values falling within certain ranges are put into categories. I have pasted a segment below but not the whole table.

     Values             Category        Bits for the value

    0                   0                   -

      -1,1                  1                  0,1

   -3,-2,2,3                2              00,01,10,11

 -7,-6,-5,-4,4,5,6,7            3    000,001,010,011,100,101,110,111 

The JPEG encoder/decoder found here performs the category encoding with a bitwise operation that I don't understand and I am hoping someone can clarify for me. RLE of 0's is done elsewhere, but this portion of the code breaks up the remaining pixel values into the categories as specified in the Cryx document.

In the code below, the variable code is the value of the YUV value of the pixel. In the while loop, if the conditions are met, i is decremented until the correct category is reached. For example, if the pixel value is 6.0, starting from category 15, i is decremented until 3 is reached. This is done with a bitwise operation that I do not understand. Can someone please clarify what condition is being tested for in the while loop? More specifically, !(absc & mask) is a Boolean, but I don't understand how this helps us to know the correct category.

The reason for the last if statement is also unclear to me. Thanks

    unsigned absc = abs(*code);
    unsigned mask = (1 << 15);
    int i    = 15;
    if (absc == 0) { *size = 0; return; }
    while (i && !(absc & mask)) { mask >>= 1; i--; }
    *size = i + 1;
    if (*code < 0) *code = (1 << *size) - absc - 1;

Solution

  • while here is used to find the most significant bit in code. Or in other words - length of code in bits.

    The loop consequently applies mask to get next bit in code. First, mask is 1000000000000000 in binary form with 1 in 15th bit (zero based), the most valued bit in 2-byte (16 bit) number. Operator & (binary AND) zeros all bits in absc except one with 1 in mask. If result is zero than shift mask right (remove last binary digit) and repeat with next bit.

    For value 6 = 110b (binary form) while will work till mask = 100b and i = 2. After it size will be set to 3.

    If code was negative than the last line will convert it in one’s compliment representation with size length. Such encoding of negative numbers is described in your categories list.