/* +-------------------------------------------------------------------+ */
/* | Copyright 1993, David Koblas (koblas@netcom.com)                  | */
/* |                                                                   | */
/* | Permission to use, copy, modify, and to distribute this software  | */
/* | and its documentation for any purpose is hereby granted without   | */
/* | fee, provided that the above copyright notice appear in all       | */
/* | copies and that both that copyright notice and this permission    | */
/* | notice appear in supporting documentation.  There is no           | */
/* | representations about the suitability of this software for        | */
/* | any purpose.  this software is provided "as is" without express   | */
/* | or implied warranty.                                              | */
/* |                                                                   | */
/* +-------------------------------------------------------------------+ */

#include "jinclude.h"
#include "image.h"
#include <setjmp.h>

static jmp_buf 			setjmp_buffer;
static external_methods_ptr	emethods;	
int				rowBase;
static Image			*image;

METHODDEF void
trace_message(const char *msgtext)
{
	RWSetMsg(msgtext, 
		emethods->message_parm[0], emethods->message_parm[1],
		emethods->message_parm[2], emethods->message_parm[3],
		emethods->message_parm[4], emethods->message_parm[5],
		emethods->message_parm[6], emethods->message_parm[7]);
}

METHODDEF void
error_exit(const char *msgtext)
{
	trace_message(msgtext);
	(*emethods->free_all)();
	longjmp(setjmp_buffer, 1);
}

METHODDEF void
put_color_map(decompress_info_ptr cinfo, int ncolors, JSAMPARRAY cmap)
{
	fprintf(stderr,"call to readJPEG put_color_map, shouldn't happen\n");
}

METHODDEF void
putPixelsRGB(decompress_info_ptr cinfo, int nrows, JSAMPIMAGE data)
{
	int		x, y;
	JSAMPROW	r, g, b;
	unsigned char	*ip;

	if (image == NULL)
		image = ImageNew(cinfo->image_width, cinfo->image_height);
	ip    = image->data + (rowBase * image->width * 3);

	for (y = 0; y < nrows; y++) {
		r = data[0][y];
		g = data[1][y];
		b = data[2][y];
		for (x = 0; x < cinfo->image_width; x++) {
			*ip++ = *r++;
			*ip++ = *g++;
			*ip++ = *b++;
		}
	}
	rowBase += nrows;
}

METHODDEF void
putPixelsGray(decompress_info_ptr cinfo, int nrows, JSAMPIMAGE data)
{
	int		x, y;
	JSAMPROW	r, g, b;
	unsigned char	*ip;

	if (image == NULL)
		image = ImageNewGrey(cinfo->image_width, cinfo->image_height);
	ip    = image->data + rowBase * image->width;

	for (y = 0; y < nrows; y++) {
		r = data[0][y];
		for (x = 0; x < cinfo->image_width; x++) 
			*ip++ = *r++;
	}

	rowBase += nrows;
}

METHODDEF void nilFunc(decompress_info_ptr cinfo)
{
}

METHODDEF void
d_ui_method_selection(decompress_info_ptr cinfo)
{
	if (cinfo->jpeg_color_space == CS_GRAYSCALE) {
		cinfo->out_color_space = CS_GRAYSCALE;
		cinfo->methods->put_pixel_rows = putPixelsGray;
	} else {
		cinfo->methods->put_pixel_rows = putPixelsRGB;
	}

	cinfo->methods->output_init   = nilFunc;
	cinfo->methods->put_color_map = put_color_map;
	cinfo->methods->output_term   = nilFunc;
}

Image *ReadJPEG(char *file)
{
	struct Decompress_info_struct 		cinfo;
	struct Decompress_methods_struct	dc_methods;
	struct External_methods_struct		e_methods;

	image = NULL;
	rowBase = 0;

	if ((cinfo.input_file = fopen(file, "r")) == NULL) 
		return NULL;

	cinfo.output_file = NULL;

	cinfo.methods = &dc_methods;
	cinfo.emethods = &e_methods;

	emethods = &e_methods;
	e_methods.error_exit = error_exit;
	e_methods.trace_message = trace_message;
	e_methods.trace_level = 0;
	e_methods.num_warnings = 0;
	e_methods.first_warning_level = 0;
	e_methods.more_warning_level = 3;

	if (setjmp(setjmp_buffer)) 
		return NULL;

	jselmemmgr(&e_methods);

	dc_methods.d_ui_method_selection = d_ui_method_selection;

	j_d_defaults(&cinfo, TRUE);

	jselrjfif(&cinfo);

	jpeg_decompress(&cinfo);

	return image;
}

int TestJPEG(char *file)
{
	unsigned char	buf[2];
	FILE		*fd = fopen(file, "r");
	int		ret = 0;

	if (fd == NULL)
		return 0;

	if (2 == fread(buf, sizeof(char), 2, fd)) {
		if (buf[0] == 0xff && buf[1] == 0xd8)
			ret = 1;
	}

	fclose(fd);

	return ret;
}
