@@ -124,6 +124,7 @@ int IMG_InitJPG()
124124
125125 return 0 ;
126126}
127+
127128void IMG_QuitJPG ()
128129{
129130 if ( lib .loaded == 0 ) {
@@ -337,89 +338,106 @@ static void output_no_message(j_common_ptr cinfo)
337338 (void )cinfo ;
338339}
339340
340- /* Load a JPEG type image from an SDL datasource */
341- SDL_Surface * IMG_LoadJPG_RW (SDL_RWops * src )
342- {
343- Sint64 start ;
341+ struct loadjpeg_vars {
342+ const char * error ;
343+ SDL_Surface * surface ;
344344 struct jpeg_decompress_struct cinfo ;
345- JSAMPROW rowptr [1 ];
346- SDL_Surface * surface = NULL ;
347345 struct my_error_mgr jerr ;
346+ };
348347
349- if ( !src ) {
350- /* The error message has been set in SDL_RWFromFile */
351- return NULL ;
352- }
353- start = SDL_RWtell (src );
354-
355- if ( (IMG_Init (IMG_INIT_JPG ) & IMG_INIT_JPG ) == 0 ) {
356- return NULL ;
357- }
348+ /* Load a JPEG type image from an SDL datasource */
349+ static SDL_bool LIBJPEG_LoadJPG_RW (SDL_RWops * src , struct loadjpeg_vars * vars )
350+ {
351+ JSAMPROW rowptr [1 ];
358352
359353 /* Create a decompression structure and load the JPEG header */
360- cinfo .err = lib .jpeg_std_error (& jerr .errmgr );
361- jerr .errmgr .error_exit = my_error_exit ;
362- jerr .errmgr .output_message = output_no_message ;
363- #ifdef _MSC_VER
364- #pragma warning(disable:4611) /* warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable */
365- #endif
366- if (setjmp (jerr .escape )) {
354+ vars -> cinfo .err = lib .jpeg_std_error (& vars -> jerr .errmgr );
355+ vars -> jerr .errmgr .error_exit = my_error_exit ;
356+ vars -> jerr .errmgr .output_message = output_no_message ;
357+ if (setjmp (vars -> jerr .escape )) {
367358 /* If we get here, libjpeg found an error */
368- lib .jpeg_destroy_decompress (& cinfo );
369- if ( surface != NULL ) {
370- SDL_FreeSurface (surface );
371- }
372- SDL_RWseek (src , start , RW_SEEK_SET );
373- IMG_SetError ("JPEG loading error" );
374- return NULL ;
359+ lib .jpeg_destroy_decompress (& vars -> cinfo );
360+ vars -> error = "JPEG loading error" ;
361+ return SDL_FALSE ;
375362 }
376363
377- lib .jpeg_create_decompress (& cinfo );
378- jpeg_SDL_RW_src (& cinfo , src );
379- lib .jpeg_read_header (& cinfo , TRUE);
364+ lib .jpeg_create_decompress (& vars -> cinfo );
365+ jpeg_SDL_RW_src (& vars -> cinfo , src );
366+ lib .jpeg_read_header (& vars -> cinfo , TRUE);
380367
381- if ( cinfo .num_components == 4 ) {
368+ if ( vars -> cinfo .num_components == 4 ) {
382369 /* Set 32-bit Raw output */
383- cinfo .out_color_space = JCS_CMYK ;
384- cinfo .quantize_colors = FALSE;
385- lib .jpeg_calc_output_dimensions (& cinfo );
370+ vars -> cinfo .out_color_space = JCS_CMYK ;
371+ vars -> cinfo .quantize_colors = FALSE;
372+ lib .jpeg_calc_output_dimensions (& vars -> cinfo );
386373
387374 /* Allocate an output surface to hold the image */
388- surface = SDL_CreateRGBSurfaceWithFormat (0 , cinfo .output_width , cinfo .output_height , 0 , SDL_PIXELFORMAT_BGRA32 );
375+ vars -> surface = SDL_CreateRGBSurfaceWithFormat (0 , vars -> cinfo .output_width , vars -> cinfo .output_height , 0 , SDL_PIXELFORMAT_BGRA32 );
389376 } else {
390377 /* Set 24-bit RGB output */
391- cinfo .out_color_space = JCS_RGB ;
392- cinfo .quantize_colors = FALSE;
378+ vars -> cinfo .out_color_space = JCS_RGB ;
379+ vars -> cinfo .quantize_colors = FALSE;
393380#ifdef FAST_JPEG
394- cinfo .scale_num = 1 ;
395- cinfo .scale_denom = 1 ;
396- cinfo .dct_method = JDCT_FASTEST ;
397- cinfo .do_fancy_upsampling = FALSE;
381+ vars -> cinfo .scale_num = 1 ;
382+ vars -> cinfo .scale_denom = 1 ;
383+ vars -> cinfo .dct_method = JDCT_FASTEST ;
384+ vars -> cinfo .do_fancy_upsampling = FALSE;
398385#endif
399- lib .jpeg_calc_output_dimensions (& cinfo );
386+ lib .jpeg_calc_output_dimensions (& vars -> cinfo );
400387
401388 /* Allocate an output surface to hold the image */
402- surface = SDL_CreateRGBSurfaceWithFormat (0 , cinfo .output_width , cinfo .output_height , 0 , SDL_PIXELFORMAT_RGB24 );
389+ vars -> surface = SDL_CreateRGBSurfaceWithFormat (0 , vars -> cinfo .output_width , vars -> cinfo .output_height , 0 , SDL_PIXELFORMAT_RGB24 );
403390 }
404391
405- if ( surface == NULL ) {
406- lib .jpeg_destroy_decompress (& cinfo );
407- SDL_RWseek (src , start , RW_SEEK_SET );
408- IMG_SetError ("Out of memory" );
409- return NULL ;
392+ if (!vars -> surface ) {
393+ lib .jpeg_destroy_decompress (& vars -> cinfo );
394+ return SDL_FALSE ;
410395 }
411396
412397 /* Decompress the image */
413- lib .jpeg_start_decompress (& cinfo );
414- while ( cinfo .output_scanline < cinfo .output_height ) {
415- rowptr [0 ] = (JSAMPROW )(Uint8 * )surface -> pixels +
416- cinfo .output_scanline * surface -> pitch ;
417- lib .jpeg_read_scanlines (& cinfo , rowptr , (JDIMENSION ) 1 );
398+ lib .jpeg_start_decompress (& vars -> cinfo );
399+ while (vars -> cinfo .output_scanline < vars -> cinfo .output_height ) {
400+ rowptr [0 ] = (JSAMPROW )(Uint8 * )vars -> surface -> pixels +
401+ vars -> cinfo .output_scanline * vars -> surface -> pitch ;
402+ lib .jpeg_read_scanlines (& vars -> cinfo , rowptr , (JDIMENSION ) 1 );
403+ }
404+ lib .jpeg_finish_decompress (& vars -> cinfo );
405+ lib .jpeg_destroy_decompress (& vars -> cinfo );
406+
407+ return SDL_TRUE ;
408+ }
409+
410+ SDL_Surface * IMG_LoadJPG_RW (SDL_RWops * src )
411+ {
412+ Sint64 start ;
413+ struct loadjpeg_vars vars ;
414+
415+ if (!src ) {
416+ /* The error message has been set in SDL_RWFromFile */
417+ return NULL ;
418+ }
419+
420+ if ((IMG_Init (IMG_INIT_JPG ) & IMG_INIT_JPG ) == 0 ) {
421+ return NULL ;
422+ }
423+
424+ start = SDL_RWtell (src );
425+ SDL_zero (vars );
426+
427+ if (LIBJPEG_LoadJPG_RW (src , & vars )) {
428+ return vars .surface ;
429+ }
430+
431+ /* this may clobber a set error if seek fails: don't care. */
432+ SDL_RWseek (src , start , RW_SEEK_SET );
433+ if (vars .surface ) {
434+ SDL_FreeSurface (vars .surface );
435+ }
436+ if (vars .error ) {
437+ IMG_SetError ("%s" , vars .error );
418438 }
419- lib .jpeg_finish_decompress (& cinfo );
420- lib .jpeg_destroy_decompress (& cinfo );
421439
422- return ( surface ) ;
440+ return NULL ;
423441}
424442
425443#define OUTPUT_BUFFER_SIZE 4096
0 commit comments