00001 /* JPEG To RGB interface --Raphael Grasset - 04/07/16 - 2004 Hitlab NZ. All Rights reserved-- 00002 00003 This file define simple routine functions for converting a JPEG image to RGB format. 00004 It use is ONLY for EyeToy Camera. 00005 00006 WARNING : It use a static image area : at each call of conversion, the new 00007 image is copying on the same memory area (limited dynamic allocation mamagement). 00008 So be careful when you manipulating the pointer on the image !! 00009 00010 USAGE : 00011 Based on libjpeg (providing hardware decompression), you need just add few things on your code: 00012 00013 #include "jpegtorgb.h" //this file 00014 00015 int xsiwe=640;//video image format 00016 int ysize=480;//video image format 00017 .... 00018 JPEGToRGBInit(xsize,ysize); //init function with image size in parameters 00019 .... 00020 00021 ARUint8* decompressed_image=JPEGToRGB(video_image,xsize,ysize); //converting function (converted image return) 00022 00023 don't be care with ARUint8, equivalent to an unsigned char format. 00024 00025 */ 00026 00027 #include "jpeglib.h" 00028 #include "jerror.h" 00029 #include <setjmp.h> 00030 00031 00032 /*---------------- Direct Input Functions for libjpeg --------------*/ 00033 00034 /* we overload the interface for open a jpeg file : the libjpeg 00035 file is limited for only FILE* input. Since we have a JPEG image 00036 in memory we need a new interface for libjpeg. For these we overload 00037 differents functions. 00038 I have modified the code for jpeg_stdio_src, and providing 00039 new functions name EyeToy_XXX (XXX template 00040 00041 Need to be optimized, cleaned. 00042 */ 00043 00044 #define JFREAD(file,buf,sizeofbuf) \ 00045 ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) 00046 00047 /* Expanded data source object for stdio input */ 00048 00049 typedef struct { 00050 struct jpeg_source_mgr pub; /* public fields */ 00051 00052 unsigned char* image; 00053 int image_size; 00054 JOCTET * buffer; /* start of buffer */ 00055 boolean start_of_file; /* have we gotten any data yet? */ 00056 } my_source_mgr; 00057 00058 typedef my_source_mgr * my_src_ptr; 00059 00060 #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ 00061 00062 /* 00063 * Initialize source --- called by jpeg_read_header 00064 * before any data is actually read. 00065 */ 00066 00067 METHODDEF(void) 00068 EyeToy_init_source (j_decompress_ptr cinfo) 00069 { 00070 my_src_ptr src = (my_src_ptr) cinfo->src; 00071 00072 /* We reset the empty-input-file flag for each image, 00073 * but we don't clear the input buffer. 00074 * This is correct behavior for reading a series of images from one source. 00075 */ 00076 src->start_of_file = TRUE; 00077 } 00078 00079 /* 00080 * Fill the input buffer --- called whenever buffer is emptied. 00081 * 00082 * In typical applications, this should read fresh data into the buffer 00083 * (ignoring the current state of next_input_byte & bytes_in_buffer), 00084 * reset the pointer & count to the start of the buffer, and return TRUE 00085 * indicating that the buffer has been reloaded. It is not necessary to 00086 * fill the buffer entirely, only to obtain at least one more byte. 00087 * 00088 * There is no such thing as an EOF return. If the end of the file has been 00089 * reached, the routine has a choice of ERREXIT() or inserting fake data into 00090 * the buffer. In most cases, generating a warning message and inserting a 00091 * fake EOI marker is the best course of action --- this will allow the 00092 * decompressor to output however much of the image is there. However, 00093 * the resulting error message is misleading if the real problem is an empty 00094 * input file, so we handle that case specially. 00095 * 00096 * In applications that need to be able to suspend compression due to input 00097 * not being available yet, a FALSE return indicates that no more data can be 00098 * obtained right now, but more may be forthcoming later. In this situation, 00099 * the decompressor will return to its caller (with an indication of the 00100 * number of scanlines it has read, if any). The application should resume 00101 * decompression after it has loaded more data into the input buffer. Note 00102 * that there are substantial restrictions on the use of suspension --- see 00103 * the documentation. 00104 * 00105 * When suspending, the decompressor will back up to a convenient restart point 00106 * (typically the start of the current MCU). next_input_byte & bytes_in_buffer 00107 * indicate where the restart point will be if the current call returns FALSE. 00108 * Data beyond this point must be rescanned after resumption, so move it to 00109 * the front of the buffer rather than discarding it. 00110 */ 00111 00112 METHODDEF(boolean) 00113 EyeToy_fill_input_buffer (j_decompress_ptr cinfo) 00114 { 00115 my_src_ptr src = (my_src_ptr) cinfo->src; 00116 00117 src->pub.next_input_byte = src->image; 00118 src->pub.bytes_in_buffer = src->image_size; 00119 00120 src->start_of_file = FALSE; 00121 00122 return TRUE; 00123 } 00124 00125 /* 00126 * Skip data --- used to skip over a potentially large amount of 00127 * uninteresting data (such as an APPn marker). 00128 * 00129 * Writers of suspendable-input applications must note that skip_input_data 00130 * is not granted the right to give a suspension return. If the skip extends 00131 * beyond the data currently in the buffer, the buffer can be marked empty so 00132 * that the next read will cause a fill_input_buffer call that can suspend. 00133 * Arranging for additional bytes to be discarded before reloading the input 00134 * buffer is the application writer's problem. 00135 */ 00136 00137 METHODDEF(void) 00138 EyeToy_skip_input_data (j_decompress_ptr cinfo, long num_bytes) 00139 { 00140 my_src_ptr src = (my_src_ptr) cinfo->src; 00141 00142 /* Just a dumb implementation for now. Could use fseek() except 00143 * it doesn't work on pipes. Not clear that being smart is worth 00144 * any trouble anyway --- large skips are infrequent. 00145 */ 00146 if (num_bytes > 0) { 00147 while (num_bytes > (long) src->pub.bytes_in_buffer) { 00148 num_bytes -= (long) src->pub.bytes_in_buffer; 00149 (void) EyeToy_fill_input_buffer(cinfo); 00150 /* note we assume that fill_input_buffer will never return FALSE, 00151 * so suspension need not be handled. 00152 */ 00153 } 00154 src->pub.next_input_byte += (size_t) num_bytes; 00155 src->pub.bytes_in_buffer -= (size_t) num_bytes; 00156 } 00157 } 00158 00159 /* 00160 * An additional method that can be provided by data source modules is the 00161 * resync_to_restart method for error recovery in the presence of RST markers. 00162 * For the moment, this source module just uses the default resync method 00163 * provided by the JPEG library. That method assumes that no backtracking 00164 * is possible. 00165 */ 00166 00167 /* 00168 * Terminate source --- called by jpeg_finish_decompress 00169 * after all data has been read. Often a no-op. 00170 * 00171 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding 00172 * application must deal with any cleanup that should happen even 00173 * for error exit. 00174 */ 00175 00176 METHODDEF(void) 00177 EyeToy_term_source (j_decompress_ptr cinfo) 00178 { 00179 /* no work necessary here */ 00180 } 00181 00182 00183 /* 00184 The new jpeg access function : directly read the memory 00185 buffer instead of a FILE* input. Since all the image 00186 is in memory we put all the buffer in one pass. 00187 */ 00188 00189 GLOBAL(void) 00190 EyeToy_jpeg_stdio_src(j_decompress_ptr cinfo,unsigned char *image,int count) 00191 { 00192 my_src_ptr src; 00193 00194 /* The source object and input buffer are made permanent so that a series 00195 * of JPEG images can be read from the same file by calling jpeg_stdio_src 00196 * only before the first one. (If we discarded the buffer at the end of 00197 * one image, we'd likely lose the start of the next one.) 00198 * This makes it unsafe to use this manager and a different source 00199 * manager serially with the same JPEG object. Caveat programmer. 00200 */ 00201 if (cinfo->src == NULL) { /* first time for this JPEG object? */ 00202 cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, 00203 sizeof(my_source_mgr)); 00204 src = (my_src_ptr) cinfo->src; 00205 src->buffer = (JOCTET *) 00206 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof(JOCTET)); 00207 } 00208 00209 src = (my_src_ptr) cinfo->src; 00210 src->pub.init_source = EyeToy_init_source; 00211 src->pub.fill_input_buffer = EyeToy_fill_input_buffer; 00212 src->pub.skip_input_data = EyeToy_skip_input_data; 00213 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ 00214 src->pub.term_source = EyeToy_term_source; 00215 src->image=image; 00216 src->image_size=count; 00217 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ 00218 src->pub.next_input_byte = NULL; /* until buffer loaded */ 00219 } 00220 00221 static ARUint8* TransfertBufferImage; 00222 00223 /*---------------- Main Functions --------------*/ 00224 00225 void JPEGToRGBInit(int xsize,int ysize) 00226 { 00227 TransfertBufferImage = malloc(xsize*ysize*3); 00228 } 00229 00230 00231 ARUint8* JPEGToRGB(ARUint8* image, int xsize,int ysize) 00232 { 00233 00234 int image_height=xsize; /* Number of rows in image */ 00235 int image_width=ysize; /* Number of columns in image */ 00236 00237 struct jpeg_error_mgr jerr; 00238 struct jpeg_decompress_struct cinfo; 00239 00240 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 00241 int row_stride; /* physical row width in output buffer */ 00242 int crows=0; 00243 00244 cinfo.err = jpeg_std_error(&jerr); 00245 00246 jpeg_create_decompress(&cinfo); 00247 00248 ssize_t count; 00249 count=(image[0]+image[1]*65536)/8; 00250 00251 EyeToy_jpeg_stdio_src(&cinfo,image+2,count); 00252 00253 (void) jpeg_read_header(&cinfo, TRUE); 00254 00255 (void) jpeg_start_decompress(&cinfo); 00256 00257 row_stride = cinfo.output_width * cinfo.output_components; 00258 /* Make a one-row-high sample array that will go away when done with image */ 00259 00260 while (cinfo.output_scanline < cinfo.output_height) 00261 { 00262 row_pointer[0] = & TransfertBufferImage[crows * row_stride]; 00263 (void) jpeg_read_scanlines(&cinfo, row_pointer, 1); 00264 crows++; 00265 } 00266 00267 (void) jpeg_finish_decompress(&cinfo); 00268 00269 jpeg_destroy_decompress(&cinfo); 00270 00271 return TransfertBufferImage; 00272 }