I'm writing a C++ program to convert a BMP image into a JPEG.
Here's the basic algorithm I'm trying to follow:
- Convert RGB color space to Y,Cb,Cr..
- 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
- Apply DCT to data units of each 8*8 pixels...
- Then apply quantization on DCT coefficient by using standard quantization table of Cb and Cr.
- Do zigzag ordering.
- Encode the DC and AC coefficient separately using huffman encoding.
- 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?