Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 204 | chris | 1 | /* JPEG To RGB interface --Raphael Grasset - 04/07/16 - 2004 Hitlab NZ. All Rights reserved-- |
| 2 | |||
| 3 | This file define simple routine functions for converting a JPEG image to RGB format. |
||
| 4 | It use is ONLY for EyeToy Camera. |
||
| 5 | |||
| 6 | WARNING : It use a static image area : at each call of conversion, the new |
||
| 7 | image is copying on the same memory area (limited dynamic allocation mamagement). |
||
| 8 | So be careful when you manipulating the pointer on the image !! |
||
| 9 | |||
| 10 | USAGE : |
||
| 11 | Based on libjpeg (providing hardware decompression), you need just add few things on your code: |
||
| 12 | |||
| 13 | #include "jpegtorgb.h" //this file |
||
| 14 | |||
| 15 | int xsiwe=640;//video image format |
||
| 16 | int ysize=480;//video image format |
||
| 17 | .... |
||
| 18 | JPEGToRGBInit(xsize,ysize); //init function with image size in parameters |
||
| 19 | .... |
||
| 20 | |||
| 21 | ARUint8* decompressed_image=JPEGToRGB(video_image,xsize,ysize); //converting function (converted image return) |
||
| 22 | |||
| 23 | don't be care with ARUint8, equivalent to an unsigned char format. |
||
| 24 | |||
| 25 | */ |
||
| 26 | |||
| 27 | #include "jpeglib.h" |
||
| 28 | #include "jerror.h" |
||
| 29 | #include <setjmp.h> |
||
| 30 | |||
| 31 | |||
| 32 | /*---------------- Direct Input Functions for libjpeg --------------*/ |
||
| 33 | |||
| 34 | /* we overload the interface for open a jpeg file : the libjpeg |
||
| 35 | file is limited for only FILE* input. Since we have a JPEG image |
||
| 36 | in memory we need a new interface for libjpeg. For these we overload |
||
| 37 | differents functions. |
||
| 38 | I have modified the code for jpeg_stdio_src, and providing |
||
| 39 | new functions name EyeToy_XXX (XXX template |
||
| 40 | |||
| 41 | Need to be optimized, cleaned. |
||
| 42 | */ |
||
| 43 | |||
| 44 | #define JFREAD(file,buf,sizeofbuf) \ |
||
| 45 | ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) |
||
| 46 | |||
| 47 | /* Expanded data source object for stdio input */ |
||
| 48 | |||
| 49 | typedef struct { |
||
| 50 | struct jpeg_source_mgr pub; /* public fields */ |
||
| 51 | |||
| 52 | unsigned char* image; |
||
| 53 | int image_size; |
||
| 54 | JOCTET * buffer; /* start of buffer */ |
||
| 55 | boolean start_of_file; /* have we gotten any data yet? */ |
||
| 56 | } my_source_mgr; |
||
| 57 | |||
| 58 | typedef my_source_mgr * my_src_ptr; |
||
| 59 | |||
| 60 | #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ |
||
| 61 | |||
| 62 | /* |
||
| 63 | * Initialize source --- called by jpeg_read_header |
||
| 64 | * before any data is actually read. |
||
| 65 | */ |
||
| 66 | |||
| 67 | METHODDEF(void) |
||
| 68 | EyeToy_init_source (j_decompress_ptr cinfo) |
||
| 69 | { |
||
| 70 | my_src_ptr src = (my_src_ptr) cinfo->src; |
||
| 71 | |||
| 72 | /* We reset the empty-input-file flag for each image, |
||
| 73 | * but we don't clear the input buffer. |
||
| 74 | * This is correct behavior for reading a series of images from one source. |
||
| 75 | */ |
||
| 76 | src->start_of_file = TRUE; |
||
| 77 | } |
||
| 78 | |||
| 79 | /* |
||
| 80 | * Fill the input buffer --- called whenever buffer is emptied. |
||
| 81 | * |
||
| 82 | * In typical applications, this should read fresh data into the buffer |
||
| 83 | * (ignoring the current state of next_input_byte & bytes_in_buffer), |
||
| 84 | * reset the pointer & count to the start of the buffer, and return TRUE |
||
| 85 | * indicating that the buffer has been reloaded. It is not necessary to |
||
| 86 | * fill the buffer entirely, only to obtain at least one more byte. |
||
| 87 | * |
||
| 88 | * There is no such thing as an EOF return. If the end of the file has been |
||
| 89 | * reached, the routine has a choice of ERREXIT() or inserting fake data into |
||
| 90 | * the buffer. In most cases, generating a warning message and inserting a |
||
| 91 | * fake EOI marker is the best course of action --- this will allow the |
||
| 92 | * decompressor to output however much of the image is there. However, |
||
| 93 | * the resulting error message is misleading if the real problem is an empty |
||
| 94 | * input file, so we handle that case specially. |
||
| 95 | * |
||
| 96 | * In applications that need to be able to suspend compression due to input |
||
| 97 | * not being available yet, a FALSE return indicates that no more data can be |
||
| 98 | * obtained right now, but more may be forthcoming later. In this situation, |
||
| 99 | * the decompressor will return to its caller (with an indication of the |
||
| 100 | * number of scanlines it has read, if any). The application should resume |
||
| 101 | * decompression after it has loaded more data into the input buffer. Note |
||
| 102 | * that there are substantial restrictions on the use of suspension --- see |
||
| 103 | * the documentation. |
||
| 104 | * |
||
| 105 | * When suspending, the decompressor will back up to a convenient restart point |
||
| 106 | * (typically the start of the current MCU). next_input_byte & bytes_in_buffer |
||
| 107 | * indicate where the restart point will be if the current call returns FALSE. |
||
| 108 | * Data beyond this point must be rescanned after resumption, so move it to |
||
| 109 | * the front of the buffer rather than discarding it. |
||
| 110 | */ |
||
| 111 | |||
| 112 | METHODDEF(boolean) |
||
| 113 | EyeToy_fill_input_buffer (j_decompress_ptr cinfo) |
||
| 114 | { |
||
| 115 | my_src_ptr src = (my_src_ptr) cinfo->src; |
||
| 116 | |||
| 117 | src->pub.next_input_byte = src->image; |
||
| 118 | src->pub.bytes_in_buffer = src->image_size; |
||
| 119 | |||
| 120 | src->start_of_file = FALSE; |
||
| 121 | |||
| 122 | return TRUE; |
||
| 123 | } |
||
| 124 | |||
| 125 | /* |
||
| 126 | * Skip data --- used to skip over a potentially large amount of |
||
| 127 | * uninteresting data (such as an APPn marker). |
||
| 128 | * |
||
| 129 | * Writers of suspendable-input applications must note that skip_input_data |
||
| 130 | * is not granted the right to give a suspension return. If the skip extends |
||
| 131 | * beyond the data currently in the buffer, the buffer can be marked empty so |
||
| 132 | * that the next read will cause a fill_input_buffer call that can suspend. |
||
| 133 | * Arranging for additional bytes to be discarded before reloading the input |
||
| 134 | * buffer is the application writer's problem. |
||
| 135 | */ |
||
| 136 | |||
| 137 | METHODDEF(void) |
||
| 138 | EyeToy_skip_input_data (j_decompress_ptr cinfo, long num_bytes) |
||
| 139 | { |
||
| 140 | my_src_ptr src = (my_src_ptr) cinfo->src; |
||
| 141 | |||
| 142 | /* Just a dumb implementation for now. Could use fseek() except |
||
| 143 | * it doesn't work on pipes. Not clear that being smart is worth |
||
| 144 | * any trouble anyway --- large skips are infrequent. |
||
| 145 | */ |
||
| 146 | if (num_bytes > 0) { |
||
| 147 | while (num_bytes > (long) src->pub.bytes_in_buffer) { |
||
| 148 | num_bytes -= (long) src->pub.bytes_in_buffer; |
||
| 149 | (void) EyeToy_fill_input_buffer(cinfo); |
||
| 150 | /* note we assume that fill_input_buffer will never return FALSE, |
||
| 151 | * so suspension need not be handled. |
||
| 152 | */ |
||
| 153 | } |
||
| 154 | src->pub.next_input_byte += (size_t) num_bytes; |
||
| 155 | src->pub.bytes_in_buffer -= (size_t) num_bytes; |
||
| 156 | } |
||
| 157 | } |
||
| 158 | |||
| 159 | /* |
||
| 160 | * An additional method that can be provided by data source modules is the |
||
| 161 | * resync_to_restart method for error recovery in the presence of RST markers. |
||
| 162 | * For the moment, this source module just uses the default resync method |
||
| 163 | * provided by the JPEG library. That method assumes that no backtracking |
||
| 164 | * is possible. |
||
| 165 | */ |
||
| 166 | |||
| 167 | /* |
||
| 168 | * Terminate source --- called by jpeg_finish_decompress |
||
| 169 | * after all data has been read. Often a no-op. |
||
| 170 | * |
||
| 171 | * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding |
||
| 172 | * application must deal with any cleanup that should happen even |
||
| 173 | * for error exit. |
||
| 174 | */ |
||
| 175 | |||
| 176 | METHODDEF(void) |
||
| 177 | EyeToy_term_source (j_decompress_ptr cinfo) |
||
| 178 | { |
||
| 179 | /* no work necessary here */ |
||
| 180 | } |
||
| 181 | |||
| 182 | |||
| 183 | /* |
||
| 184 | The new jpeg access function : directly read the memory |
||
| 185 | buffer instead of a FILE* input. Since all the image |
||
| 186 | is in memory we put all the buffer in one pass. |
||
| 187 | */ |
||
| 188 | |||
| 189 | GLOBAL(void) |
||
| 190 | EyeToy_jpeg_stdio_src(j_decompress_ptr cinfo,unsigned char *image,int count) |
||
| 191 | { |
||
| 192 | my_src_ptr src; |
||
| 193 | |||
| 194 | /* The source object and input buffer are made permanent so that a series |
||
| 195 | * of JPEG images can be read from the same file by calling jpeg_stdio_src |
||
| 196 | * only before the first one. (If we discarded the buffer at the end of |
||
| 197 | * one image, we'd likely lose the start of the next one.) |
||
| 198 | * This makes it unsafe to use this manager and a different source |
||
| 199 | * manager serially with the same JPEG object. Caveat programmer. |
||
| 200 | */ |
||
| 201 | if (cinfo->src == NULL) { /* first time for this JPEG object? */ |
||
| 202 | cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, |
||
| 203 | sizeof(my_source_mgr)); |
||
| 204 | src = (my_src_ptr) cinfo->src; |
||
| 205 | src->buffer = (JOCTET *) |
||
| 206 | (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof(JOCTET)); |
||
| 207 | } |
||
| 208 | |||
| 209 | src = (my_src_ptr) cinfo->src; |
||
| 210 | src->pub.init_source = EyeToy_init_source; |
||
| 211 | src->pub.fill_input_buffer = EyeToy_fill_input_buffer; |
||
| 212 | src->pub.skip_input_data = EyeToy_skip_input_data; |
||
| 213 | src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ |
||
| 214 | src->pub.term_source = EyeToy_term_source; |
||
| 215 | src->image=image; |
||
| 216 | src->image_size=count; |
||
| 217 | src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ |
||
| 218 | src->pub.next_input_byte = NULL; /* until buffer loaded */ |
||
| 219 | } |
||
| 220 | |||
| 221 | static ARUint8* TransfertBufferImage; |
||
| 222 | |||
| 223 | /*---------------- Main Functions --------------*/ |
||
| 224 | |||
| 225 | void JPEGToRGBInit(int xsize,int ysize) |
||
| 226 | { |
||
| 227 | TransfertBufferImage = malloc(xsize*ysize*3); |
||
| 228 | } |
||
| 229 | |||
| 230 | |||
| 231 | ARUint8* JPEGToRGB(ARUint8* image, int xsize,int ysize) |
||
| 232 | { |
||
| 233 | |||
| 234 | int image_height=xsize; /* Number of rows in image */ |
||
| 235 | int image_width=ysize; /* Number of columns in image */ |
||
| 236 | |||
| 237 | struct jpeg_error_mgr jerr; |
||
| 238 | struct jpeg_decompress_struct cinfo; |
||
| 239 | |||
| 240 | JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ |
||
| 241 | int row_stride; /* physical row width in output buffer */ |
||
| 242 | int crows=0; |
||
| 243 | |||
| 244 | cinfo.err = jpeg_std_error(&jerr); |
||
| 245 | |||
| 246 | jpeg_create_decompress(&cinfo); |
||
| 247 | |||
| 248 | ssize_t count; |
||
| 249 | count=(image[0]+image[1]*65536)/8; |
||
| 250 | |||
| 251 | EyeToy_jpeg_stdio_src(&cinfo,image+2,count); |
||
| 252 | |||
| 253 | (void) jpeg_read_header(&cinfo, TRUE); |
||
| 254 | |||
| 255 | (void) jpeg_start_decompress(&cinfo); |
||
| 256 | |||
| 257 | row_stride = cinfo.output_width * cinfo.output_components; |
||
| 258 | /* Make a one-row-high sample array that will go away when done with image */ |
||
| 259 | |||
| 260 | while (cinfo.output_scanline < cinfo.output_height) |
||
| 261 | { |
||
| 262 | row_pointer[0] = & TransfertBufferImage[crows * row_stride]; |
||
| 263 | (void) jpeg_read_scanlines(&cinfo, row_pointer, 1); |
||
| 264 | crows++; |
||
| 265 | } |
||
| 266 | |||
| 267 | (void) jpeg_finish_decompress(&cinfo); |
||
| 268 | |||
| 269 | jpeg_destroy_decompress(&cinfo); |
||
| 270 | |||
| 271 | return TransfertBufferImage; |
||
| 272 | } |