Add error handler when read image data using libjpeg.

Fix errors when read image using libjpeg.
Fix errors when read image with broken data using libjpeg.
This commit is contained in:
wenbin1989 2012-11-01 21:42:24 +08:00
parent 84b642d186
commit 470fcacc81
1 changed files with 76 additions and 8 deletions

View File

@ -197,11 +197,64 @@ bool CCImage::initWithImageData(void * pData,
return bRet;
}
/*
* ERROR HANDLING:
*
* The JPEG library's standard error handler (jerror.c) is divided into
* several "methods" which you can override individually. This lets you
* adjust the behavior without duplicating a lot of code, which you might
* have to update with each future release.
*
* We override the "error_exit" method so that control is returned to the
* library's caller when a fatal error occurs, rather than calling exit()
* as the standard error_exit method does.
*
* We use C's setjmp/longjmp facility to return control. This means that the
* routine which calls the JPEG library must first execute a setjmp() call to
* establish the return point. We want the replacement error_exit to do a
* longjmp(). But we need to make the setjmp buffer accessible to the
* error_exit routine. To do this, we make a private extension of the
* standard JPEG error handler object. (If we were using C++, we'd say we
* were making a subclass of the regular error handler.)
*
* Here's the extended error handler struct:
*/
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
/*
* Here's the routine that will replace the standard error_exit method:
*/
METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
bool CCImage::_initWithJpgData(void * data, int nSize)
{
/* these are standard libjpeg structures for reading(decompression) */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
/* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
struct my_error_mgr jerr;
/* libjpeg data structure for storing one row, that is, scanline of an image */
JSAMPROW row_pointer[1] = {0};
unsigned long location = 0;
@ -210,8 +263,18 @@ bool CCImage::_initWithJpgData(void * data, int nSize)
bool bRet = false;
do
{
/* here we set up the standard libjpeg error handler */
cinfo.err = jpeg_std_error( &jerr );
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
CCLog("%d", bRet);
jpeg_destroy_decompress(&cinfo);
break;
}
/* setup decompression process and source, then read JPEG header */
jpeg_create_decompress( &cinfo );
@ -238,8 +301,8 @@ bool CCImage::_initWithJpgData(void * data, int nSize)
jpeg_start_decompress( &cinfo );
/* init image info */
m_nWidth = (short)(cinfo.image_width);
m_nHeight = (short)(cinfo.image_height);
m_nWidth = (short)(cinfo.output_width);
m_nHeight = (short)(cinfo.output_height);
m_bHasAlpha = false;
m_bPreMulti = false;
m_nBitsPerComponent = 8;
@ -251,16 +314,21 @@ bool CCImage::_initWithJpgData(void * data, int nSize)
/* now actually read the jpeg into the raw buffer */
/* read one scan line at a time */
while( cinfo.output_scanline < cinfo.image_height )
while( cinfo.output_scanline < cinfo.output_height )
{
jpeg_read_scanlines( &cinfo, row_pointer, 1 );
for( i=0; i<cinfo.image_width*cinfo.output_components;i++)
for( i=0; i<cinfo.output_width*cinfo.output_components;i++)
{
m_pData[location++] = row_pointer[0][i];
}
}
jpeg_finish_decompress( &cinfo );
/* When read image file with broken data, jpeg_finish_decompress() may cause error.
* Besides, jpeg_destroy_decompress() shall deallocate and release all memory associated
* with the decompression object.
* So it doesn't need to call jpeg_finish_decompress().
*/
//jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo );
/* wrap up decompression, destroy objects, free pointers and close open files */
bRet = true;