#include "jpeglib.h"
#include <setjmp.h>

struct retImage{
	long width, height;
	void *buffer;
};

struct my_error_mgr {
  struct jpeg_error_mgr pub;	/* "public" fields */
  jmp_buf setjmp_buffer;	/* for return to caller */
};

typedef struct my_error_mgr * my_error_ptr;

METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  my_error_ptr myerr = (my_error_ptr) cinfo->err;

  /* Always display the message. */
  /* We could postpone this until after returning, if we chose. */
  (*cinfo->err->output_message) (cinfo);

  /* Return control to the setjmp point */
  longjmp(myerr->setjmp_buffer, 1);
}

void put_scanline_someplace(void *writeBuffer, void *scanLineBuffer, int rowSize, int whichLine)
{
	char *writeWhere = (char *)writeBuffer + whichLine*((rowSize)/3)*4;
	int j=0;
	for(int i=0;i<rowSize;i+=3)
	{
		writeWhere[j] = ((char*)scanLineBuffer)[i];
		writeWhere[j+1] = ((char*)scanLineBuffer)[i+1];
		writeWhere[j+2] = ((char*)scanLineBuffer)[i+2];
		j += 4;
	}
}

struct retImage readJPG(void *jpegDat, int fileSize)
{
  struct retImage hop;
  hop.width = 0;
  hop.height= 0;
  hop.buffer= 0;
  struct jpeg_decompress_struct cinfo;
  struct my_error_mgr jerr;
  JSAMPARRAY buffer;		/* Output row buffer */
  int row_stride;		/* physical row width in output buffer */
//	-------------------------
	struct daBuff *fileBuff;
	fileBuff = new struct daBuff[1];
	fileBuff->size = fileSize;
	fileBuff->dat = jpegDat;
//	-------------------------

  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = my_error_exit;

  if (setjmp(jerr.setjmp_buffer)) {
    jpeg_destroy_decompress(&cinfo);
    return hop;
  }
  jpeg_create_decompress(&cinfo);
  jpeg_stdio_src(&cinfo, fileBuff);
  (void) jpeg_read_header(&cinfo, TRUE);
  cinfo.buffered_image = TRUE;
  (void) jpeg_start_decompress(&cinfo);
  hop.buffer = (void*)new char[cinfo.output_width*cinfo.output_height*4];
  row_stride = cinfo.output_width * cinfo.output_components;
  buffer = (*cinfo.mem->alloc_sarray)
		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

//  int wLine =0 ;
//  while (cinfo.output_scanline < cinfo.output_height) {
//    (void) jpeg_read_scanlines(&cinfo, buffer, 1);
//    put_scanline_someplace(hop.buffer, buffer, row_stride, wLine++);


  while (! jpeg_input_complete(&cinfo))
  {
	jpeg_start_output(&cinfo, cinfo.input_scan_number);
	int wLine =0 ;
	while (cinfo.output_scanline < cinfo.output_height) {
		(void) jpeg_read_scanlines(&cinfo, buffer, 1);
		put_scanline_someplace(hop.buffer, buffer[0], row_stride, cinfo.output_height-(++wLine));
	}
	jpeg_finish_output(&cinfo);
  }

  (void) jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);

  delete fileBuff->dat;	// delete jpeg file data
  delete fileBuff;
  hop.width  = cinfo.output_width;
  hop.height = cinfo.output_height;
  return hop;
}
