gprconsultants
asked on
Jpeg header in c
I want to save an image file as jpeg file using ansi c.
Can I get the header data structure in c and way to write/ store the jpeg file?
Can I get the header data structure in c and way to write/ store the jpeg file?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> I want to convert bmp file to jpeg.
That's really a different question than what you asked originally, but have a look at the imagemagick library for your image conversion needs :
http://www.imagemagick.org/script/index.php
That's really a different question than what you asked originally, but have a look at the imagemagick library for your image conversion needs :
http://www.imagemagick.org/script/index.php
Kindly refer the below links..It may helpful for you..
http://www.imagemagick.org/script/index.php
http://www.codeguru.com/forum/archive/index.php/t-378333.html
http://www.imagemagick.org/script/index.php
http://www.codeguru.com/forum/archive/index.php/t-378333.html
ASKER
Hello All,
I have written the code for bmp to jpeg image conversion. But not getting the corect resultant image.
I am attaching the image with code here.
I have written the code for bmp to jpeg image conversion. But not getting the corect resultant image.
I am attaching the image with code here.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jtypes.h"
#include "jglobals.h"
#include "jtables.h"
#include <conio.h>
#define N 8
//bitstring bitcode;
int startr,startc;
typedef struct bmpinfo
{
unsigned long size;
long width;
long height;
unsigned short planes;
unsigned short bitcount;
unsigned long compression;
unsigned long imagesize;
long xres;
long yres;
unsigned long colours;
unsigned long impcolors;
} BITMAPINFOHEADER;
#pragma pack(1)
typedef struct bmpfile
{
//unsigned short type;
unsigned long size;
unsigned short reserved1;
unsigned short reserved2;
unsigned long offset;
}BITMAPFILEHEADER;
int R[64][64],B[64][64],G[64][64];
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
unsigned char s=0;
void write_APP0info()
//Nothing to overwrite for APP0info
{
writeword(APP0info.marker);
writeword(APP0info.length);
writebyte('J');
writebyte('F');
writebyte('I');
writebyte('F');
writebyte(0);
writebyte(APP0info.versionhi);
writebyte(APP0info.versionlo);
writebyte(APP0info.xyunits);
writeword(APP0info.xdensity);
writeword(APP0info.ydensity);
writebyte(APP0info.thumbnwidth);
writebyte(APP0info.thumbnheight);
}
void write_SOF0info()
// We should overwrite width and height
{
writeword(SOF0info.marker);
writeword(SOF0info.length);
writebyte(SOF0info.precision);
writeword(SOF0info.height);
writeword(SOF0info.width);
writebyte(SOF0info.nrofcomponents);
writebyte(SOF0info.IdY);
writebyte(SOF0info.HVY);
writebyte(SOF0info.QTY);
writebyte(SOF0info.IdCb);
writebyte(SOF0info.HVCb);
writebyte(SOF0info.QTCb);
writebyte(SOF0info.IdCr);
writebyte(SOF0info.HVCr);
writebyte(SOF0info.QTCr);
}
void write_DQTinfo()
{
BYTE i;
writeword(DQTinfo.marker);
writeword(DQTinfo.length);
writebyte(DQTinfo.QTYinfo);
for (i=0; i<64; i++)
writebyte(DQTinfo.Ytable[i]);
writebyte(DQTinfo.QTCbinfo);
for (i=0; i<64; i++)
writebyte(DQTinfo.Cbtable[i]);
}
void set_quant_table(BYTE *basic_table, BYTE scale_factor, BYTE *newtable)
// Set quantization table and zigzag reorder it
{
BYTE i;
long temp;
for (i=0; i<64; i++)
{
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
// limit the values to the valid range
if (temp <= 0L)
temp = 1L;
if (temp > 255L)
temp = 255L;
newtable[zigzag[i]] = (BYTE) temp;
}
}
void set_DQTinfo()
{
BYTE scalefactor = 50;// scalefactor controls the visual quality of the image
// the smaller is the better image we'll get, and the smaller
// compression we'll achieve
DQTinfo.marker = 0xFFDB;
DQTinfo.length = 132;
DQTinfo.QTYinfo = 0;
DQTinfo.QTCbinfo = 1 ;
set_quant_table(std_luminance_qt, scalefactor, DQTinfo.Ytable);
set_quant_table(std_chrominance_qt, scalefactor, DQTinfo.Cbtable);
}
void write_DHTinfo()
{
BYTE i;
writeword(DHTinfo.marker);
writeword(DHTinfo.length);
writebyte(DHTinfo.HTYDCinfo);
for (i=0; i<16; i++)
writebyte(DHTinfo.YDC_nrcodes[i]);
for (i=0; i<12; i++)
writebyte(DHTinfo.YDC_values[i]);
writebyte(DHTinfo.HTYACinfo);
for (i=0; i<16; i++)
writebyte(DHTinfo.YAC_nrcodes[i]);
for (i=0; i<162; i++)
writebyte(DHTinfo.YAC_values[i]);
writebyte(DHTinfo.HTCbDCinfo);
for (i=0; i<16; i++)
writebyte(DHTinfo.CbDC_nrcodes[i]);
for (i=0; i<12; i++)
writebyte(DHTinfo.CbDC_values[i]);
writebyte(DHTinfo.HTCbACinfo);
for (i=0; i<16; i++)
writebyte(DHTinfo.CbAC_nrcodes[i]);
for (i=0; i<162; i++)
writebyte(DHTinfo.CbAC_values[i]);
}
void set_DHTinfo()
{
BYTE i;
// fill the DHTinfo structure [get the values from the standard Huffman tables]
DHTinfo.marker = 0xFFC4;
DHTinfo.length = 0x01A2;
DHTinfo.HTYDCinfo = 0;
for (i=0; i<16; i++)
DHTinfo.YDC_nrcodes[i] = std_dc_luminance_nrcodes[i+1];
for (i=0; i<12; i++)
DHTinfo.YDC_values[i] = std_dc_luminance_values[i];
DHTinfo.HTYACinfo = 0x10;
for (i=0; i<16; i++)
DHTinfo.YAC_nrcodes[i] = std_ac_luminance_nrcodes[i+1];
for (i=0; i<162; i++)
DHTinfo.YAC_values[i] = std_ac_luminance_values[i];
DHTinfo.HTCbDCinfo = 1;
for (i=0; i<16; i++)
DHTinfo.CbDC_nrcodes[i] = std_dc_chrominance_nrcodes[i+1];
for (i=0; i<12; i++)
DHTinfo.CbDC_values[i] = std_dc_chrominance_values[i];
DHTinfo.HTCbACinfo = 0x11;
for (i=0; i<16; i++)
DHTinfo.CbAC_nrcodes[i] = std_ac_chrominance_nrcodes[i+1];
for (i=0; i<162; i++)
DHTinfo.CbAC_values[i] = std_ac_chrominance_values[i];
}
void write_SOSinfo()
//Nothing to overwrite for SOSinfo
{
writeword(SOSinfo.marker);
writeword(SOSinfo.length);
writebyte(SOSinfo.nrofcomponents);
writebyte(SOSinfo.IdY);
writebyte(SOSinfo.HTY);
writebyte(SOSinfo.IdCb);
writebyte(SOSinfo.HTCb);
writebyte(SOSinfo.IdCr);
writebyte(SOSinfo.HTCr);
writebyte(SOSinfo.Ss);
writebyte(SOSinfo.Se);
writebyte(SOSinfo.Bf);
}
void write_comment(BYTE *comment)
{
WORD i, length;
writeword(0xFFFE); // The COM marker
length = strlen((const char *)comment);
writeword(length + 2);
for (i=0; i<length; i++)
writebyte(comment[i]);
}
void writebits(bitstring bs)
// A portable version; it should be done in assembler
{
long int value;
SBYTE posval;// bit position in the bitstring we read, should be <=15 and >=0
value = bs.value;
posval = bs.length - 1;
while (posval >= 0)
{
if (value & mask[posval])
bytenew |= mask[bytepos];
posval--;
bytepos--;
if (bytepos < 0)
{
// write it
if (bytenew == 0xFF)
{
// special case
writebyte(0xFF);
writebyte(0);
}
else
writebyte(bytenew);
printf(" %hd ",bytenew);
// reinit
bytepos = 7;
bytenew = 0;
}
}
}
void compute_Huffman_table(BYTE *nrcodes, BYTE *std_table, bitstring *HT)
{
BYTE k,j;
BYTE pos_in_table;
WORD codevalue;
codevalue = 0;
pos_in_table = 0;
for (k=1; k<=16; k++)
{
for (j=1; j<=nrcodes[k]; j++)
{
HT[std_table[pos_in_table]].value = codevalue;
HT[std_table[pos_in_table]].length = k;
pos_in_table++;
codevalue++;
}
codevalue <<= 1;
}
}
void init_Huffman_tables()
{
// Compute the Huffman tables used for encoding
compute_Huffman_table(std_dc_luminance_nrcodes, std_dc_luminance_values, YDC_HT);
compute_Huffman_table(std_ac_luminance_nrcodes, std_ac_luminance_values, YAC_HT);
compute_Huffman_table(std_dc_chrominance_nrcodes, std_dc_chrominance_values, CbDC_HT);
compute_Huffman_table(std_ac_chrominance_nrcodes, std_ac_chrominance_values, CbAC_HT);
}
void exitmessage(char *error_message)
{
printf("%s\n",error_message);
exit(EXIT_FAILURE);
}
int find_cat(long int num)
{
if(num==0) return 0;
if(num ==-1 || num==1)
return 1;
if((num >=-3 && num<=-2)||(num>=2 && num<=3))
return 2;
if((num >=-7 && num<=-4)||(num>=4 && num<=7))
return 3;
if((num >=-15 && num<=-8)||(num>=8 && num<=15))
return 4;
if((num >=-31 && num<=-16)||(num>=16 && num<=31))
return 5;
if((num >=-63 && num<=-32)||(num>=32 && num<=63))
return 6;
if((num >=-127 && num<=-64)||(num>=64 && num<=127))
return 7;
if((num >=-255 && num<=-128)||(num>=128 && num<=255))
return 8;
if((num >=-511 && num<=-256)||(num>=256 && num<=511))
return 9;
if((num >=-1023 && num<=-512)||(num>=512 && num<=1032))
return 10;
if((num >=-2047 && num<=-1024)||(num>=1024 && num<=2047))
return 11;
if((num >=-4095 && num<=-2048)||(num>=2048 && num<=4095))
return 12;
if((num >=-8191 && num<=-4096)||(num>=4096 && num<=8191))
return 13;
if((num >=-16383 && num<=-8192)||(num>=8192 && num<=16383))
return 14;
if((num >=-32767 && num<=-16384)||(num>=16384 && num<=32767))
return 15;
}
long int nrupper(long int num)
{ int ch1=find_cat(num);
if(ch1==1)
return 2;
if(ch1==2)
return 4;
if(ch1==3)
return 8;
if(ch1==4)
return 16;
if(ch1==5)
return 32;
if(ch1==6)
return 64;
if(ch1==7)
return 128;
if(ch1==8)
return 256;
if(ch1==9)
return 512;
if(ch1==10)
return 1024;
if(ch1==11)
return 2048;
if(ch1==12)
return 4096;
if(ch1==13)
return 8192;
if(ch1==14)
return 16384;
if(ch1==15)
return 32768;
}
void find_value(double num)
{ bitstring bs2;
bs2.length=find_cat(num);
if(num>0)
{
bs2.value=(WORD)num;
// if(find_cat(num)==4 && s==1)
// printf("\n num=%ld result=%ld ",(long int)num,(long int)bs2.value);
}
else
{
bs2.value=(WORD)(nrupper(num)-1+num);
// if(find_cat(num)==4 && s==1)
// printf("\n num=%ld result=%ld",(long int)num,(long int)bs2.value);
}
writebits(bs2);
}
void set_numbers_category_and_bitcode()
{
/* SDWORD nr;
SDWORD nrlower, nrupper;
BYTE cat;
*/
/* category_alloc = (BYTE *)malloc(4096*sizeof(BYTE));
if (category_alloc == NULL)
exitmessage("Not enough memory.");
else
{ printf("\n allocated 8192");
// exit(0);
}*/
//allow negative subscripts
// category = category_alloc + 2048;
/* bitcode_alloc=(bitstring *)malloc(4096*sizeof(bitstring));
if (bitcode_alloc==NULL)
exitmessage("Not enough memory.");
bitcode = bitcode_alloc + 2048;
nrlower = 1;
nrupper = 2;
for (cat=1; cat<=11; cat++)
{
//Positive numbers
for (nr=nrlower; nr<nrupper; nr++)
{
//category[nr] = cat;
bitcode[nr].length = cat;
bitcode[nr].value = (WORD)nr;
}
//Negative numbers
for (nr=-(nrupper-1); nr<=-nrlower; nr++)
{
category[nr] = cat;
bitcode[nr].length = cat;
bitcode[nr].value = (WORD)(nrupper-1+nr);
}
nrlower <<= 1;
nrupper <<= 1;
} */
}
void precalculate_YCbCr_tables()
{
WORD R,G,B;
for (R=0; R<256; R++)
{
YRtab[R] = (SDWORD)(65536*0.299+0.5)*R;
CbRtab[R] = (SDWORD)(65536*-0.16874+0.5)*R;
CrRtab[R] = (SDWORD)(32768)*R;
}
for (G=0; G<256; G++)
{
YGtab[G] = (SDWORD)(65536*0.587+0.5)*G;
CbGtab[G] = (SDWORD)(65536*-0.33126+0.5)*G;
CrGtab[G] = (SDWORD)(65536*-0.41869+0.5)*G;
}
for (B=0; B<256; B++)
{
YBtab[B] = (SDWORD)(65536*0.114+0.5)*B;
CbBtab[B] = (SDWORD)(32768)*B;
CrBtab[B] = (SDWORD)(65536*-0.08131+0.5)*B;
}
}
// Using a bit modified form of the FDCT routine from IJG's C source:
// Forward DCT routine idea taken from Independent JPEG Group's C source for
// JPEG encoders/decoders
/* For float AA&N IDCT method, divisors are equal to quantization
coefficients scaled by scalefactor[row]*scalefactor[col], where
scalefactor[0] = 1
scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
We apply a further scale factor of 8.
What's actually stored is 1/divisor so that the inner loop can
use a multiplication rather than a division. */
void prepare_quant_tables()
{
double aanscalefactor[8] = {1.0, 1.387039845, 1.306562965, 1.175875602,
1.0, 0.785694958, 0.541196100, 0.275899379};
BYTE row, col;
BYTE i = 0;
for (row = 0; row < 8; row++)
{
for (col = 0; col < 8; col++)
{
fdtbl_Y[i] = (float) (1.0 / ((double) DQTinfo.Ytable[zigzag[i]] *
aanscalefactor[row] * aanscalefactor[col] * 8.0));
fdtbl_Cb[i] = (float) (1.0 / ((double) DQTinfo.Cbtable[zigzag[i]] *
aanscalefactor[row] * aanscalefactor[col] * 8.0));
i++;
}
}
}
void fdct_and_quantization(SBYTE *data, float *fdtbl, SWORD *outdata)
{
float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
float tmp10, tmp11, tmp12, tmp13;
float z1, z2, z3, z4, z5, z11, z13;
float *dataptr;
float datafloat[64];
float temp;
SBYTE ctr;
BYTE i;
for (i=0; i<64; i++)
datafloat[i] = data[i];
/* Pass 1: process rows. */
dataptr = datafloat;
for (ctr = 7; ctr >= 0; ctr--)
{
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
tmp6 = dataptr[1] - dataptr[6];
tmp2 = dataptr[2] + dataptr[5];
tmp5 = dataptr[2] - dataptr[5];
tmp3 = dataptr[3] + dataptr[4];
tmp4 = dataptr[3] - dataptr[4];
/* Even part */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * ((float) 0.707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = (tmp10 - tmp12) * ((float) 0.382683433); /* c6 */
z2 = ((float) 0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = ((float) 1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * ((float) 0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[5] = z13 + z2; /* phase 6 */
dataptr[3] = z13 - z2;
dataptr[1] = z11 + z4;
dataptr[7] = z11 - z4;
dataptr += 8; /* advance pointer to next row */
}
/* Pass 2: process columns. */
dataptr = datafloat;
for (ctr = 7; ctr >= 0; ctr--)
{
tmp0 = dataptr[0] + dataptr[56];
tmp7 = dataptr[0] - dataptr[56];
tmp1 = dataptr[8] + dataptr[48];
tmp6 = dataptr[8] - dataptr[48];
tmp2 = dataptr[16] + dataptr[40];
tmp5 = dataptr[16] - dataptr[40];
tmp3 = dataptr[24] + dataptr[32];
tmp4 = dataptr[24] - dataptr[32];
/* Even part */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[32] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * ((float) 0.707106781); /* c4 */
dataptr[16] = tmp13 + z1; /* phase 5 */
dataptr[48] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = (tmp10 - tmp12) * ((float) 0.382683433); /* c6 */
z2 = ((float) 0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = ((float) 1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * ((float) 0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[40] = z13 + z2; /* phase 6 */
dataptr[24] = z13 - z2;
dataptr[8] = z11 + z4;
dataptr[56] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
/* Quantize/descale the coefficients, and store into output array */
for (i = 0; i < 64; i++)
{
/* Apply the quantization and scaling factor */
temp = datafloat[i] * fdtbl[i];
/* Round to nearest integer.
Since C does not specify the direction of rounding for negative
quotients, we have to force the dividend positive for portability.
The maximum coefficient size is +-16K (for 12-bit data), so this
code should work for either 16-bit or 32-bit ints.
*/
outdata[i] = (SWORD) ((SWORD)(temp + 16384.5) - 16384);
// printf(" %hd ",outdata[i]);
}
}
void process_DU(SBYTE *ComponentDU,float *fdtbl,SWORD *DC,
bitstring *HTDC,bitstring *HTAC)
{
bitstring EOB = HTAC[0x00];
bitstring M16zeroes = HTAC[0xF0];
BYTE i;
BYTE startpos;
BYTE end0pos;
BYTE nrzeroes;
BYTE nrmarker;
SWORD Diff;
fdct_and_quantization(ComponentDU, fdtbl, DU_DCT);
// zigzag reorder
for (i=0; i<64; i++)
DU[zigzag[i]]=DU_DCT[i];
// Encode DC
Diff = DU[0] - *DC;
*DC = DU[0];
if (Diff == 0)
writebits(HTDC[0]); //Diff might be 0
else
{
writebits(HTDC[find_cat(Diff)]);
// writebits(bitcode[Diff]);
find_value(Diff);
}
// Encode ACs
for (end0pos=63; (end0pos>0)&&(DU[end0pos]==0); end0pos--) ;
//end0pos = first element in reverse order != 0
i = 1;
while (i <= end0pos)
{
startpos = i;
for (; (DU[i]==0) && (i<=end0pos); i++) ;
nrzeroes = i - startpos;
if (nrzeroes >= 16)
{
for (nrmarker=1; nrmarker<=nrzeroes/16; nrmarker++)
writebits(M16zeroes);
nrzeroes = nrzeroes%16;
}
writebits(HTAC[nrzeroes*16+find_cat(DU[i])]);
// writebits(bitcode[DU[i]]);
find_value(DU[i]);
i++;
}
if (end0pos != 63)
writebits(EOB);
}
/*void load_data_units_from_RGB_buffer(WORD xpos, WORD ypos)
{
BYTE x, y;
BYTE pos = 0;
DWORD location;
BYTE R, G, B;
location = ypos * width + xpos;
for (y=0; y<8; y++)
{
for (x=0; x<8; x++)
{
R = RGB_buffer[location].R;
G = RGB_buffer[location].G;
B = RGB_buffer[location].B;
// convert to YCbCr
YDU[pos] = Y(R,G,B);
CbDU[pos] = Cb(R,G,B);
CrDU[pos] = Cr(R,G,B);
location++;
pos++;
}
location += width - 8;
}
}
*/
void main_encoder()
{
SWORD DCY = 0, DCCb = 0, DCCr = 0;
int Loop, i,j,l,m,p,q,count,k;
// unsigned char k;
BYTE pos=0; int row,col;
printf("\n read pixel matrix");
for(row=0;row<bmih.height;row+=N)
{
for(col=0;col<bmih.width;col+=N)
{
startr=row;startc=col; pos=0;
for(i=0,l=startr;i<N;i++,l++)
{
for(j=0,k=startc;j<N;j++,k++)
{
YDU[pos]=(SBYTE)R[l][k];
CbDU[pos]=(SBYTE)G[l][k];
CrDU[pos]=(SBYTE)B[l][k];
pos++;
}
}
process_DU(YDU, fdtbl_Y, &DCY, YDC_HT, YAC_HT);
process_DU(CbDU, fdtbl_Cb, &DCCb, CbDC_HT, CbAC_HT);
process_DU(CrDU, fdtbl_Cb, &DCCr, CbDC_HT, CbAC_HT);
}
}
printf("\n Processed and written data successfully");
/*for (ypos=0; ypos<height; ypos+=8)
{
for (xpos=0; xpos<width; xpos+=8)
{
load_data_units_from_RGB_buffer(xpos, ypos);
process_DU(YDU, fdtbl_Y, &DCY, YDC_HT, YAC_HT);
process_DU(CbDU, fdtbl_Cb, &DCCb, CbDC_HT, CbAC_HT);
process_DU(CrDU, fdtbl_Cb, &DCCr, CbDC_HT, CbAC_HT);
}
}*/
}
void init_all()
{
set_DQTinfo();
set_DHTinfo();
init_Huffman_tables();
set_numbers_category_and_bitcode();
precalculate_YCbCr_tables();
prepare_quant_tables();
}
void main()
{
FILE *ImageFile;//*fp_jpeg_stream;
unsigned char c1; char magic[2];
int Loop, i,j,k,l,m,p,q,count;
unsigned char Y1,Cb1,Cr1;
WORD width_original,height_original;
BYTE len_filename;
bitstring fillbits;
clrscr();
if((ImageFile = fopen("lena2.bmp", "rb")) == NULL)
{
printf("Could not open file for reading");
exit(0);
}
fread(magic,2,1,ImageFile);
fread(&bmfh, sizeof(BITMAPFILEHEADER), 1, ImageFile);
fread(&bmih, sizeof(BITMAPINFOHEADER), 1, ImageFile);
width=bmih.width; height=bmih.height;
// a=A;
// fseek(ImageFile,0,SEEK_CUR);
i=0;k=0;l=0;m=0;p=0;q=0;count=0;
printf("\n READING PIXEL MATRIX");
for(Loop = 0; Loop < ((bmih.height * bmih.width) * 3); Loop += 1)
{ fread(&c1, sizeof(unsigned char), 1,ImageFile);
red: if(count==0)
{
if(k<64) R[i][k++]=c1;
else
{
i++; k=0;
R[i][k++]=c1;
}
} //if
else if (count==1)
{
if(m<64) G[l][m++]=c1;
else
{
l++; m=0;
G[l][m++]=c1;
}
}//else if
else if(count==2)
{
if(q<64) B[p][q++]=c1;
else
{
p++; q=0;
B[p][q++]=c1;
}
}//else if
else { count=0; goto red; }
count++;
}
fclose(ImageFile);
for(i=0;i<64;i++)
{
for(j=0;j<64;j++)
{
Y1=((unsigned char)(0.299* R [i][j]+ 0.587 * G[i][j] + 0.114 * B[i][j]));
//Y1=Y(R[i][j],G[i][j],B[i][j]);
Cb1=((unsigned char)(- 0.1687* R[i][j]- 0.3313 * G[i][j] + 0.5 * B[i][j] + 128));
//Cb1=Cb(R[i][j],G[i][j],B[i][j]);
Cr1=((unsigned char)(0.5 * R[i][j] - 0.4187 * G[i][j] - 0.0813 * B[i][j] + 128));
//Cr1=Cr(R[i][j],G[i][j],B[i][j]);
R[i][j]=Y1;
G[i][j]=Cb1;
B[i][j]=Cr1;
}
}
fp_jpeg_stream = fopen("new_image.jpg","wb");
init_all();
printf("\n Setting width n height");
SOF0info.width = bmih.width;
SOF0info.height = bmih.height;
writeword(0xFFD8); // SOI
write_APP0info();
// write_comment("Cris made this JPEG with his own encoder");
write_DQTinfo();
write_SOF0info();
write_DHTinfo();
write_SOSinfo();
// init global variables
bytenew = 0; // current byte
bytepos = 7; // bit position in this byte
main_encoder();
// Do the bit alignment of the EOI marker
if (bytepos >= 0)
{
fillbits.length = bytepos + 1;
fillbits.value = (1<<(bytepos+1)) - 1;
writebits(fillbits);
}
writeword(0xFFD9); // EOI
// free(RGB_buffer);
// free(category_alloc);
// free(bitcode_alloc);
fclose(fp_jpeg_stream);
printf("\n Written and saved the file");
}
ASKER
I am working on 64x64 bmp image with depth=24 bits.
Could you post the original image, as well as the converted image you get ?
ASKER
Hello ,
Original image. Also I have not posted the header files. Do i send it?
Original image. Also I have not posted the header files. Do i send it?
Anything you have that you think might be useful :)
ASKER
ASKER
Your code is difficult to read, so I'll base myself on the images instead.
The image looks like it's flipped vertically. That should be relatively easy to fix (start filling from the other side of the image).
The colours look like they're inverted, and smoothed. So there are probably conversion as well as rounding errors somewhere.
The image looks like it's flipped vertically. That should be relatively easy to fix (start filling from the other side of the image).
The colours look like they're inverted, and smoothed. So there are probably conversion as well as rounding errors somewhere.
ASKER
can i comment out the code so that it becomes readable.
>> can i comment out the code so that it becomes readable.
To make the code more readable, you'd at the very least need to get rid of all magic values, and meaningless symbol names. It would also be good to modularize the code into meaningful (properly named) functions. It would also help a lot if the code was properly indented.
While quickly scanning the code (without looking at the details), my eye fell on this :
>> R[i][j]=Y1;
>> G[i][j]=Cb1;
>> B[i][j]=Cr1;
This seems to suggest that this is using YCbCr, as if it were RGB. That could explain the wrong colours.
To make the code more readable, you'd at the very least need to get rid of all magic values, and meaningless symbol names. It would also be good to modularize the code into meaningful (properly named) functions. It would also help a lot if the code was properly indented.
While quickly scanning the code (without looking at the details), my eye fell on this :
>> R[i][j]=Y1;
>> G[i][j]=Cb1;
>> B[i][j]=Cr1;
This seems to suggest that this is using YCbCr, as if it were RGB. That could explain the wrong colours.
ASKER
Actually I have converted R,,G,B into Y,Cb,Cr and every byte is written (saved) back to R,G,B matrices. So that i will save the space. I think the error is in rounding. But still I am not getting probable reason/statement from the code.
>> and every byte is written (saved) back to R,G,B matrices.
Ok.
>> But still I am not getting probable reason/statement from the code.
I'd start by tracking down the easy part : the fact that the image is mirrored vertically.
Ok.
>> But still I am not getting probable reason/statement from the code.
I'd start by tracking down the easy part : the fact that the image is mirrored vertically.
ASKER
the steps are:
1) Read 24 bit bmp file and converted into R,G,B pixel matrices
2) R[][],G[][],B[][] are converted to Y,Cb,Cr and then stored back in the three matrices so that R[][] stores
Y, G[][] stores Cb and so on
3) Then opened the file .jpeg which is to be written
4) Stored the header information
5) Called main_encoder()
6) in main_encoder, conveted each data unit of 8x8 block into array and then a call is made for process_DU for each 64 byte array of Y,Cb,cR
7)In Process_DU, performed DCT and Quantization using IJG's DCT Routine and Written the bitstring for the data to file
8) All the function SET_DHTinfo,SET_DQTinfo sets the value for header and WRITE_... writes the header.
9) bitswise dat is written using writebits() function.
10) debugging is done by placing printf() wherever necessory.
1) Read 24 bit bmp file and converted into R,G,B pixel matrices
2) R[][],G[][],B[][] are converted to Y,Cb,Cr and then stored back in the three matrices so that R[][] stores
Y, G[][] stores Cb and so on
3) Then opened the file .jpeg which is to be written
4) Stored the header information
5) Called main_encoder()
6) in main_encoder, conveted each data unit of 8x8 block into array and then a call is made for process_DU for each 64 byte array of Y,Cb,cR
7)In Process_DU, performed DCT and Quantization using IJG's DCT Routine and Written the bitstring for the data to file
8) All the function SET_DHTinfo,SET_DQTinfo sets the value for header and WRITE_... writes the header.
9) bitswise dat is written using writebits() function.
10) debugging is done by placing printf() wherever necessory.
The vertical mirroring is indeed because you're processing the BMP data in the wrong order. The BMP data starts in the lower left corner of the image (the first row is the bottom row of the image), so the loop in the main_encoder function has to be changed to :
for (row = bmih.height - 1; row >= 0; row -= N)
instead of :
>> for(row=0;row<bmih.height; row+=N)
and :
for (i = 0, l = startr; i < N; i++, l--)
instead of :
>> for(i=0,l=startr;i<N;i++,l ++)
for (row = bmih.height - 1; row >= 0; row -= N)
instead of :
>> for(row=0;row<bmih.height;
and :
for (i = 0, l = startr; i < N; i++, l--)
instead of :
>> for(i=0,l=startr;i<N;i++,l
ASKER
Thanks a lot. Now the vertical mirroring problem is solved. The next problem may be because of color space transformation or some mistake might be there in writing the header.
ASKER
ASKER
Again thank you for your kind and prompt help. I am trying to solve the problem.
ASKER
Great. Sorry I couldn't get back earlier. I haven't had the chance.
So, what was the problem with the colours ?
So, what was the problem with the colours ?
ASKER
the problem was in the redaing of RGB color. Actually in Bitmap the data is stored as B,G,R and as R,G,B.
I just changed the sequence and it worked.
Thanks.
I just changed the sequence and it worked.
Thanks.
Ah. Nice find :)
This question has been classified as abandoned and is being closed as part of the Cleanup Program. See my comment at the end of the question for more details.
ASKER
I want to convert bmp file to jpeg.
I read bmp file applied dct . but dont know how to store it as jpeg
Thank you