Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ImageJPEG.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 
00027 /* ----------------------------------------------------------------------------
00028  * This is a libary for reading & writing JPEG files
00029  * ------------------------------------------------------------------------- */
00030 #ifdef HAVE_CONFIG_H
00031     #include <phissionconfig.h>
00032 #endif
00033 
00034 #include <phStandard.h>
00035 
00036 #include <ImageJPEG.h>
00037 #include <ImageDefinitions.h>
00038 
00039 #include <phError.h>
00040 #include <phMemory.h>
00041 #include <phPrint.h>
00042 
00043 /* jpeglib.h, jerror.h, jconfig.h, jmorecfg.h */
00044 #include <jpeglib.h>
00045 #include <jerror.h>
00046 
00047 #ifdef __cplusplus
00048 extern "C" {
00049 #endif
00050 
00051 /* ---------------------------------------------------------------------------
00052  * *** NOTE *** :
00053  *
00054  * The following code started from code examples in: 
00055  *          srcjpeg/src/jpeg/6b/jpeg-6b/jdatasrc.c
00056  *          srcjpeg/src/jpeg/6b/jpeg-6b/jdatadst.c
00057  *          
00058  * Many changes were made to provide a memory->memory source and 
00059  * destination managers. Most comments have been left in unedited, although 
00060  * some have been edited.
00061  *
00062  * Alot of custom code has also been written to ease the load on code
00063  * that wants an easy way to compress and decompress.
00064  * ------------------------------------------------------------------------ */
00065 
00066 /* ------------------------------------------------------------------------ */
00067 /* -1 == not started */
00068 #define phJPEG_INITED -1
00069 /* 0 == started */
00070 #define phJPEG_STARTED 0
00071 /* 1 == finished */
00072 #define phJPEG_FINISHED 1
00073 
00074 #define phJPEG_SOURCE 1
00075 #define phJPEG_DEST 2
00076 
00077 #define phJPEG_DEFAULT_SIZE 4096
00078 
00079 /* ------------------------------------------------------------------------- */
00080 /* Create an info struct to simplify the code that is shared between 
00081  * destination and source managers */
00082 typedef struct {
00083 
00084     uint8_t        *m_data;
00085     uint32_t        m_final_size;
00086     uint32_t        m_actual_size;
00087     uint8_t        *m_buffer;
00088     uint32_t        m_buffer_size;
00089     ph_malloc_func  m_malloc;
00090     ph_realloc_func m_realloc;
00091     int             m_state;
00092 
00093     /* For fill input buffer in a source manager */
00094     JOCTET        m_eoi_buffer[2];
00095     
00096 } ph_mem_info;
00097 
00098 /* ------------------------------------------------------------------------ */
00099 /* Expanded data destination object for MEMORY OUTPUT */
00100 typedef struct {
00101     /* JOCTET * next_output_byte;  // => next byte to write in buffer
00102      * size_t free_in_buffer;      // # of byte spaces remaining in buffer */
00103     struct jpeg_destination_mgr pub;
00104     
00105     ph_mem_info info;
00106     
00107 } ph_destination_mgr;
00108 
00109 typedef ph_destination_mgr *ph_dest_ptr;
00110 
00111 /* ------------------------------------------------------------------------ */
00112 /* Expanded data source object for stdio input */
00113 typedef struct {
00114     /* const JOCTET * next_input_byte; // => next byte to read from buffer
00115      * size_t         bytes_in_buffer; // # of bytes remaining in buffer    */
00116     struct jpeg_source_mgr pub;
00117     
00118     ph_mem_info info;
00119 
00120 } ph_source_mgr;
00121 
00122 typedef ph_source_mgr *ph_src_ptr;
00123 
00124 /* ---------------------------------------------------------------------------
00125  * Static Function prototypes *
00126  * ------------------------------------------------------------------------ */
00127 static void     ph_jpeg_init_destination    ( j_compress_ptr cinfo );
00128 static boolean  ph_jpeg_empty_output_buffer ( j_compress_ptr cinfo );
00129 static void     ph_jpeg_term_destination    ( j_compress_ptr cinfo );
00130 static int      ph_mem_info_init( ph_mem_info      *info,
00131                                   uint8_t         **pdst,
00132                                   uint32_t         *sizeptr,
00133                                   ph_malloc_func    mem_malloc,
00134                                   ph_realloc_func   mem_realloc,
00135                                   int               info_type /* phJPEG_SOURCE, 
00136                                                                  phJPEG_DEST */
00137                                  );
00138 static void     ph_init_source      ( j_decompress_ptr cinfo );
00139 static boolean  ph_fill_input_buffer( j_decompress_ptr cinfo );
00140 static void     ph_skip_input_data  ( j_decompress_ptr cinfo, long num_bytes );
00141 static void     ph_term_source      ( j_decompress_ptr cinfo );
00142 
00143 /* ------------------------------------------------------------------------- */
00144 /* Desination Manager functions */
00145 /* ------------------------------------------------------------------------- */
00146 /* if *dst != NULL, *dst is used as the memory,
00147  *      otherwise the memory is allocated with mem_malloc/malloc internally
00148  *          and returned. 
00149  *          
00150  * **NOTE**: the PROGRAMMER is responsible for freeing this memory. 
00151  *  jpeg_destroy will destroy all information about the pointer so it
00152  *  must be saved/retrieved(using ph_jpeg_dest_ptr) before jpeg_destroy
00153  *  is called, if the memory is to be freed.
00154  */
00155 /* ------------------------------------------------------------------------- */
00156 /* if *sizeptr != NULL, *sizeptr is used as the size,
00157  *      otherwise a default phJPEG_DEFAULT_SIZE is used and returned. */
00158 /* if mem_malloc != NULL, mem_malloc is used to allocate,
00159  *      otherwise the default malloc is used. */
00160 /* if mem_realloc != NULL, mem_realloc is used to reallocate,  
00161  *      otherwise the default realloc is used. */
00162 /* ------------------------------------------------------------------------- */
00163 static void ph_jpeg_mem_dest ( ph_cinfo_handle cinfo, 
00164                                uint8_t         **pdst,
00165                                uint32_t        *pdstsize,
00166                                ph_malloc_func   mem_malloc,
00167                                ph_realloc_func  mem_realloc
00168                                );
00169 
00170 /* ------------------------------------------------------------------------- */
00171 /* Returns the final size used for output if the compress cycle has finished, 
00172  * otherwise it returns the actual size of the buffer being used */
00173 static uint32_t ph_jpeg_dest_mem_size( ph_cinfo_handle cinfo );
00174 
00175 /* ------------------------------------------------------------------------- */
00176 /* This returns a pointer to the destination memory output, usually the
00177  * user supplied pointer if preallocated, otherwise it's the pointer
00178  * returned by ph_jpeg_mem_dest */
00179 static uint8_t  *ph_jpeg_dest_mem_ptr( ph_cinfo_handle cinfo );
00180 
00181 /* ------------------------------------------------------------------------- */
00182 /* Source manager functions */
00183 /* ------------------------------------------------------------------------- */
00184 /* sizeptr can't be 0, it has to be the size of the srcmem buffer */
00185 /* srcmem can't be NULL */
00186 static void ph_jpeg_mem_source( ph_cinfo_handle cinfo, 
00187                                 uint8_t         *srcmem,
00188                                 uint32_t        size,
00189                                 ph_malloc_func  mem_malloc,
00190                                 ph_realloc_func mem_realloc
00191                                 );
00192     
00193 #if 0
00194 static uint32_t ph_jpeg_src_mem_size( ph_cinfo_handle cinfo );
00195 static uint8_t  *ph_jpeg_src_mem_ptr( ph_cinfo_handle cinfo );
00196 #endif
00197 
00198 
00199 /* ---------------------------------------------------------------------------
00200  * Initialize destination --- called by jpeg_start_compress
00201  * before any data is actually written.
00202  * ---------------------------------------------------------------------------
00203  * From docjpeg/doc/jpeg/6b/jpeg-6b/libjpeg.txt:
00204  * 
00205  * init_destination (j_compress_ptr cinfo)
00206  *  Initialize destination.  This is called by jpeg_start_compress()
00207  *  before any data is actually written.  It must initialize
00208  *  next_output_byte and free_in_buffer.  free_in_buffer must be
00209  *  initialized to a positive value.
00210  * ------------------------------------------------------------------------ */
00211 static void ph_jpeg_init_destination (j_compress_ptr cinfo)
00212 {
00213     /* phFUNCTION("ph_jpeg_init_destination") */
00214     
00215     ph_dest_ptr dest = (ph_dest_ptr) cinfo->dest;
00216     
00217     /* The output buffer should be ready */
00218     dest->pub.next_output_byte = (JOCTET *)dest->info.m_buffer;
00219     dest->pub.free_in_buffer = dest->info.m_actual_size;
00220 
00221     DEBUG_PRINT("private-%p:%d\n",
00222              dest->info.m_buffer,
00223              dest->info.m_actual_size);
00224     
00225     DEBUG_PRINT("public-%p:%d\n",
00226              dest->pub.next_output_byte,
00227              dest->pub.free_in_buffer);
00228     
00229     dest->info.m_state = phJPEG_STARTED;
00230 }
00231 
00232 
00233 /* ---------------------------------------------------------------------------
00234  * Empty the output buffer --- called whenever buffer fills up.
00235  *
00236  * In typical applications, this should write the entire output buffer
00237  * (ignoring the current state of next_output_byte & free_in_buffer),
00238  * reset the pointer & count to the start of the buffer, and return TRUE
00239  * indicating that the buffer has been dumped.
00240  *
00241  * In applications that need to be able to suspend compression due to output
00242  * overrun, a FALSE return indicates that the buffer cannot be emptied now.
00243  * In this situation, the compressor will return to its caller (possibly with
00244  * an indication that it has not accepted all the supplied scanlines).  The
00245  * application should resume compression after it has made more room in the
00246  * output buffer.  Note that there are substantial restrictions on the use of
00247  * suspension --- see the documentation.
00248  *
00249  * When suspending, the compressor will back up to a convenient restart point
00250  * (typically the start of the current MCU). next_output_byte & free_in_buffer
00251  * indicate where the restart point will be if the current call returns FALSE.
00252  * Data beyond this point will be regenerated after resumption, so do not
00253  * write it out when emptying the buffer externally.
00254  * ---------------------------------------------------------------------------
00255  * From docjpeg/doc/jpeg/6b/jpeg-6b/libjpeg.txt:
00256  * 
00257  * empty_output_buffer (j_compress_ptr cinfo)
00258  *  This is called whenever the buffer has filled (free_in_buffer
00259  *  reaches zero).  In typical applications, it should write out the
00260  *  *entire* buffer (use the saved start address and buffer length;
00261  *  ignore the current state of next_output_byte and free_in_buffer).
00262  *  Then reset the pointer & count to the start of the buffer, and
00263  *  return TRUE indicating that the buffer has been dumped.
00264  *  free_in_buffer must be set to a positive value when TRUE is
00265  *  returned.  A FALSE return should only be used when I/O suspension is
00266  *  desired ....
00267  * ------------------------------------------------------------------------ */
00268 static boolean ph_jpeg_empty_output_buffer (j_compress_ptr cinfo)
00269 {
00270     phFUNCTION("ph_jpeg_empty_output_buffer")
00271     
00272     JOCTET *new_buffer_loc = NULL;
00273     ph_dest_ptr dest = (ph_dest_ptr) cinfo->dest;
00274     
00275     /* Pointer to the new buffer start location */
00276     /* JOCTET *buffer_loc  = NULL; */
00277     uint32_t new_size   = dest->info.m_actual_size + phJPEG_DEFAULT_SIZE;
00278     
00279     /* This really shouldn't be called much if at all. If it is called,
00280      * then phJPEG_DEFAULT_SIZE is realloced to the end of the output 
00281      * buffer */
00282         
00283     DEBUG_PRINT("public(before)-%p:%d\n",
00284              dest->pub.next_output_byte,
00285              dest->pub.free_in_buffer);
00286     
00287     /* Realloc more memory */
00288     dest->info.m_buffer = (dest->info.m_realloc)(dest->info.m_buffer,new_size);
00289     if (dest->info.m_buffer == NULL)
00290     {
00291         phERR_PRINT("dest->info.m_buffer == NULL\n");
00292     }
00293     
00294     /* Get a pointer to the new buffer location in memory */
00295     new_buffer_loc = (JOCTET *)dest->info.m_buffer;
00296     new_buffer_loc += dest->info.m_actual_size;
00297     
00298     /* Set the new size of the buffer */
00299     dest->info.m_final_size = dest->info.m_actual_size = new_size;
00300     
00301     /* Assign the output_byte and free_in_buffer */
00302     dest->pub.next_output_byte = new_buffer_loc;
00303     dest->pub.free_in_buffer = phJPEG_DEFAULT_SIZE;
00304     
00305     DEBUG_PRINT("private-%p:%d\n",
00306              dest->info.m_buffer,
00307              dest->info.m_actual_size);
00308     
00309     DEBUG_PRINT("public(after)-%p:%d\n",
00310              dest->pub.next_output_byte,
00311              dest->pub.free_in_buffer);
00312  
00313     return TRUE;
00314 }
00315 
00316 
00317 /* ---------------------------------------------------------------------------
00318  * Terminate destination --- called by jpeg_finish_compress
00319  * after all data has been written.  Usually needs to flush buffer.
00320  *
00321  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
00322  * application must deal with any cleanup that should happen even
00323  * for error exit.
00324  * ---------------------------------------------------------------------------
00325  * From docjpeg/doc/jpeg/6b/jpeg-6b/libjpeg.txt:
00326  * 
00327  * term_destination (j_compress_ptr cinfo)
00328  *  Terminate destination --- called by jpeg_finish_compress() after all
00329  *  data has been written.  In most applications, this must flush any
00330  *  data remaining in the buffer.  Use either next_output_byte or
00331  *  free_in_buffer to determine how much data is in the buffer.
00332  *  
00333  * term_destination() is NOT called by jpeg_abort() or jpeg_destroy().  If you
00334  * want the destination manager to be cleaned up during an abort, you must do it
00335  * yourself.
00336  * ------------------------------------------------------------------------ */
00337 static void ph_jpeg_term_destination (j_compress_ptr cinfo)
00338 {
00339     phFUNCTION("ph_jpeg_term_destination")
00340 
00341     ph_dest_ptr dest = (ph_dest_ptr) cinfo->dest;
00342     
00343     /* if there is room in the output buffer still, then we need to
00344      * realloc the buffer to size */
00345     if (dest->pub.free_in_buffer > 0)
00346     {
00347         uint32_t final_size = dest->info.m_actual_size - dest->pub.free_in_buffer;
00348         
00349         /* Set the new size */
00350         dest->info.m_final_size = final_size;
00351     }
00352     
00353     DEBUG_PRINT("private-%p:a(%d):f(%d)\n",
00354              dest->info.m_buffer,
00355              dest->info.m_actual_size,
00356              dest->info.m_final_size);
00357     
00358     DEBUG_PRINT("public(after)-%p:%d\n",
00359              dest->pub.next_output_byte,
00360              dest->pub.free_in_buffer);
00361     
00362     dest->info.m_state = phJPEG_FINISHED;
00363     dest->pub.next_output_byte = NULL;
00364     dest->pub.free_in_buffer = 0;
00365 }
00366 
00367 
00368 /* ---------------------------------------------------------------------------
00369  * Prepare for output to a memory location.
00370  * If the dst pointer's value is NULL (i.e. *dst == NULL), 
00371  *  the memory will be allocated here using calloc_func. 
00372  *  'size' here tells the method
00373  *
00374  * If the dest pointer's value isn't NULL (i.e. *dst != NULL), 
00375  *  this method will not allocate memory. 'size' here tells
00376  *  how much room there is in the buffer. If at any time more memory
00377  *  is required, realloc will be called. If more memory is present in the
00378  *  buffer than required, it isn't truncated. The size can be retreived
00379  *  after 'finish' is called using 'jpeg_final_size'
00380  *
00381  * If calloc_func is NULL, the default calloc is used.
00382  * If realloc_func is NULL, the default realloc is used.
00383  * ------------------------------------------------------------------------ */
00384 void ph_jpeg_mem_dest ( ph_cinfo_handle cinfoptr, 
00385                         uint8_t         **pdst,
00386                         uint32_t        *pdstsize,
00387                         ph_malloc_func   mem_malloc,
00388                         ph_realloc_func  mem_realloc
00389                         )
00390     
00391 {
00392     phFUNCTION("ph_jpeg_mem_dest")
00393 
00394     ph_dest_ptr dest        = NULL;
00395 
00396     
00397     /* ~pthoren: Comment not quite accurate, change from stdio to mem */
00398   
00399     /* The destination object is made permanent so that multiple JPEG images
00400      * can be written to the same file without re-executing jpeg_stdio_dest.
00401      * This makes it dangerous to use this manager and a different destination
00402      * manager serially with the same JPEG object, because their private object
00403      * sizes may be different.  Caveat programmer.
00404      */
00405 
00406     j_compress_ptr cinfo = (j_compress_ptr)cinfoptr;
00407 
00408     if (cinfo->dest == NULL) 
00409     {
00410         /* first time for this JPEG object? */
00411         cinfo->dest = (struct jpeg_destination_mgr *)
00412             (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00413                                         sizeof(ph_destination_mgr));
00414         phMemset(cinfo->dest,0,sizeof(ph_destination_mgr));
00415     }
00416     
00417     dest = (ph_dest_ptr) cinfo->dest;
00418 
00419     rc = ph_mem_info_init(&(dest->info),
00420                           pdst,
00421                           pdstsize,
00422                           mem_malloc,
00423                           mem_realloc,
00424                           phJPEG_DEST );
00425     phPRINT_RC(rc,NULL,"ph_mem_info_init");
00426 
00427     DEBUG_PRINT("%p(%p):%p(%d)\n",pdst,*pdst,pdstsize,*pdstsize);
00428     
00429     dest->pub.init_destination    = ph_jpeg_init_destination;
00430     dest->pub.empty_output_buffer = ph_jpeg_empty_output_buffer;
00431     dest->pub.term_destination    = ph_jpeg_term_destination;
00432 
00433     /* These are set in init_destination */
00434     dest->pub.next_output_byte = NULL;
00435     dest->pub.free_in_buffer = 0;
00436 }
00437 
00438 /* ---------------------------------------------------------------------------
00439  * *** END OF cjpeg COPYING ***
00440  * ------------------------------------------------------------------------ */
00441 
00442 
00443 static int ph_mem_info_init( ph_mem_info       *info,
00444                              uint8_t          **pdst,
00445                              uint32_t          *sizeptr,
00446                              ph_malloc_func     mem_malloc,
00447                              ph_realloc_func    mem_realloc,
00448                              /* phJPEG_SOURCE, phJPEG_DEST */
00449                              int                info_type 
00450                              )
00451 {
00452     phFUNCTION("ph_mem_info_init")
00453 
00454     int realloc_possible    = 1;
00455     uint32_t    size        = 0;
00456     
00457     DEBUG_PRINT("info:%p,pdst:%p(%p),psize:%p(%d),malloc:%p,realloc:%p,type:0x%08x\n",
00458             info,
00459             pdst,*pdst,
00460             sizeptr,*sizeptr,
00461             mem_malloc,
00462             mem_realloc,
00463             info_type  );
00464  
00465     /* This shouldn't happen. However, it might if someone is playing around
00466      * with allocated information instead of a pointer to a piece of info 
00467      * on the stack */
00468     if (info == NULL) return -1;
00469     if ((info_type != phJPEG_SOURCE) && (info_type != phJPEG_DEST)) return -1;
00470 
00471     /* Assign the malloc function pointer to the user supplied malloc */
00472     if (mem_malloc != NULL)
00473     {
00474         info->m_malloc = mem_malloc;
00475     }
00476     
00477     /* Assign the malloc function pointer to the default malloc */
00478     if (info->m_malloc == NULL)
00479     {
00480         info->m_malloc = (ph_malloc_func)malloc;
00481     }
00482     
00483     /* Assign the realloc function pointer to the user supplied realloc */
00484     if (mem_realloc != NULL)
00485     {
00486         info->m_realloc = mem_realloc;
00487     }
00488  
00489     /* Assign the realloc function pointer to the default realloc */
00490     if (info->m_realloc == NULL)
00491     {
00492         info->m_realloc = (ph_realloc_func)realloc;
00493     }
00494     
00495     /* If the input size pointer is available, use it */
00496     if (sizeptr != NULL)
00497     {
00498         size = *sizeptr;
00499     }
00500     else if (info_type == phJPEG_SOURCE)
00501     {
00502         /* TODO: return -1 */
00503         phERR_PRINT("phJPEG_SOURCE specified without a size.\n");
00504     }
00505     
00506     /* if the size is 0, and this is an initialization call, set size
00507      * to a default value. If size stays 0, the compress-jpeg object
00508      * will use the memory that has already been allocated. If the
00509      * size has changed in size, the data will be realloc'd below. */
00510     if (size == 0)
00511     {
00512         size = phJPEG_DEFAULT_SIZE;
00513         realloc_possible = 1;
00514     }
00515     
00516     /* Initialize the pointer to the buffer */
00517     /* m_buffer will be NULL the first time through this function if this
00518      * isn't used. Otherwise, if this function has already been called, then
00519      * m_buffer will not be NULL. It may require resizing or mallocing below. */
00520     if (pdst != NULL)
00521     {
00522         info->m_buffer  = *pdst;
00523     }
00524     else if (info_type == phJPEG_SOURCE)
00525     {
00526         /* TODO: return -1 */
00527         phERR_PRINT("phJPEG_SOURCE specified without any input memory\n");
00528     }
00529     
00530     /* If the buffer was passed as NULL; size will not be 0 */
00531     if (info->m_buffer == NULL)
00532     {
00533         DEBUG_PRINT("malloc\n");
00534         /* Make sure size is valid */
00535         info->m_buffer = (info->m_malloc)(size);
00536         if (info->m_buffer == NULL)
00537         {
00538             phERR_PRINT("malloc:info->m_buffer == NULL\n");
00539         }
00540         if (info_type == phJPEG_DEST) 
00541         {
00542             phMemset(info->m_buffer,0,info->m_actual_size);
00543         }
00544     
00545     }
00546     /* We'll only execute here if the size passed in was 
00547      * 0 and the pointer wasn't NULL. Try to realloc the thing */
00548     else if ((info->m_buffer != NULL) && (realloc_possible))
00549     {
00550         DEBUG_PRINT("realloc\n");
00551         info->m_buffer = (info->m_realloc)(info->m_buffer,size);
00552         if (info->m_buffer == NULL)
00553         {
00554             phERR_PRINT("realloc:info->m_buffer == NULL\n");
00555         }
00556         if (info_type == phJPEG_DEST) 
00557         {
00558             phMemset(info->m_buffer,0,size);
00559         }
00560     }
00561 
00562     /* These should agree by this point. It is possible the
00563      * user passed a bogus size though. If it's bigger than
00564      * the actual data buffer, problems/segfaults  may occur. 
00565      * If it's smaller, then there's a good chance it will be
00566      * realloced to fit larger memory. */
00567     info->m_actual_size    = size;
00568     
00569     /* Set the memory return pointer */
00570     if (pdst != NULL)
00571     {
00572         *pdst = info->m_buffer;
00573     }
00574 
00575     /* Set the size return pointer */
00576     if (sizeptr != NULL) 
00577     {
00578         *sizeptr = info->m_actual_size;
00579     }   
00580    
00581     /* dst size is always going to be <= to actual size */
00582     info->m_final_size = info->m_actual_size;
00583   
00584     /* -1 == not started */
00585     /* 0 == started */
00586     /* 1 == finished */
00587     info->m_state = phJPEG_INITED;
00588 
00589     /* Init the safety mechanism if the fill_input_buffer method is 
00590      * called on a source manager's object */
00591     info->m_eoi_buffer[0] = (JOCTET) 0xFF;
00592     info->m_eoi_buffer[1] = (JOCTET) JPEG_EOI;
00593     
00594     /* 0 == phSUCCESS */
00595     return 0;
00596 }    
00597 
00598 /* ------------------------------------------------------------------------ */
00599 uint32_t ph_jpeg_dest_mem_size( ph_cinfo_handle cinfoptr )
00600 {
00601     phFUNCTION("ph_jpeg_dest_mem_size")
00602     j_compress_ptr  cinfo = NULL;
00603     ph_dest_ptr     dest = NULL;
00604 
00605     if (cinfoptr == NULL) return 0;
00606     
00607     cinfo = (j_compress_ptr)cinfoptr;
00608     dest = (ph_dest_ptr) cinfo->dest;
00609 
00610     if (dest->info.m_state == phJPEG_FINISHED)
00611     {
00612         DEBUG_PRINT("final_size:%d\n",dest->info.m_final_size);
00613         return dest->info.m_final_size;
00614     }
00615     else
00616     {
00617         DEBUG_PRINT("actual_size:%d\n",dest->info.m_actual_size);
00618         return dest->info.m_actual_size;
00619     }
00620 
00621     return 0;
00622 }
00623 
00624 /* ------------------------------------------------------------------------ */
00625 uint8_t  *ph_jpeg_dest_mem_ptr( ph_cinfo_handle cinfoptr )
00626 {
00627     phFUNCTION("ph_jpeg_dest_mem_ptr")
00628     j_compress_ptr  cinfo = NULL;
00629     ph_dest_ptr     dest = NULL;
00630 
00631    
00632     if (cinfoptr == NULL) return NULL;
00633 
00634     cinfo = (j_compress_ptr)cinfoptr;
00635     dest = (ph_dest_ptr) cinfo->dest;
00636 
00637     DEBUG_PRINT("buffer:%p\n",dest->info.m_buffer );
00638     
00639     return dest->info.m_buffer;
00640 }
00641 
00642 #if 0
00643 /* ------------------------------------------------------------------------ */
00644 uint32_t ph_jpeg_src_mem_size( ph_cinfo_handle cinfoptr )
00645 {
00646     phFUNCTION("ph_jpeg_src_mem_size")
00647     j_decompress_ptr  cinfo = NULL;
00648     ph_src_ptr     src = NULL;
00649 
00650     
00651     if (cinfoptr == NULL) return 0;
00652 
00653     cinfo = (j_decompress_ptr )cinfoptr;
00654     src = (ph_src_ptr) cinfo->src;
00655 
00656     DEBUG_PRINT("actual_size:%d\n",src->info.m_actual_size);
00657     
00658     return src->info.m_actual_size;
00659 }
00660 
00661 /* ------------------------------------------------------------------------ */
00662 uint8_t  *ph_jpeg_src_mem_ptr( ph_cinfo_handle cinfoptr )
00663 {
00664     phFUNCTION("ph_jpeg_src_mem_ptr")
00665     j_decompress_ptr    cinfo = NULL;
00666     ph_src_ptr          src = NULL;
00667    
00668     if (cinfoptr == NULL) return NULL;
00669     
00670     cinfo = (j_decompress_ptr )cinfoptr;
00671     src = (ph_src_ptr) cinfo->src;
00672 
00673     DEBUG_PRINT("buffer:%p\n",src->info.m_buffer);
00674     return src->info.m_buffer;
00675 }
00676 #endif /* #if 0 */
00677 
00678 
00679 
00680 /* ---------------------------------------------------------------------------
00681  * Initialize source --- called by jpeg_read_header
00682  * before any data is actually read.
00683  * ---------------------------------------------------------------------------
00684  * From docjpeg/doc/jpeg/6b/jpeg-6b/libjpeg.txt:
00685  * 
00686  * Initialize source.  This is called by jpeg_read_header() before any
00687  * data is actually read.  Unlike init_destination(), it may leave
00688  * bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
00689  * will occur immediately).
00690  * ------------------------------------------------------------------------ */
00691 static void ph_init_source (j_decompress_ptr cinfo)
00692 {
00693     phFUNCTION("ph_init_source")
00694     
00695     /* ph_src_ptr src = (ph_src_ptr) cinfo->src; */
00696     
00697     /* We reset the empty-input-file flag for each image,
00698      * but we don't clear the input buffer.
00699      * This is correct behavior for reading a series of images from one source.
00700      */
00701     /* src->info.m_state = phJPEG_STARTED; */
00702 }
00703 
00704 /* ---------------------------------------------------------------------------
00705  * Fill the input buffer --- called whenever buffer is emptied.
00706  *
00707  * In typical applications, this should read fresh data into the buffer
00708  * (ignoring the current state of next_input_byte & bytes_in_buffer),
00709  * reset the pointer & count to the start of the buffer, and return TRUE
00710  * indicating that the buffer has been reloaded.  It is not necessary to
00711  * fill the buffer entirely, only to obtain at least one more byte.
00712  *
00713  * There is no such thing as an EOF return.  If the end of the file has been
00714  * reached, the routine has a choice of ERREXIT() or inserting fake data into
00715  * the buffer.  In most cases, generating a warning message and inserting a
00716  * fake EOI marker is the best course of action --- this will allow the
00717  * decompressor to output however much of the image is there.  However,
00718  * the resulting error message is misleading if the real problem is an empty
00719  * input file, so we handle that case specially.
00720  *
00721  * In applications that need to be able to suspend compression due to input
00722  * not being available yet, a FALSE return indicates that no more data can be
00723  * obtained right now, but more may be forthcoming later.  In this situation,
00724  * the decompressor will return to its caller (with an indication of the
00725  * number of scanlines it has read, if any).  The application should resume
00726  * decompression after it has loaded more data into the input buffer.  Note
00727  * that there are substantial restrictions on the use of suspension --- see
00728  * the documentation.
00729  *
00730  * When suspending, the decompressor will back up to a convenient restart point
00731  * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
00732  * indicate where the restart point will be if the current call returns FALSE.
00733  * Data beyond this point must be rescanned after resumption, so move it to
00734  * the front of the buffer rather than discarding it.
00735  * ---------------------------------------------------------------------------
00736  * From docjpeg/doc/jpeg/6b/jpeg-6b/libjpeg.txt:
00737  * 
00738  * This is called whenever bytes_in_buffer has reached zero and more
00739  * data is wanted.  In typical applications, it should read fresh data
00740  * into the buffer (ignoring the current state of next_input_byte and
00741  * bytes_in_buffer), reset the pointer & count to the start of the
00742  * buffer, and return TRUE indicating that the buffer has been reloaded.
00743  * It is not necessary to fill the buffer entirely, only to obtain at
00744  * least one more byte.  bytes_in_buffer MUST be set to a positive value
00745  * if TRUE is returned.  A FALSE return should only be used when I/O
00746  * suspension is desired (this mode is discussed in the next section).
00747  * ------------------------------------------------------------------------ */
00748 static boolean ph_fill_input_buffer (j_decompress_ptr cinfo)
00749 {
00750     phFUNCTION("ph_fill_input_buffer")
00751 
00752     ph_src_ptr src = (ph_src_ptr) cinfo->src;
00753 
00754     if (src->info.m_state == phJPEG_INITED)
00755     {
00756         src->info.m_state = phJPEG_STARTED;
00757         
00758         src->pub.next_input_byte = (JOCTET *)src->info.m_buffer;
00759         src->pub.bytes_in_buffer = src->info.m_actual_size;
00760     }
00761     else
00762     {
00763         /* This method should never be called because the whole file is in
00764          * * memory pointed to by the buffer */
00765         WARNMS(cinfo, JWRN_JPEG_EOF);
00766         
00767         /* Insert a fake EOI marker */
00768         src->pub.next_input_byte = src->info.m_eoi_buffer;
00769         src->pub.bytes_in_buffer = 2;
00770         
00771         src->info.m_state = phJPEG_FINISHED;
00772     }
00773     
00774     return TRUE;
00775 }
00776 
00777 
00778 /* ---------------------------------------------------------------------------
00779  * Skip data --- used to skip over a potentially large amount of
00780  * uninteresting data (such as an APPn marker).
00781  *
00782  * Writers of suspendable-input applications must note that skip_input_data
00783  * is not granted the right to give a suspension return.  If the skip extends
00784  * beyond the data currently in the buffer, the buffer can be marked empty so
00785  * that the next read will cause a fill_input_buffer call that can suspend.
00786  * Arranging for additional bytes to be discarded before reloading the input
00787  * buffer is the application writer's problem.
00788  * ---------------------------------------------------------------------------
00789  * From docjpeg/doc/jpeg/6b/jpeg-6b/libjpeg.txt:
00790  * 
00791  * Skip num_bytes worth of data.  The buffer pointer and count should
00792  * be advanced over num_bytes input bytes, refilling the buffer as
00793  * needed.  This is used to skip over a potentially large amount of
00794  * uninteresting data (such as an APPn marker).  In some applications
00795  * it may be possible to optimize away the reading of the skipped data,
00796  * but it's not clear that being smart is worth much trouble; large
00797  * skips are uncommon.  bytes_in_buffer may be zero on return.
00798  * A zero or negative skip count should be treated as a no-op.
00799  * ------------------------------------------------------------------------ */
00800 static void ph_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
00801 {
00802     phFUNCTION("ph_skip_input_data")
00803     
00804     ph_src_ptr src = (ph_src_ptr) cinfo->src;
00805     
00806     if (num_bytes > 0) 
00807     {
00808         src->pub.next_input_byte += (size_t) num_bytes;
00809         src->pub.bytes_in_buffer -= (size_t) num_bytes;
00810     }
00811 }
00812 
00813 
00814 /* ---------------------------------------------------------------------------
00815  * An additional method that can be provided by data source modules is the
00816  * resync_to_restart method for error recovery in the presence of RST markers.
00817  * For the moment, this source module just uses the default resync method
00818  * provided by the JPEG library.  That method assumes that no backtracking
00819  * is possible.
00820  * ---------------------------------------------------------------------------
00821  * From docjpeg/doc/jpeg/6b/jpeg-6b/libjpeg.txt:
00822  * 
00823  * This routine is called only when the decompressor has failed to find
00824  * a restart (RSTn) marker where one is expected.  Its mission is to
00825  * find a suitable point for resuming decompression.  For most
00826  * applications, we recommend that you just use the default resync
00827  * procedure, jpeg_resync_to_restart().  However, if you are able to back
00828  * up in the input data stream, or if you have a-priori knowledge about
00829  * the likely location of restart markers, you may be able to do better.
00830  * Read the read_restart_marker() and jpeg_resync_to_restart() routines
00831  * in jdmarker.c if you think you'd like to implement your own resync
00832  * procedure.
00833  * ------------------------------------------------------------------------ */
00834 
00835 
00836 /* ---------------------------------------------------------------------------
00837  * Terminate source --- called by jpeg_finish_decompress
00838  * after all data has been read.  Often a no-op.
00839  *
00840  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
00841  * application must deal with any cleanup that should happen even
00842  * for error exit.
00843  * ---------------------------------------------------------------------------
00844  * From docjpeg/doc/jpeg/6b/jpeg-6b/libjpeg.txt:
00845  * 
00846  * Terminate source --- called by jpeg_finish_decompress() after all
00847  * data has been read.  Often a no-op.
00848  * ------------------------------------------------------------------------ */
00849 static void ph_term_source (j_decompress_ptr cinfo)
00850 {
00851     phFUNCTION("ph_term_source")
00852 
00853     ph_src_ptr src = (ph_src_ptr) cinfo->src;
00854 
00855     src->info.m_state = phJPEG_FINISHED;    
00856     src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
00857     src->pub.next_input_byte = NULL; /* until buffer loaded */
00858 }
00859 
00860 
00861 /* ---------------------------------------------------------------------------
00862  * Prepare for input from a stdio stream.
00863  * The caller must have already opened the stream, and is responsible
00864  * for closing it after finishing decompression.
00865  * ------------------------------------------------------------------------ */
00866 void ph_jpeg_mem_source(ph_cinfo_handle cinfoptr, 
00867                         uint8_t         *srcmem,
00868                         uint32_t        size,
00869                         ph_malloc_func  mem_malloc,
00870                         ph_realloc_func mem_realloc
00871                         )
00872     
00873 {
00874     phFUNCTION("ph_jpeg_mem_source")
00875 
00876     ph_src_ptr src;
00877     
00878     /* The source object and input buffer are made permanent so that a series
00879      * of JPEG images can be read by calling ph_jpeg_mem_source
00880      * only before the first one.  (If we discarded the buffer at the end of
00881      * one image, we'd likely lose the start of the next one.)
00882      * This makes it unsafe to use this manager and a different source
00883      * manager serially with the same JPEG object.  Caveat programmer.
00884      */
00885     j_decompress_ptr cinfo = (j_decompress_ptr )cinfoptr;
00886     
00887     /* first time for this JPEG object? */
00888     if (cinfo->src == NULL) 
00889     {
00890         cinfo->src = (struct jpeg_source_mgr *)
00891             (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00892                                         sizeof(ph_source_mgr));
00893         phMemset(cinfo->src,0,sizeof(ph_source_mgr));
00894     }
00895     
00896     src = (ph_src_ptr) cinfo->src;
00897     
00898     rc = ph_mem_info_init(&(src->info),
00899                           &srcmem,
00900                           &size,
00901                           mem_malloc,
00902                           mem_realloc,
00903                           phJPEG_SOURCE );
00904     phPRINT_RC(rc,NULL,"ph_mem_info_init");
00905     
00906     src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
00907     src->pub.next_input_byte = NULL; /* until buffer loaded */
00908     
00909     /* Set the function pointers */
00910     src->pub.init_source          = ph_init_source;
00911     src->pub.fill_input_buffer    = ph_fill_input_buffer;
00912     src->pub.skip_input_data      = ph_skip_input_data;
00913     src->pub.resync_to_restart    = jpeg_resync_to_restart; /* use default method */
00914     src->pub.term_source          = ph_term_source;
00915 }
00916 
00917 /* ------------------------------------------------------------------------- */
00918 /* This will be for error checking in the future */
00919 /* ------------------------------------------------------------------------- */
00920 #define phJPEG_DECOMPRESS 1
00921 #define phJPEG_COMPRESS 2
00922 
00923 typedef struct ph_jpeg_struct_t
00924 {
00925     int type;
00926 } ph_jpeg_struct;
00927 
00928 typedef struct ph_jpeg_compress_struct_t
00929 {
00930     ph_jpeg_struct id;
00931     struct jpeg_compress_struct cinfo;
00932 } ph_jpeg_compress_type;
00933 
00934 typedef struct ph_jpeg_decompress_struct_t
00935 {
00936     ph_jpeg_struct id;
00937     struct jpeg_decompress_struct cinfo;
00938 } ph_jpeg_decompress_type;
00939 
00940 /* ------------------------------------------------------------------------- */
00941 struct ph_jpeg_compress_struct {
00942     struct jpeg_compress_struct cinfo;
00943     struct jpeg_error_mgr jerr;
00944 };
00945 struct ph_jpeg_decompress_struct {
00946     struct jpeg_decompress_struct cinfo;
00947     struct jpeg_error_mgr jerr;
00948 };
00949 /* ------------------------------------------------------------------------- */
00950 int ph_jpeg_new_compress( ph_cinfo_handle *compress_info )
00951 {
00952     phFUNCTION("ph_jpeg_new_compress")
00953 
00954     if (compress_info != NULL)
00955     {
00956         struct ph_jpeg_compress_struct *ph_cinfo = 
00957                     phCalloc(1,sizeof(struct ph_jpeg_compress_struct));
00958 
00959         phCHECK_NULLPTR(ph_cinfo,"phCalloc","failed to allocate cinfo struct.");
00960   
00961         /* Initialize the JPEG compression object with default error handling. */
00962         ph_cinfo->cinfo.err = jpeg_std_error(&(ph_cinfo->jerr));
00963 
00964         /* Create the compression object */
00965         jpeg_create_compress(&(ph_cinfo->cinfo));
00966 
00967             
00968         ph_cinfo->cinfo.in_color_space = JCS_RGB;
00969         ph_cinfo->cinfo.input_components = 3;
00970         ph_cinfo->cinfo.data_precision = 8;
00971         
00972         /* Set the image defaults */
00973         jpeg_set_defaults(&(ph_cinfo->cinfo));
00974 
00975         *compress_info = (void *)ph_cinfo;
00976     }
00977     else
00978     {
00979         phERR_PRINT("compress_info == NULL\n");
00980         return phFAIL;
00981     }
00982 
00983     return phSUCCESS;
00984 
00985 error:
00986     return phFAIL;
00987 }
00988 
00989 /* ------------------------------------------------------------------------- */
00990 #define IMAGE_JPEG_WRITE_TEMPJPEG() 0
00991 #if IMAGE_JPEG_WRITE_TEMPJPEG()
00992 static int totaljpegs = 0;
00993 #endif
00994 /* ------------------------------------------------------------------------- */
00995 int ph_jpeg_compress( ph_cinfo_handle   compress_info,
00996                       uint8_t           *src,
00997                       uint32_t          srcsize,
00998                       uint32_t          width,
00999                       uint32_t          height,
01000                       int32_t           format,
01001                       int               quality,
01002                       uint8_t           **pdst,
01003                       uint32_t          *pdstsize )
01004 {
01005     phFUNCTION("ph_jpeg_compress")
01006 
01007     struct jpeg_compress_struct *cinfo = NULL;
01008     int call_finish_compress = 0;
01009     int call_default_colorspace = 0;
01010     /* int i = 0; */
01011 
01012     /* No special flag bits are allowed */
01013     if (format & phImageSpecialMask)
01014     {
01015         phERR_PRINT("A special flag is specified in format\n");
01016         return phFAIL;
01017     }
01018 
01019     if (pdst == NULL)
01020     {
01021         phERR_PRINT("pdst == NULL\n");
01022         return phFAIL;
01023     }
01024     
01025     if (pdstsize == NULL)
01026     {
01027         phERR_PRINT("pdstsize == NULL\n");
01028         return phFAIL;
01029     }
01030     
01031     if (compress_info != NULL)
01032     {
01033         uint32_t    width_bytes     = 1;
01034         uint32_t    row_stride      = 0;
01035         JDIMENSION  num_scanlines   = 0;
01036         int         rows_height     = 1;
01037         JSAMPROW    rows[1]          = { NULL };
01038 
01039 #if IMAGE_JPEG_WRITE_TEMPJPEG()
01040         FILE *tempjpeg = NULL;
01041         char filename[255];
01042         int32_t nbytes = 0;
01043         int32_t bytes_left = 0;
01044         uint8_t *dstptr = NULL;
01045 #endif /* IMAGE_JPEG_WRITE_TEMPJPEG */
01046         
01047         cinfo = (struct jpeg_compress_struct *)compress_info;
01048 
01049         /* Initialize cinfo compression parameters */
01050         cinfo->image_height = height;
01051         cinfo->image_width = width;
01052         
01053         /* Check the Phission format and set the fields appropriately */
01054         if (format & phImageRGB24)
01055         {
01056             if ((cinfo->in_color_space != JCS_RGB) ||
01057                 (cinfo->input_components != 3))
01058             {
01059                 cinfo->in_color_space = JCS_RGB;
01060                 cinfo->input_components = 3;
01061 
01062                 call_default_colorspace = 1;
01063             }
01064 
01065             width_bytes = 3;
01066         }
01067         else if (format & phImageGREY8)
01068         {
01069             if ((cinfo->in_color_space != JCS_GRAYSCALE) ||
01070                 (cinfo->input_components != 1))
01071             {
01072                 cinfo->in_color_space = JCS_GRAYSCALE;
01073                 cinfo->input_components = 1;
01074 
01075                 call_default_colorspace = 1;
01076             }
01077             width_bytes = 1;
01078         }
01079         else
01080         {
01081             phERR_PRINT("Invalid input format.\n");
01082             return phFAIL;
01083         }
01084        
01085         DEBUG_PRINT("ih:%d,iw:%d,nc:%d\n",
01086                  cinfo->image_height,
01087                  cinfo->image_width,
01088                  cinfo->input_components);
01089 
01090         /* Only call this if the color spaces aren't the same as theiry
01091          * current settings were */
01092         if (call_default_colorspace)
01093         {
01094             /* Set the image defaults */
01095             /* Can we call this here ? *
01096              */
01097             jpeg_set_defaults(cinfo);
01098 
01099             /* Now that we know input colorspace, 
01100              * fix colorspace-dependent defaults */
01101             jpeg_default_colorspace(cinfo);
01102         }
01103 
01104         jpeg_set_quality(cinfo,quality,FALSE);
01105         
01106         /* Specify data destination for compression */
01107         /* 
01108          void ph_jpeg_mem_dest (ph_cinfo_handle cinfo, 
01109                                 uint8_t         **pdst,
01110                                 uint32_t        *pdstsize,
01111                                 ph_malloc_func   mem_malloc,
01112                                 ph_realloc_func  mem_realloc
01113                                 );
01114         */
01115         ph_jpeg_mem_dest(compress_info,
01116                          pdst,
01117                          pdstsize,
01118                          NULL,
01119                          NULL);
01120 
01121         /* Start compressor */
01122         jpeg_start_compress(cinfo, TRUE);
01123         call_finish_compress = 1;
01124 
01125         /* Process data */
01126         row_stride = width_bytes * cinfo->image_width;
01127         while (cinfo->next_scanline < cinfo->image_height) 
01128         {
01129             rows[0] = (JSAMPROW)&(src[row_stride * cinfo->next_scanline]);
01130         
01131             DEBUG_PRINT("%p\n",rows[0]);
01132             DEBUG_PRINT("next:%d,height:%d\n",
01133                      cinfo->next_scanline,
01134                      cinfo->image_height);
01135             
01136             num_scanlines = jpeg_write_scanlines(cinfo, 
01137                                                  rows, 
01138                                                  rows_height );
01139         }
01140         
01141         (void) jpeg_finish_compress(cinfo);
01142         call_finish_compress = 0;
01143 
01144         /* Incase the destination manager altered the dest values,
01145          * check and be sure they are updated in the return pointers*/
01146         *pdst = ph_jpeg_dest_mem_ptr(cinfo);
01147         *pdstsize = ph_jpeg_dest_mem_size(cinfo);
01148         DEBUG_PRINT("%p:%d\n", *pdst, *pdstsize);
01149 
01150 #if IMAGE_JPEG_WRITE_TEMPJPEG()
01151         /* Save the jpeg file */
01152         /* WARNING: not thread safe */
01153         sprintf(filename,"temp_%d.jpg",totaljpegs);
01154         tempjpeg = fopen(filename,"w+");
01155         if (tempjpeg == NULL)
01156         {
01157             phPRINT_RC(-1,"fopen","fopen for temp jpeg failed");
01158         }
01159         
01160         bytes_left = *pdstsize;
01161         dstptr = *pdst;
01162         do
01163         {
01164             nbytes = fwrite(dstptr,  
01165                             sizeof(uint8_t),  
01166                             bytes_left,
01167                             tempjpeg);
01168             bytes_left -= nbytes;
01169             dstptr += nbytes;
01170         } while (bytes_left > 0);
01171         totaljpegs++;
01172 
01173         fclose(tempjpeg);
01174 #endif /* IMAGE_JPEG_WRITE_TEMPJPEG */
01175         
01176     }
01177     else
01178     {
01179         phERR_PRINT("compress_info == NULL\n");
01180         return phFAIL;
01181     }
01182     
01183     return phSUCCESS;
01184 error:
01185     if (call_finish_compress)
01186     {
01187         if (cinfo != NULL)
01188         {
01189             (void) jpeg_finish_compress(cinfo);
01190             call_finish_compress = 0;
01191         }
01192     }
01193 
01194     return phFAIL;
01195 }
01196 
01197 /* ------------------------------------------------------------------------- */
01198 int ph_jpeg_free_compress( ph_cinfo_handle *compress_info )
01199 {
01200     phFUNCTION("ph_jpeg_free_compress")
01201 
01202     if (compress_info != NULL)
01203     {
01204         struct ph_jpeg_compress_struct *ph_cinfo = 
01205             (struct ph_jpeg_compress_struct *)*compress_info;
01206         struct jpeg_compress_struct *cinfo = 
01207             (struct jpeg_compress_struct *)&(ph_cinfo->cinfo);
01208         
01209         jpeg_destroy_compress(cinfo);
01210         
01211         phMemset(*compress_info,0,sizeof(struct ph_jpeg_compress_struct));
01212         phFree(*compress_info);
01213     }
01214 
01215     return phSUCCESS;
01216 }
01217 
01218 /* ------------------------------------------------------------------------- */
01219 /* ------------------------------------------------------------------------- */
01220 int ph_jpeg_new_decompress( ph_cinfo_handle *decompress_info )
01221 {
01222     phFUNCTION("ph_jpeg_new_decompress")
01223 
01224     if (decompress_info != NULL)
01225     {
01226         struct ph_jpeg_decompress_struct *ph_cinfo = 
01227                     phCalloc(1,sizeof(struct ph_jpeg_decompress_struct));
01228 
01229         phCHECK_NULLPTR(ph_cinfo,"phCalloc","failed to allocate cinfo struct.");
01230   
01231         /* Initialize the JPEG decompression object with default error handling. */
01232         ph_cinfo->cinfo.err = jpeg_std_error(&(ph_cinfo->jerr));
01233 
01234         /* Create the decompression object */
01235         jpeg_create_decompress(&(ph_cinfo->cinfo));
01236 
01237         *decompress_info = (void *)ph_cinfo;
01238     }
01239     else
01240     {
01241         phERR_PRINT("decompress_info == NULL\n");
01242         return phFAIL;
01243     }
01244 
01245     return phSUCCESS;
01246 error:
01247     return phFAIL;
01248 }
01249 
01250 /* ------------------------------------------------------------------------- */
01251 int ph_jpeg_decompress( ph_cinfo_handle decompress_info,
01252                         uint8_t         *src,
01253                         uint32_t        srcsize,
01254                         uint8_t         **pdst,
01255                         uint32_t        *pdstsize,
01256                         uint32_t        *pwidth,
01257                         uint32_t        *pheight,
01258                         int32_t         *pformat )
01259 {
01260     phFUNCTION("ph_jpeg_decompress")
01261 
01262     struct jpeg_decompress_struct *cinfo = NULL;
01263     int call_finish_decompress = 0;
01264 
01265     DEBUG_PRINT("%p,%p,%d,%p(%p),%p(%d),%p(%d),%p(%d),%p(0x%08x)\n",
01266              decompress_info,
01267              src,
01268              srcsize,
01269              pdst,*pdst,
01270              pdstsize,*pdstsize,
01271              pwidth,*pwidth,
01272              pheight,*pheight,
01273              pformat, *pformat );
01274 
01275     if (decompress_info != NULL)
01276     {
01277         uint32_t    width_bytes     = 0;
01278         uint8_t     *dstptr         = NULL;
01279         JDIMENSION  num_scanlines   = 0;
01280         int         rows_height     = 1;
01281         JSAMPROW    rows[1]          = { NULL };
01282     
01283         cinfo = (struct jpeg_decompress_struct *)decompress_info;
01284 
01285         /* 
01286          * void ph_jpeg_mem_source( ph_cinfo_handle cinfoptr, 
01287          *                          uint8_t         *srcmem,
01288          *                          uint32_t        size,
01289          *                          ph_malloc_func  mem_malloc,
01290          *                          ph_realloc_func mem_realloc
01291          *                          );                          */
01292         ph_jpeg_mem_source(decompress_info,
01293                            src,
01294                            srcsize,
01295                            NULL,
01296                            NULL);
01297 
01298         /* Read file header, set default decompression parameters */
01299         (void) jpeg_read_header(cinfo, TRUE);
01300         /*
01301             JDIMENSION image_width          Width and height of image
01302             JDIMENSION image_height
01303             int num_components              Number of color components
01304             J_COLOR_SPACE jpeg_color_space  Colorspace of image
01305             boolean saw_JFIF_marker         TRUE if a JFIF APP0 marker was seen
01306               UINT8 JFIF_major_version      Version information from JFIF marker
01307               UINT8 JFIF_minor_version
01308               UINT8 density_unit            Resolution data from JFIF marker
01309               UINT16 X_density
01310               UINT16 Y_density
01311             boolean saw_Adobe_marker        TRUE if an Adobe APP14 marker was seen
01312               UINT8 Adobe_transform         Color transform code from Adobe marker
01313          */
01314 
01315        
01316         /* Set up the destination buffer info, width, height, format */
01317         /* get the height and set the return pointer height */
01318         if (pheight != NULL)
01319         {
01320             *pheight = cinfo->image_height;
01321         }
01322         
01323         /* Get the width and set the return pointer width */
01324         if (pwidth != NULL)
01325         {
01326             *pwidth = cinfo->image_width;
01327         }
01328 
01329         /* Get the format and set the return pointer format */
01330         /* Since not all the JPEG output formats are supported,
01331          * let's use the *pformat format value to determine
01332          * the output from the decompression.
01333          * Everything defaults to RGB24 if it's unsupported. */
01334         if (pformat != NULL)
01335         {
01336             if (*pformat & phImageValidFormatMask)
01337             {
01338                 if (*pformat & phImageRGB24)
01339                 {
01340                     cinfo->out_color_space = JCS_RGB;
01341                 }
01342                 else if (*pformat & phImageGREY8)
01343                 {
01344                     cinfo->out_color_space = JCS_GRAYSCALE;
01345                 }
01346                 else
01347                 {
01348                     *pformat &= phImageValidFormatMask;
01349                     *pformat |= phImageRGB24;
01350                     cinfo->out_color_space = JCS_RGB;
01351                 }
01352             }
01353             else
01354             {
01355                 *pformat &= phImageValidFormatMask;
01356                 *pformat |= phImageRGB24;
01357                 cinfo->out_color_space = JCS_RGB;
01358             }
01359 #if 0
01360             switch (cinfo->jpeg_color_space)
01361             {
01362                 case JCS_RGB:
01363                     DEBUG_PRINT("phImageRGB24\n");
01364                     *pformat = phImageRGB24;
01365                     break;
01366                     
01367                 case JCS_GRAYSCALE:
01368                     DEBUG_PRINT("phImageGREY8\n");
01369                     *pformat = phImageGREY8;
01370                     break;
01371                 case JCS_YCbCr:
01372                     DEBUG_PRINT("phImageNOFORMAT:YCbCr\n");
01373                     *pformat = phImageNOFORMAT;
01374                     break;
01375                 case JCS_CMYK:
01376                     DEBUG_PRINT("phImageNOFORMAT:CMYK\n");
01377                     *pformat = phImageNOFORMAT;
01378                     break;
01379 
01380                 default:
01381                     DEBUG_PRINT("phImageNOFORMAT:default\n");
01382                     *pformat = phImageNOFORMAT;
01383                     //* TODO: error return ?? *
01384                     break;
01385             }            
01386 #endif
01387         }
01388         else
01389         {
01390             cinfo->out_color_space = JCS_RGB;
01391         }
01392         
01393         /* Make sure there is enough memory */
01394         if ((pdst != NULL) && (pdstsize != NULL))
01395         {
01396             uint32_t samples_per_row =   
01397                         cinfo->image_height *          /* height */
01398                         cinfo->image_width *           /* width */
01399                         cinfo->num_components; /* depth */
01400             DEBUG_PRINT("pdst:%p(%p),pdstsize:%p(%u)\n",
01401                      pdst,*pdst,pdstsize,*pdstsize );
01402             DEBUG_PRINT("spr:%u,h:%d,w:%d,nc/d:%d\n",
01403                      samples_per_row,
01404                      cinfo->image_height,
01405                      cinfo->image_width,
01406                      cinfo->num_components );
01407                      
01408             if (samples_per_row > 0)
01409             {
01410                 phDALLOC_RESIZE( *pdst, *pdstsize, samples_per_row, uint8_t);
01411             }
01412 
01413             /* Start decompressor */
01414             (void) jpeg_start_decompress(cinfo);
01415             call_finish_decompress = 1;
01416 
01417             dstptr = *pdst;
01418             width_bytes =   cinfo->output_width *           /* width */
01419                                cinfo->out_color_components; /* depth */
01420 
01421             /* Process data */
01422             while (cinfo->output_scanline < cinfo->output_height) 
01423             {
01424                 rows[0]  = (JSAMPROW)dstptr;
01425 
01426                 /* reads data right into the destination buffer */
01427                 num_scanlines = jpeg_read_scanlines(cinfo, 
01428                         rows,
01429                         rows_height);
01430                 if (num_scanlines > 0)
01431                 {
01432                     dstptr += width_bytes * num_scanlines;
01433                 }
01434             }
01435 
01436             (void) jpeg_finish_decompress(cinfo);
01437             call_finish_decompress = 0;
01438         }
01439         /* else ... don't decompress, just return the info */
01440     }
01441     else 
01442     {
01443         phERR_PRINT("decompress_info == NULL\n");
01444         return phFAIL;
01445     }
01446 
01447     return phSUCCESS;
01448 error:
01449     if (call_finish_decompress)
01450     {
01451         if (cinfo != NULL)
01452         {
01453             (void) jpeg_finish_decompress(cinfo);
01454             call_finish_decompress = 0;
01455         }        
01456     }
01457 
01458     return phFAIL;
01459 }
01460 
01461 /* ------------------------------------------------------------------------- */
01462 int ph_jpeg_free_decompress( ph_cinfo_handle *decompress_info )
01463 {
01464     phFUNCTION("ph_jpeg_free_decompress")
01465 
01466     if (decompress_info != NULL)
01467     {
01468         struct ph_jpeg_decompress_struct *ph_cinfo = 
01469             (struct ph_jpeg_decompress_struct *)*decompress_info;
01470         struct jpeg_decompress_struct *cinfo = 
01471             (struct jpeg_decompress_struct *)&ph_cinfo->cinfo;
01472         
01473         jpeg_destroy_decompress(cinfo);
01474 
01475         phMemset(*decompress_info,0,sizeof(struct ph_jpeg_decompress_struct));
01476         phFree(*decompress_info);
01477     }
01478 
01479     return phSUCCESS;
01480 }
01481 
01482 
01483 /* TODO: 
01484  * -code image file reading/writing routines; see djpeg/cjpeg
01485  * - move all bu tthe compress/decompress code into here as static functions
01486  *  */
01487 
01488 
01489 
01490 #ifdef __cplusplus
01491 };
01492 #endif /* __cplusplus */
01493 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:02 2007 for phission by  doxygen 1.4.4