[email protected]
#include <stdio.h>
#include <string.h>
#include "SDL_image.h"
#ifdef LOAD_JPG
#include <jpeglib.h>
int IMG_isJPG(SDL_RWops *src)
{
	int is_JPG;
	Uint8 magic[4];
	is_JPG = 0;
	if ( SDL_RWread(src, magic, 2, 1) ) {
		if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) {
			SDL_RWread(src, magic, 4, 1);
			SDL_RWread(src, magic, 4, 1);
			if ( memcmp((char *)magic, "JFIF", 4) == 0 ||
			     memcmp((char *)magic, "Exif", 4) == 0 ) {
				is_JPG = 1;
			}
		}
	}
	return(is_JPG);
}
#define INPUT_BUFFER_SIZE	4096
typedef struct {
	struct jpeg_source_mgr pub;
	SDL_RWops *ctx;
	Uint8 buffer[INPUT_BUFFER_SIZE];
} my_source_mgr;
static void init_source (j_decompress_ptr cinfo)
{
	
	return;
}
static int fill_input_buffer (j_decompress_ptr cinfo)
{
	my_source_mgr * src = (my_source_mgr *) cinfo->src;
	int nbytes;
	nbytes = SDL_RWread(src->ctx, src->buffer, 1, INPUT_BUFFER_SIZE);
	if (nbytes <= 0) {
		
		src->buffer[0] = (Uint8) 0xFF;
		src->buffer[1] = (Uint8) JPEG_EOI;
		nbytes = 2;
	}
	src->pub.next_input_byte = src->buffer;
	src->pub.bytes_in_buffer = nbytes;
	return TRUE;
}
static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
	my_source_mgr * src = (my_source_mgr *) cinfo->src;
	
	if (num_bytes > 0) {
		while (num_bytes > (long) src->pub.bytes_in_buffer) {
			num_bytes -= (long) src->pub.bytes_in_buffer;
			(void) src->pub.fill_input_buffer(cinfo);
			
		}
		src->pub.next_input_byte += (size_t) num_bytes;
		src->pub.bytes_in_buffer -= (size_t) num_bytes;
	}
}
static void term_source (j_decompress_ptr cinfo)
{
	
	return;
}
static void jpeg_SDL_RW_src (j_decompress_ptr cinfo, SDL_RWops *ctx)
{
  my_source_mgr *src;
  
  if (cinfo->src == NULL) {	
    cinfo->src = (struct jpeg_source_mgr *)
      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
				  sizeof(my_source_mgr));
    src = (my_source_mgr *) cinfo->src;
  }
  src = (my_source_mgr *) cinfo->src;
  src->pub.init_source = init_source;
  src->pub.fill_input_buffer = fill_input_buffer;
  src->pub.skip_input_data = skip_input_data;
  src->pub.resync_to_restart = jpeg_resync_to_restart; 
  src->pub.term_source = term_source;
  src->ctx = ctx;
  src->pub.bytes_in_buffer = 0; 
  src->pub.next_input_byte = NULL; 
}
struct my_error_mgr {
	struct jpeg_error_mgr errmgr;
	
};
static void my_error_exit(j_common_ptr cinfo)
{
	struct my_error_mgr *err = (struct my_error_mgr *)cinfo->err;
	
}
static void output_no_message(j_common_ptr cinfo)
{
	
}
SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
{
	struct jpeg_decompress_struct cinfo;
	JSAMPROW rowptr[1];
	SDL_Surface *volatile surface = NULL;
	struct my_error_mgr jerr;
	if ( !src ) {
		
		return NULL;
	}
	
	cinfo.err = jpeg_std_error(&jerr.errmgr);
	jerr.errmgr.error_exit = my_error_exit;
	jerr.errmgr.output_message = output_no_message;
#if 0
	if(setjmp(jerr.escape)) {
		
		jpeg_destroy_decompress(&cinfo);
		IMG_SetError("JPEG loading error");
		SDL_FreeSurface(surface);
		return NULL;
	}
#endif
	jpeg_create_decompress(&cinfo);
	jpeg_SDL_RW_src(&cinfo, src);
	jpeg_read_header(&cinfo, TRUE);
	
	cinfo.out_color_space = JCS_RGB;
	cinfo.quantize_colors = FALSE;
#ifdef FAST_JPEG
	cinfo.scale_num   = 1;
	cinfo.scale_denom = 1;
	cinfo.dct_method = JDCT_FASTEST;
	cinfo.do_fancy_upsampling = FALSE;
#endif
	jpeg_calc_output_dimensions(&cinfo);
	
	surface = SDL_AllocSurface(SDL_SWSURFACE,
	               cinfo.output_width, cinfo.output_height, 24,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
	                           0x0000FF, 0x00FF00, 0xFF0000,
#else
	                           0xFF0000, 0x00FF00, 0x0000FF,
#endif
				   0);
	if ( surface == NULL ) {
		IMG_SetError("Out of memory");
		goto done;
	}
	
	jpeg_start_decompress(&cinfo);
	while ( cinfo.output_scanline < cinfo.output_height ) {
		rowptr[0] = (JSAMPROW)(Uint8 *)surface->pixels +
		                    cinfo.output_scanline * surface->pitch;
		jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
	}
	jpeg_finish_decompress(&cinfo);
	
done:
	jpeg_destroy_decompress(&cinfo);
	return(surface);
}
#else
int IMG_isJPG(SDL_RWops *src)
{
	return(0);
}
SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
{
	return(NULL);
}
#endif