IMG_jpg.c
changeset 123 1f7908a9cabb
parent 121 1bf9c0c87374
child 143 e01fee7bdf3b
     1.1 --- a/IMG_jpg.c	Sun Mar 19 05:35:17 2006 +0000
     1.2 +++ b/IMG_jpg.c	Thu Apr 20 16:52:50 2006 +0000
     1.3 @@ -35,29 +35,65 @@
     1.4  /* Define this for fast loading and not as good image quality */
     1.5  /*#define FAST_JPEG*/
     1.6  
     1.7 +/* Define this for quicker (but less perfect) JPEG identification */
     1.8 +#define FAST_IS_JPEG
     1.9 +
    1.10  /* See if an image is contained in a data source */
    1.11  int IMG_isJPG(SDL_RWops *src)
    1.12  {
    1.13  	int start;
    1.14  	int is_JPG;
    1.15 +	int in_scan;
    1.16  	Uint8 magic[4];
    1.17  
    1.18 +	/* This detection code is by Steaphan Greene <stea@cs.binghamton.edu> */
    1.19 +	/* Blame me, not Sam, if this doesn't work right. */
    1.20 +	/* And don't forget to report the problem to the the sdl list too! */
    1.21 +
    1.22  	start = SDL_RWtell(src);
    1.23  	is_JPG = 0;
    1.24 +	in_scan = 0;
    1.25  	if ( SDL_RWread(src, magic, 2, 1) ) {
    1.26  		if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) {
    1.27 -			SDL_RWread(src, magic, 4, 1);
    1.28 -
    1.29 -			/* skip IPTC info block if it exists... */
    1.30 -			if ( (magic[0] == 0xFF) && (magic[1] == 0xED) ) {
    1.31 -				SDL_RWseek(src, (((Uint16)magic[2] << 8) |magic[3]) + 2, SEEK_CUR);
    1.32 -			}
    1.33 -
    1.34 -			SDL_RWread(src, magic, 4, 1);
    1.35 -			if ( memcmp((char *)magic, "JFIF", 4) == 0 ||
    1.36 -			     memcmp((char *)magic, "Exif", 4) == 0 ||
    1.37 -			     memcmp((char *)magic, "VVL", 3) == 0 ) {
    1.38 -				is_JPG = 1;
    1.39 +			is_JPG = 1;
    1.40 +			while (is_JPG == 1) {
    1.41 +				if(SDL_RWread(src, magic, 1, 2) != 2) {
    1.42 +					is_JPG = 0;
    1.43 +				} else if( (magic[0] != 0xFF) && (in_scan == 0) ) {
    1.44 +					is_JPG = 0;
    1.45 +				} else if( (magic[0] != 0xFF) || (magic[1] == 0xFF) ) {
    1.46 +					/* Extra padding in JPEG (legal) */
    1.47 +					/* or this is data and we are scanning */
    1.48 +					SDL_RWseek(src, -1, SEEK_CUR);
    1.49 +				} else if(magic[1] == 0xD9) {
    1.50 +					/* Got to end of good JPEG */
    1.51 +					break;
    1.52 +				} else if( (in_scan == 1) && (magic[1] == 0x00) ) {
    1.53 +					/* This is an encoded 0xFF within the data */
    1.54 +				} else if( (magic[1] >= 0xD0) && (magic[1] < 0xD9) ) {
    1.55 +					/* These have nothing else */
    1.56 +				} else if(SDL_RWread(src, magic+2, 1, 2) != 2) {
    1.57 +					is_JPG = 0;
    1.58 +				} else {
    1.59 +					/* Yes, it's big-endian */
    1.60 +					Uint32 start;
    1.61 +					Uint32 size;
    1.62 +					Uint32 end;
    1.63 +					start = SDL_RWtell(src);
    1.64 +					size = (magic[2] << 8) + magic[3];
    1.65 +					end = SDL_RWseek(src, size-2, SEEK_CUR);
    1.66 +					if ( end != start + size - 2 ) is_JPG = 0;
    1.67 +					if ( magic[1] == 0xDA ) {
    1.68 +						/* Now comes the actual JPEG meat */
    1.69 +#ifdef	FAST_IS_JPEG
    1.70 +						/* Ok, I'm convinced.  It is a JPEG. */
    1.71 +						break;
    1.72 +#else
    1.73 +						/* I'm not convinced.  Prove it! */
    1.74 +						in_scan = 1;
    1.75 +#endif
    1.76 +					}
    1.77 +				}
    1.78  			}
    1.79  		}
    1.80  	}
    1.81 @@ -231,26 +267,43 @@
    1.82  	jpeg_SDL_RW_src(&cinfo, src);
    1.83  	jpeg_read_header(&cinfo, TRUE);
    1.84  
    1.85 -	/* Set 24-bit RGB output */
    1.86 -	cinfo.out_color_space = JCS_RGB;
    1.87 -	cinfo.quantize_colors = FALSE;
    1.88 +	if(cinfo.num_components == 4) {
    1.89 +		/* Set 32-bit Raw output */
    1.90 +		cinfo.out_color_space = JCS_CMYK;
    1.91 +		cinfo.quantize_colors = FALSE;
    1.92 +		jpeg_calc_output_dimensions(&cinfo);
    1.93 +
    1.94 +		/* Allocate an output surface to hold the image */
    1.95 +		surface = SDL_AllocSurface(SDL_SWSURFACE,
    1.96 +		        cinfo.output_width, cinfo.output_height, 32,
    1.97 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN
    1.98 +		                   0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
    1.99 +#else
   1.100 +		                   0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF);
   1.101 +#endif
   1.102 +	} else {
   1.103 +		/* Set 24-bit RGB output */
   1.104 +		cinfo.out_color_space = JCS_RGB;
   1.105 +		cinfo.quantize_colors = FALSE;
   1.106  #ifdef FAST_JPEG
   1.107 -	cinfo.scale_num   = 1;
   1.108 -	cinfo.scale_denom = 1;
   1.109 -	cinfo.dct_method = JDCT_FASTEST;
   1.110 -	cinfo.do_fancy_upsampling = FALSE;
   1.111 +		cinfo.scale_num   = 1;
   1.112 +		cinfo.scale_denom = 1;
   1.113 +		cinfo.dct_method = JDCT_FASTEST;
   1.114 +		cinfo.do_fancy_upsampling = FALSE;
   1.115  #endif
   1.116 -	jpeg_calc_output_dimensions(&cinfo);
   1.117 +		jpeg_calc_output_dimensions(&cinfo);
   1.118  
   1.119 -	/* Allocate an output surface to hold the image */
   1.120 -	surface = SDL_AllocSurface(SDL_SWSURFACE,
   1.121 -	               cinfo.output_width, cinfo.output_height, 24,
   1.122 +		/* Allocate an output surface to hold the image */
   1.123 +		surface = SDL_AllocSurface(SDL_SWSURFACE,
   1.124 +		        cinfo.output_width, cinfo.output_height, 24,
   1.125  #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   1.126 -	                           0x0000FF, 0x00FF00, 0xFF0000,
   1.127 +		                   0x0000FF, 0x00FF00, 0xFF0000,
   1.128  #else
   1.129 -	                           0xFF0000, 0x00FF00, 0x0000FF,
   1.130 +		                   0xFF0000, 0x00FF00, 0x0000FF,
   1.131  #endif
   1.132 -				   0);
   1.133 +		                   0);
   1.134 +	}
   1.135 +
   1.136  	if ( surface == NULL ) {
   1.137  		jpeg_destroy_decompress(&cinfo);
   1.138  		SDL_RWseek(src, start, SEEK_SET);