views:

501

answers:

2

I'm writing a C++ program to convert a BMP image into a JPEG.

Here's the basic algorithm I'm trying to follow:

  1. Convert RGB color space to Y,Cb,Cr..
  2. Down sample Cb and Cr by 2 (that means for each square block of 2*2 there is 4 different Y value but 1 Cb and 1 Cr value
  3. Apply DCT to data units of each 8*8 pixels...
  4. Then apply quantization on DCT coefficient by using standard quantization table of Cb and Cr.
  5. Do zigzag ordering.
  6. Encode the DC and AC coefficient separately using huffman encoding.
  7. Write proper header and write huffman encoded value to the file...

I've verified that I'm doing the above correctly but I'm still having the following issues:

  • The JPEG being generated isn't displayed correctly.
  • I made a small 8*8 24 bit(color depth) bmp file completly filled with color value R=10 B=10 and G=100...all 64 pixels are of same color..
  • The data that I'm getting at every step is as follows...
    • BMP header size of 40
    • size of header 40
    • width 8
    • height 8
    • no of planes 1
    • no of bits per pixel 24
    • image size 194
    • x resolution pixel per meter 2834
    • y resolution pixel per meter 2834
    • no of colors 0
    • no of imp colors 0
    • The Y Cb Cr conversion of (R,B,G)=(10,10,100) is (62,-29,-37)

So let's consider Y component first.

The DCT coefficient for Y component is :

 495 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0

After Quantization, the zig zag ordering of single data unit that I'm getting is this, for the Y component.

30 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0

Now the Huffman coding of above zig zag order array is :

  • Y dc coding: 00111110
  • Y ac coding: 1010 (for ac huffman table(luminance Y) EOB value is 1010)
  • Similary huffman coding of Cb and Cr components is as follows:
  • cb dc coding: 11000010
  • cb ac coding: 01 (for ac huffman table(chrominance Cb,Cr) EOB value is 01)
  • cr dc coding: 110101110
  • cr ac coding: 01
  • The final Huffman code that I get is:

    001111101010110000100111010111001 Length 33

so to make it divisible by 8, padding of 1 is done.

0011111010101100001001110101110011111111 Length 40.

Here each single 0 or 1 is actually a bit that needs to be stored as it is in the JPEG file but since we can't write bit by bit into file, a total of 8 bits are taken and converted into a integer value in base 10 and stored into a 1-byte character.

Can anyone offer any suggestions about where I'm going wrong?

+1  A: 

The first thing to do to solve your problem is to get the Pennebaker/Mitchel book on the JPEG standard.

The order of operations is:

1) Colorspace conversion 2) FDCT 3) Quantize 4) Zigzag reorder 5) Huffman encode

Those operations have many complexities because of the many rules you must follow.

a) Are you handling the DC predictors properly? b) Are you encoding the A/C components properly w.r.t. the runs of zeros? c) Are you respecting the output stream rule about "padded zeros" and markers? d) Is your colorspace conversion formula correct? Does it include the 0x80 which must be subtracted from each of the components? e) Are you encoding the MCU blocks in the proper order based on your choice of subsampling option?

BitBank
+1  A: 

Don't reinvent the wheel. Use ImageMagick, Magick++, or CImg to accomplish this.

Michael Aaron Safyan