llimagejpeg.cpp

Go to the documentation of this file.
00001 
00031 #include "linden_common.h"
00032 #include "stdtypes.h"
00033 
00034 #include "llimagejpeg.h"
00035 
00036 #include "llerror.h"
00037 
00038 LLImageJPEG::LLImageJPEG() 
00039         :
00040         LLImageFormatted(IMG_CODEC_JPEG),
00041         mOutputBuffer( NULL ),
00042         mOutputBufferSize( 0 ),
00043         mEncodeQuality( 75 )            // on a scale from 1 to 100
00044 {
00045 }
00046 
00047 LLImageJPEG::~LLImageJPEG()
00048 {
00049         llassert( !mOutputBuffer ); // Should already be deleted at end of encode.
00050         delete[] mOutputBuffer;
00051 }
00052 
00053 BOOL LLImageJPEG::updateData()
00054 {
00055         resetLastError();
00056 
00057         // Check to make sure that this instance has been initialized with data
00058         if (!getData() || (0 == getDataSize()))
00059         {
00060                 setLastError("Uninitialized instance of LLImageJPEG");
00061                 return FALSE;
00062         }
00063 
00065         // Step 1: allocate and initialize JPEG decompression object
00066 
00067         // This struct contains the JPEG decompression parameters and pointers to
00068         // working space (which is allocated as needed by the JPEG library).
00069         struct jpeg_decompress_struct cinfo;
00070         cinfo.client_data = this;
00071 
00072         struct jpeg_error_mgr jerr;
00073         cinfo.err = jpeg_std_error(&jerr);
00074         
00075         // Customize with our own callbacks
00076         jerr.error_exit =               &LLImageJPEG::errorExit;                        // Error exit handler: does not return to caller
00077         jerr.emit_message =             &LLImageJPEG::errorEmitMessage;         // Conditionally emit a trace or warning message
00078         jerr.output_message =   &LLImageJPEG::errorOutputMessage;       // Routine that actually outputs a trace or error message
00079 
00080         try
00081         {
00082                 // Now we can initialize the JPEG decompression object.
00083                 jpeg_create_decompress(&cinfo);
00084 
00086                 // Step 2: specify data source
00087                 // (Code is modified version of jpeg_stdio_src();
00088                 if (cinfo.src == NULL)
00089                 {       
00090                         cinfo.src = (struct jpeg_source_mgr *)
00091                                 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00092                                 sizeof(struct jpeg_source_mgr));
00093                 }
00094                 cinfo.src->init_source  =               &LLImageJPEG::decodeInitSource;
00095                 cinfo.src->fill_input_buffer =  &LLImageJPEG::decodeFillInputBuffer;
00096                 cinfo.src->skip_input_data =    &LLImageJPEG::decodeSkipInputData;
00097                 cinfo.src->resync_to_restart = jpeg_resync_to_restart; // For now, use default method, but we should be able to do better.
00098                 cinfo.src->term_source =                &LLImageJPEG::decodeTermSource;
00099 
00100                 cinfo.src->bytes_in_buffer =    getDataSize();
00101                 cinfo.src->next_input_byte =    getData();
00102                 
00104                 // Step 3: read file parameters with jpeg_read_header()
00105                 jpeg_read_header( &cinfo, TRUE );
00106 
00107                 // Data set by jpeg_read_header
00108                 setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
00109 
00110                 /*
00111                 // More data set by jpeg_read_header
00112                 cinfo.num_components;
00113                 cinfo.jpeg_color_space; // Colorspace of image
00114                 cinfo.saw_JFIF_marker;          // TRUE if a JFIF APP0 marker was seen
00115                 cinfo.JFIF_major_version;       // Version information from JFIF marker
00116                 cinfo.JFIF_minor_version;  //
00117                 cinfo.density_unit;             // Resolution data from JFIF marker
00118                 cinfo.X_density;
00119                 cinfo.Y_density;
00120                 cinfo.saw_Adobe_marker; // TRUE if an Adobe APP14 marker was seen
00121                 cinfo.Adobe_transform;     // Color transform code from Adobe marker
00122                 */
00123         }
00124         catch (int)
00125         {
00126                 jpeg_destroy_decompress(&cinfo);
00127 
00128                 return FALSE;
00129         }
00131         // Step 4: Release JPEG decompression object 
00132         jpeg_destroy_decompress(&cinfo);
00133 
00134         return TRUE;
00135 }
00136 
00137 // Initialize source --- called by jpeg_read_header
00138 // before any data is actually read.
00139 void LLImageJPEG::decodeInitSource( j_decompress_ptr cinfo )
00140 {
00141         // no work necessary here
00142 }
00143 
00144 // Fill the input buffer --- called whenever buffer is emptied.
00145 boolean LLImageJPEG::decodeFillInputBuffer( j_decompress_ptr cinfo )
00146 {
00147 //      jpeg_source_mgr* src = cinfo->src;
00148 //      LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00149 
00150         // Should never get here, since we provide the entire buffer up front.
00151         ERREXIT(cinfo, JERR_INPUT_EMPTY);
00152 
00153         return TRUE;
00154 }
00155 
00156 // Skip data --- used to skip over a potentially large amount of
00157 // uninteresting data (such as an APPn marker).
00158 //
00159 // Writers of suspendable-input applications must note that skip_input_data
00160 // is not granted the right to give a suspension return.  If the skip extends
00161 // beyond the data currently in the buffer, the buffer can be marked empty so
00162 // that the next read will cause a fill_input_buffer call that can suspend.
00163 // Arranging for additional bytes to be discarded before reloading the input
00164 // buffer is the application writer's problem.
00165 void LLImageJPEG::decodeSkipInputData (j_decompress_ptr cinfo, long num_bytes)
00166 {
00167         jpeg_source_mgr* src = cinfo->src;
00168 //      LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00169 
00170     src->next_input_byte += (size_t) num_bytes;
00171     src->bytes_in_buffer -= (size_t) num_bytes;
00172 }
00173 
00174 void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
00175 {
00176   // no work necessary here
00177 }
00178 
00179 
00180 BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
00181 {
00182         llassert_always(raw_image);
00183         
00184         resetLastError();
00185         
00186         // Check to make sure that this instance has been initialized with data
00187         if (!getData() || (0 == getDataSize()))
00188         {
00189                 setLastError("LLImageJPEG trying to decode an image with no data!");
00190                 return FALSE;
00191         }
00192         
00193         S32 row_stride = 0;
00194         U8* raw_image_data = NULL;
00195 
00197         // Step 1: allocate and initialize JPEG decompression object
00198 
00199         // This struct contains the JPEG decompression parameters and pointers to
00200         // working space (which is allocated as needed by the JPEG library).
00201         struct jpeg_decompress_struct cinfo;
00202 
00203         struct jpeg_error_mgr jerr;
00204         cinfo.err = jpeg_std_error(&jerr);
00205         
00206         // Customize with our own callbacks
00207         jerr.error_exit =               &LLImageJPEG::errorExit;                        // Error exit handler: does not return to caller
00208         jerr.emit_message =             &LLImageJPEG::errorEmitMessage;         // Conditionally emit a trace or warning message
00209         jerr.output_message =   &LLImageJPEG::errorOutputMessage;       // Routine that actually outputs a trace or error message
00210         
00211 
00212         try
00213         {
00214                 // Now we can initialize the JPEG decompression object.
00215                 jpeg_create_decompress(&cinfo);
00216 
00218                 // Step 2: specify data source
00219                 // (Code is modified version of jpeg_stdio_src();
00220                 if (cinfo.src == NULL)
00221                 {       
00222                         cinfo.src = (struct jpeg_source_mgr *)
00223                                 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00224                                 sizeof(struct jpeg_source_mgr));
00225                 }
00226                 cinfo.src->init_source  =               &LLImageJPEG::decodeInitSource;
00227                 cinfo.src->fill_input_buffer =  &LLImageJPEG::decodeFillInputBuffer;
00228                 cinfo.src->skip_input_data =    &LLImageJPEG::decodeSkipInputData;
00229                 cinfo.src->resync_to_restart = jpeg_resync_to_restart; // For now, use default method, but we should be able to do better.
00230                 cinfo.src->term_source =                &LLImageJPEG::decodeTermSource;
00231                 cinfo.src->bytes_in_buffer =    getDataSize();
00232                 cinfo.src->next_input_byte =    getData();
00233                 
00235                 // Step 3: read file parameters with jpeg_read_header()
00236                 
00237                 jpeg_read_header(&cinfo, TRUE);
00238 
00239                 // We can ignore the return value from jpeg_read_header since
00240                 //   (a) suspension is not possible with our data source, and
00241                 //   (b) we passed TRUE to reject a tables-only JPEG file as an error.
00242                 // See libjpeg.doc for more info.
00243 
00244                 setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
00245 
00246                 raw_image->resize(getWidth(), getHeight(), getComponents());
00247                 raw_image_data = raw_image->getData();
00248                 
00249                 
00251                 // Step 4: set parameters for decompression 
00252                 cinfo.out_color_components = 3;
00253                 cinfo.out_color_space = JCS_RGB;
00254    
00255 
00257                 // Step 5: Start decompressor 
00258                 
00259                 jpeg_start_decompress(&cinfo);
00260                 // We can ignore the return value since suspension is not possible
00261                 // with our data source.
00262                 
00263                 // We may need to do some setup of our own at this point before reading
00264                 // the data.  After jpeg_start_decompress() we have the correct scaled
00265                 // output image dimensions available, as well as the output colormap
00266                 // if we asked for color quantization.
00267                 // In this example, we need to make an output work buffer of the right size.
00268     
00269                 // JSAMPLEs per row in output buffer 
00270                 row_stride = cinfo.output_width * cinfo.output_components;
00271                 
00273                 // Step 6: while (scan lines remain to be read) 
00274                 //           jpeg_read_scanlines(...); 
00275                 
00276                 // Here we use the library's state variable cinfo.output_scanline as the
00277                 // loop counter, so that we don't have to keep track ourselves.
00278                 
00279                 // Move pointer to last line
00280                 raw_image_data += row_stride * (cinfo.output_height - 1);
00281 
00282                 while (cinfo.output_scanline < cinfo.output_height)
00283                 {
00284                         // jpeg_read_scanlines expects an array of pointers to scanlines.
00285                         // Here the array is only one element long, but you could ask for
00286                         // more than one scanline at a time if that's more convenient.
00287                         
00288                         jpeg_read_scanlines(&cinfo, &raw_image_data, 1);
00289                         raw_image_data -= row_stride;  // move pointer up a line
00290                 }
00291 
00293                 // Step 7: Finish decompression 
00294                 jpeg_finish_decompress(&cinfo);
00295 
00297                 // Step 8: Release JPEG decompression object 
00298                 jpeg_destroy_decompress(&cinfo);
00299         }
00300 
00301         catch (int)
00302         {
00303                 jpeg_destroy_decompress(&cinfo);
00304                 return FALSE;
00305         }
00306 
00307         // Check to see whether any corrupt-data warnings occurred
00308         if( jerr.num_warnings != 0 )
00309         {
00310                 // TODO: extract the warning to find out what went wrong.
00311                 setLastError( "Unable to decode JPEG image.");
00312                 return FALSE;
00313         }
00314 
00315         return TRUE;
00316 }
00317 
00318 
00319 // Initialize destination --- called by jpeg_start_compress before any data is actually written.
00320 // static
00321 void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
00322 {
00323   LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00324 
00325   cinfo->dest->next_output_byte = self->mOutputBuffer;
00326   cinfo->dest->free_in_buffer = self->mOutputBufferSize;
00327 }
00328 
00329 
00330 //  Empty the output buffer --- called whenever buffer fills up.
00331 // 
00332 //  In typical applications, this should write the entire output buffer
00333 //  (ignoring the current state of next_output_byte & free_in_buffer),
00334 //  reset the pointer & count to the start of the buffer, and return TRUE
00335 //  indicating that the buffer has been dumped.
00336 // 
00337 //  In applications that need to be able to suspend compression due to output
00338 //  overrun, a FALSE return indicates that the buffer cannot be emptied now.
00339 //  In this situation, the compressor will return to its caller (possibly with
00340 //  an indication that it has not accepted all the supplied scanlines).  The
00341 //  application should resume compression after it has made more room in the
00342 //  output buffer.  Note that there are substantial restrictions on the use of
00343 //  suspension --- see the documentation.
00344 // 
00345 //  When suspending, the compressor will back up to a convenient restart point
00346 //  (typically the start of the current MCU). next_output_byte & free_in_buffer
00347 //  indicate where the restart point will be if the current call returns FALSE.
00348 //  Data beyond this point will be regenerated after resumption, so do not
00349 //  write it out when emptying the buffer externally.
00350 
00351 boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
00352 {
00353   LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00354 
00355   // Should very rarely happen, since our output buffer is
00356   // as large as the input to start out with.
00357   
00358   // Double the buffer size;
00359   S32 new_buffer_size = self->mOutputBufferSize * 2;
00360   U8* new_buffer = new U8[ new_buffer_size ];
00361   if (!new_buffer)
00362   {
00363         llerrs << "Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )" << llendl;
00364         return FALSE;
00365   }
00366   memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize );   /* Flawfinder: ignore */
00367   delete[] self->mOutputBuffer;
00368   self->mOutputBuffer = new_buffer;
00369 
00370   cinfo->dest->next_output_byte = self->mOutputBuffer + self->mOutputBufferSize;
00371   cinfo->dest->free_in_buffer = self->mOutputBufferSize;
00372   self->mOutputBufferSize = new_buffer_size;
00373 
00374   return TRUE;
00375 }
00376 
00377 //  Terminate destination --- called by jpeg_finish_compress
00378 //  after all data has been written.  Usually needs to flush buffer.
00379 // 
00380 //  NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
00381 //  application must deal with any cleanup that should happen even
00382 //  for error exit.
00383 void LLImageJPEG::encodeTermDestination( j_compress_ptr cinfo )
00384 {
00385         LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00386 
00387         S32 file_bytes = (S32)(self->mOutputBufferSize - cinfo->dest->free_in_buffer);
00388         self->allocateData(file_bytes);
00389 
00390         memcpy( self->getData(), self->mOutputBuffer, file_bytes );     /* Flawfinder: ignore */
00391 }
00392 
00393 // static 
00394 void LLImageJPEG::errorExit( j_common_ptr cinfo )       
00395 {
00396         //LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00397 
00398         // Always display the message
00399         (*cinfo->err->output_message)(cinfo);
00400 
00401         // Let the memory manager delete any temp files
00402         jpeg_destroy(cinfo);
00403 
00404         // Return control to the setjmp point
00405         throw 1;
00406 }
00407 
00408 // Decide whether to emit a trace or warning message.
00409 // msg_level is one of:
00410 //   -1: recoverable corrupt-data warning, may want to abort.
00411 //    0: important advisory messages (always display to user).
00412 //    1: first level of tracing detail.
00413 //    2,3,...: successively more detailed tracing messages.
00414 // An application might override this method if it wanted to abort on warnings
00415 // or change the policy about which messages to display.
00416 // static 
00417 void LLImageJPEG::errorEmitMessage( j_common_ptr cinfo, int msg_level )
00418 {
00419   struct jpeg_error_mgr * err = cinfo->err;
00420 
00421   if (msg_level < 0) 
00422   {
00423           // It's a warning message.  Since corrupt files may generate many warnings,
00424           // the policy implemented here is to show only the first warning,
00425           // unless trace_level >= 3.
00426           if (err->num_warnings == 0 || err->trace_level >= 3)
00427           {
00428                   (*err->output_message) (cinfo);
00429           }
00430           // Always count warnings in num_warnings.
00431           err->num_warnings++;
00432   }
00433   else 
00434   {
00435           // It's a trace message.  Show it if trace_level >= msg_level.
00436           if (err->trace_level >= msg_level)
00437           {
00438                   (*err->output_message) (cinfo);
00439           }
00440   }
00441 }
00442 
00443 // static 
00444 void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo )
00445 {
00446         // Create the message
00447         char buffer[JMSG_LENGTH_MAX];   /* Flawfinder: ignore */
00448         (*cinfo->err->format_message) (cinfo, buffer);
00449 
00450         ((LLImageJPEG*) cinfo->client_data)->setLastError( buffer );
00451 
00452         BOOL is_decode = (cinfo->is_decompressor != 0);
00453         llwarns << "LLImageJPEG " << (is_decode ? "decode " : "encode ") << " failed: " << buffer << llendl;
00454 }
00455 
00456 BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
00457 {
00458         llassert_always(raw_image);
00459         
00460         resetLastError();
00461 
00462         switch( raw_image->getComponents() )
00463         {
00464         case 1:
00465         case 3:
00466                 break;
00467         default:
00468                 setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
00469                 return FALSE;
00470         }
00471 
00472         setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
00473 
00474         // Allocate a temporary buffer big enough to hold the entire compressed image (and then some)
00475         // (Note: we make it bigger in emptyOutputBuffer() if we need to)
00476         delete[] mOutputBuffer;
00477         mOutputBufferSize = getWidth() * getHeight() * getComponents() + 1024;
00478         mOutputBuffer = new U8[ mOutputBufferSize ];
00479 
00480         const U8* raw_image_data = NULL;
00481         S32 row_stride = 0;
00482 
00484         // Step 1: allocate and initialize JPEG compression object
00485 
00486         // This struct contains the JPEG compression parameters and pointers to
00487         // working space (which is allocated as needed by the JPEG library).
00488         struct jpeg_compress_struct cinfo;
00489         cinfo.client_data = this;
00490 
00491         // We have to set up the error handler first, in case the initialization
00492         // step fails.  (Unlikely, but it could happen if you are out of memory.)
00493         // This routine fills in the contents of struct jerr, and returns jerr's
00494         // address which we place into the link field in cinfo.
00495         struct jpeg_error_mgr jerr;
00496         cinfo.err = jpeg_std_error(&jerr);
00497 
00498         // Customize with our own callbacks
00499         jerr.error_exit =               &LLImageJPEG::errorExit;                        // Error exit handler: does not return to caller
00500         jerr.emit_message =             &LLImageJPEG::errorEmitMessage;         // Conditionally emit a trace or warning message
00501         jerr.output_message =   &LLImageJPEG::errorOutputMessage;       // Routine that actually outputs a trace or error message
00502 
00503         // Establish the setjmp return context mSetjmpBuffer.  Used by library to abort.
00504         if( setjmp(mSetjmpBuffer) ) 
00505         {
00506                 // If we get here, the JPEG code has signaled an error.
00507                 // We need to clean up the JPEG object, close the input file, and return.
00508                 jpeg_destroy_compress(&cinfo);
00509                 delete[] mOutputBuffer;
00510                 mOutputBuffer = NULL;
00511                 mOutputBufferSize = 0;
00512                 return FALSE;
00513         }
00514 
00515         try
00516         {
00517 
00518                 // Now we can initialize the JPEG compression object.
00519                 jpeg_create_compress(&cinfo);
00520 
00522                 // Step 2: specify data destination
00523                 // (code is a modified form of jpeg_stdio_dest() )
00524                 if( cinfo.dest == NULL)
00525                 {       
00526                         cinfo.dest = (struct jpeg_destination_mgr *)
00527                                 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00528                                 sizeof(struct jpeg_destination_mgr));
00529                 }
00530                 cinfo.dest->next_output_byte =          mOutputBuffer;          // => next byte to write in buffer
00531                 cinfo.dest->free_in_buffer =            mOutputBufferSize;      // # of byte spaces remaining in buffer
00532                 cinfo.dest->init_destination =          &LLImageJPEG::encodeInitDestination;
00533                 cinfo.dest->empty_output_buffer =       &LLImageJPEG::encodeEmptyOutputBuffer;
00534                 cinfo.dest->term_destination =          &LLImageJPEG::encodeTermDestination;
00535 
00537                 // Step 3: set parameters for compression 
00538                 //
00539                 // First we supply a description of the input image.
00540                 // Four fields of the cinfo struct must be filled in:
00541                 
00542                 cinfo.image_width = getWidth();         // image width and height, in pixels 
00543                 cinfo.image_height = getHeight();
00544 
00545                 switch( getComponents() )
00546                 {
00547                 case 1:
00548                         cinfo.input_components = 1;             // # of color components per pixel
00549                         cinfo.in_color_space = JCS_GRAYSCALE; // colorspace of input image
00550                         break;
00551                 case 3:
00552                         cinfo.input_components = 3;             // # of color components per pixel
00553                         cinfo.in_color_space = JCS_RGB; // colorspace of input image
00554                         break;
00555                 default:
00556                         setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
00557                         return FALSE;
00558                 }
00559 
00560                 // Now use the library's routine to set default compression parameters.
00561                 // (You must set at least cinfo.in_color_space before calling this,
00562                 // since the defaults depend on the source color space.)
00563                 jpeg_set_defaults(&cinfo);
00564 
00565                 // Now you can set any non-default parameters you wish to.
00566                 jpeg_set_quality(&cinfo, mEncodeQuality, TRUE );  // limit to baseline-JPEG values
00567 
00569                 // Step 4: Start compressor 
00570                 //
00571                 // TRUE ensures that we will write a complete interchange-JPEG file.
00572                 // Pass TRUE unless you are very sure of what you're doing.
00573    
00574                 jpeg_start_compress(&cinfo, TRUE);
00575 
00577                 // Step 5: while (scan lines remain to be written) 
00578                 //            jpeg_write_scanlines(...); 
00579 
00580                 // Here we use the library's state variable cinfo.next_scanline as the
00581                 // loop counter, so that we don't have to keep track ourselves.
00582                 // To keep things simple, we pass one scanline per call; you can pass
00583                 // more if you wish, though.
00584    
00585                 row_stride = getWidth() * getComponents();      // JSAMPLEs per row in image_buffer
00586 
00587                 // NOTE: For compatibility with LLImage, we need to invert the rows.
00588                 raw_image_data = raw_image->getData();
00589                 
00590                 const U8* last_row_data = raw_image_data + (getHeight()-1) * row_stride;
00591 
00592                 JSAMPROW row_pointer[1];                                // pointer to JSAMPLE row[s]
00593                 while (cinfo.next_scanline < cinfo.image_height) 
00594                 {
00595                         // jpeg_write_scanlines expects an array of pointers to scanlines.
00596                         // Here the array is only one element long, but you could pass
00597                         // more than one scanline at a time if that's more convenient.
00598 
00599                         //Ugly const uncast here (jpeg_write_scanlines should take a const* but doesn't)
00600                         //row_pointer[0] = (JSAMPROW)(raw_image_data + (cinfo.next_scanline * row_stride));
00601                         row_pointer[0] = (JSAMPROW)(last_row_data - (cinfo.next_scanline * row_stride));
00602 
00603                         jpeg_write_scanlines(&cinfo, row_pointer, 1);
00604                 }
00605 
00607                 //   Step 6: Finish compression 
00608                 jpeg_finish_compress(&cinfo);
00609 
00610                 // After finish_compress, we can release the temp output buffer. 
00611                 delete[] mOutputBuffer;
00612                 mOutputBuffer = NULL;
00613                 mOutputBufferSize = 0;
00614 
00616                 //   Step 7: release JPEG compression object 
00617                 jpeg_destroy_compress(&cinfo);
00618         }
00619 
00620         catch(int)
00621         {
00622                 jpeg_destroy_compress(&cinfo);
00623                 delete[] mOutputBuffer;
00624                 mOutputBuffer = NULL;
00625                 mOutputBufferSize = 0;
00626                 return FALSE;
00627         }
00628 
00629         return TRUE;
00630 }

Generated on Thu Jul 1 06:08:44 2010 for Second Life Viewer by  doxygen 1.4.7