#include #include "dct.h" #define ENCODE 0 #define DECODE 1 #define MAXROWS 1024 #define MAXCOLS 768 #define HEADER 56 #define SOI_MK 0xFFD8 /* start of image */ #define SOF_MK 0xFFC0 /* start of frame */ #define EOI_MK 0xFFD9 /* end of image */ #define DRI_MK 0xFFDD /* restart interval */ #define get_size(fi) (((unsigned int)Image1[fi]) << 8) + (unsigned int)Image1[fi+1] unsigned char Image1[MAXCOLS*3*MAXROWS+HEADER]; unsigned char clip(int value) { if (value < 0) return (char) 0; if (value > 255) return (char) 255; return (unsigned char) value; } /* RGB -> YCbCr (also from BMP to JPEG) */ // Y = 0.299 R + 0.587 G + 0.114 B unsigned char RGB2Y (unsigned char R, unsigned char G, unsigned char B) { return clip(0.299 * R + 0.587 * G + 0.114 * B); } // Cb = - 0.1687 R - 0.3313 G + 0.5 B + 128 unsigned char RGB2Cb (unsigned char R, unsigned char G, unsigned char B) { return clip(- 0.1687 * R - 0.3313 * G + 0.5 * B + 128); } //Cr = 0.5 R - 0.4187 G - 0.0813 B + 128 unsigned char RGB2Cr (unsigned char R, unsigned char G, unsigned char B) { return clip(0.5 * R - 0.4187 * G - 0.0813 * B + 128); } /* RGB -> YCbCr (also from JPEG to BMP) */ // R = Y + 1.402 (Cr-128) unsigned char YCbCr2R (unsigned char Y, unsigned char Cr) { return clip(Y + 1.402 *(Cr-128)); } // G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128) unsigned char YCbCr2G (unsigned char Y, unsigned char Cb, unsigned char Cr) { return clip(Y - 0.34414 *(Cb-128) - 0.71414 *(Cr-128)); } // B = Y + 1.772 (Cb-128) unsigned char YCbCr2B (unsigned char Y, unsigned char Cb) { return clip(Y + 1.772 *(Cb-128)); } int main(int argc, char *argv[]) { int retval, i; int workspace[DCTSIZE_BLOCK]; int type, hCounter = 0; int x_size, y_size, offset, depth; char *fileIn, *fileOut; FILE *fI, *fO; unsigned char ch, mrgb[3]; unsigned int aux; /*******************************************************************************************/ /* Just for testing on the PC */ if(argc != 4) { printf("need more arguments"); return 0; } type = atoi(argv[1]); fileIn = argv[2]; fileOut = argv[3]; if (NULL == (fI = fopen(fileIn, "rb"))){ printf("unable to open the file to read from (%s)",fileIn); return 0; } if ((fO = fopen(fileOut,"wb")) == NULL) { printf("unable to open the file to write (%s)",fileOut); return 0; } /* Read the max possible size to the memory */ fread(Image1, sizeof(unsigned char), (MAXROWS*MAXCOLS*3+HEADER), fI); /*******************************************************************************************/ /* The image must be in the memory by now */ switch(type) { case ENCODE: offset = ((int)Image1[13] << 24) + ((int)Image1[12] << 16) + ((int)Image1[11] << 8) + Image1[10]; x_size = ((int)Image1[21] << 24) + ((int)Image1[20] << 16) + ((int)Image1[19] << 8) + Image1[18]; y_size = ((int)Image1[25] << 24) + ((int)Image1[24] << 16) + ((int)Image1[23] << 8) + Image1[22]; depth = ((int)Image1[29] << 8) + Image1[28]; /**/ printf("Image Resolution: %d x %d x %i Offset: %i\n", x_size, y_size, depth, offset); break; case DECODE: /* First find the SOI marker: */ aux = get_size(hCounter); hCounter+=2; if (aux != SOI_MK) { printf("INFO:\tNO SOI marker!\n"); return 0;} printf("%ld:\tINFO:\tFound the SOI marker!\n", hCounter); /* Read first marker */ while( aux != SOF_MK) { aux = get_size(hCounter); hCounter+=2; if(aux == SOF_MK) { get_size(hCounter); hCounter+=2; /* header size, don't care */ /* load basic image parameters */ hCounter++; /* precision, 8bit, don't care */ y_size = get_size(hCounter); hCounter+=2; x_size = get_size(hCounter); hCounter+=2; printf("\tINFO:\tImage size is %d by %d\n", x_size, y_size); depth = Image1[hCounter]; /* # of components */ printf("\tINFO:\t"); switch (depth) { case 1: printf("Monochrome"); break; case 3: printf("Color"); break; default: printf("Not a"); break; } printf(" JPEG image!\n"); return 0; } else { hCounter = hCounter + get_size(hCounter); } } } retval = 0; type = ENCODE; switch(type) { case ENCODE: // RGB -> YUV // Convert to 8x8 // DCT fdct(workspace); // ZZ // Q // VLC (huffman) break; case DECODE: // VLD (huffman) // IQ // ZZ // IDCT //idct(workspace); // Convert 8x8 to lines // YUV -> RGB break; } return retval; }