bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) ) { wxCHECK_MSG( image, false, "NULL image pointer" ); struct jpeg_decompress_struct cinfo; wx_error_mgr jerr; unsigned char *ptr; // save this before calling Destroy() const unsigned maxWidth = image->GetOptionInt(wxIMAGE_OPTION_MAX_WIDTH), maxHeight = image->GetOptionInt(wxIMAGE_OPTION_MAX_HEIGHT); image->Destroy(); cinfo.err = jpeg_std_error( &jerr ); jerr.error_exit = wx_error_exit; if (!verbose) cinfo.err->output_message = wx_ignore_message; /* Establish the setjmp return context for wx_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. */ if (verbose) { wxLogError(_("JPEG: Couldn't load - file is probably corrupted.")); } (cinfo.src->term_source)(&cinfo); jpeg_destroy_decompress(&cinfo); if (image->IsOk()) image->Destroy(); return false; } jpeg_create_decompress( &cinfo ); wx_jpeg_io_src( &cinfo, stream ); jpeg_read_header( &cinfo, TRUE ); int bytesPerPixel; if ((cinfo.out_color_space == JCS_CMYK) || (cinfo.out_color_space == JCS_YCCK)) { cinfo.out_color_space = JCS_CMYK; bytesPerPixel = 4; } else // all the rest is treated as RGB { cinfo.out_color_space = JCS_RGB; bytesPerPixel = 3; } // scale the picture to fit in the specified max size if necessary if ( maxWidth > 0 || maxHeight > 0 ) { unsigned& scale = cinfo.scale_denom; while ( (maxWidth && (cinfo.image_width / scale > maxWidth)) || (maxHeight && (cinfo.image_height / scale > maxHeight)) ) { scale *= 2; } } jpeg_start_decompress( &cinfo ); image->Create( cinfo.output_width, cinfo.output_height ); if (!image->IsOk()) { jpeg_finish_decompress( &cinfo ); jpeg_destroy_decompress( &cinfo ); return false; } image->SetMask( false ); ptr = image->GetData(); unsigned stride = cinfo.output_width * bytesPerPixel; JSAMPARRAY tempbuf = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, stride, 1 ); while ( cinfo.output_scanline < cinfo.output_height ) { jpeg_read_scanlines( &cinfo, tempbuf, 1 ); if (cinfo.out_color_space == JCS_RGB) { memcpy( ptr, tempbuf[0], stride ); ptr += stride; } else // CMYK { const unsigned char* inptr = (const unsigned char*) tempbuf[0]; for (size_t i = 0; i < cinfo.output_width; i++) { wx_cmyk_to_rgb(ptr, inptr); ptr += 3; inptr += 4; } } } // set up resolution if available: it's part of optional JFIF APP0 chunk if ( cinfo.saw_JFIF_marker ) { image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, cinfo.X_density); image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, cinfo.Y_density); // we use the same values for this option as libjpeg so we don't need // any conversion here image->SetOption(wxIMAGE_OPTION_RESOLUTIONUNIT, cinfo.density_unit); } if ( cinfo.image_width != cinfo.output_width || cinfo.image_height != cinfo.output_height ) { // save the original image size image->SetOption(wxIMAGE_OPTION_ORIGINAL_WIDTH, cinfo.image_width); image->SetOption(wxIMAGE_OPTION_ORIGINAL_HEIGHT, cinfo.image_height); } jpeg_finish_decompress( &cinfo ); jpeg_destroy_decompress( &cinfo ); return true; }
bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) ) { struct jpeg_decompress_struct cinfo; struct wx_error_mgr jerr; unsigned char *ptr; image->Destroy(); cinfo.err = jpeg_std_error( &jerr.pub ); jerr.pub.error_exit = wx_error_exit; if (!verbose) cinfo.err->output_message = wx_ignore_message; /* Establish the setjmp return context for wx_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. */ if (verbose) wxLogError(_("JPEG: Couldn't load - file is probably corrupted.")); (cinfo.src->term_source)(&cinfo); jpeg_destroy_decompress(&cinfo); if (image->Ok()) image->Destroy(); return false; } jpeg_create_decompress( &cinfo ); wx_jpeg_io_src( &cinfo, stream ); jpeg_read_header( &cinfo, TRUE ); int bytesPerPixel; if ((cinfo.out_color_space == JCS_CMYK) || (cinfo.out_color_space == JCS_YCCK)) { cinfo.out_color_space = JCS_CMYK; bytesPerPixel = 4; } else // all the rest is treated as RGB { cinfo.out_color_space = JCS_RGB; bytesPerPixel = 3; } jpeg_start_decompress( &cinfo ); image->Create( cinfo.image_width, cinfo.image_height ); if (!image->Ok()) { jpeg_finish_decompress( &cinfo ); jpeg_destroy_decompress( &cinfo ); return false; } image->SetMask( false ); ptr = image->GetData(); unsigned stride = cinfo.output_width * bytesPerPixel; JSAMPARRAY tempbuf = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, stride, 1 ); while ( cinfo.output_scanline < cinfo.output_height ) { jpeg_read_scanlines( &cinfo, tempbuf, 1 ); if (cinfo.out_color_space == JCS_RGB) { memcpy( ptr, tempbuf[0], stride ); ptr += stride; } else // CMYK { const unsigned char* inptr = (const unsigned char*) tempbuf[0]; for (size_t i = 0; i < cinfo.output_width; i++) { wx_cmyk_to_rgb(ptr, inptr); ptr += 3; inptr += 4; } } } jpeg_finish_decompress( &cinfo ); jpeg_destroy_decompress( &cinfo ); return true; }