#include"CJPEGLoader.h"

#include"../../../Auxiliary/FileIO/CFileRead.h"
#include"../../../Auxiliary/FileIO/CFileWrite.h"
#include"../../../Auxiliary/Debug/CAssert.h"
#include"../../../Auxiliary/Debug/CException.h"
#include"../../../Auxiliary/Debug/CWarning.h"


extern "C" {
#define XMD_H
#include"../../../Import/ijg/jpeglib.h"
}

#ifdef USE_INTELIPP
#pragma comment(lib,"ippcorel.lib")
//#pragma comment(lib,"ippacemerged.lib")
//#pragma comment(lib,"ippacmerged.lib")
//#pragma comment(lib,"ippccemerged.lib")
//#pragma comment(lib,"ippccmerged.lib")
//#pragma comment(lib,"ippchemerged.lib")
//#pragma comment(lib,"ippchmerged.lib")
//#pragma comment(lib,"ippcvemerged.lib")
//#pragma comment(lib,"ippcvmerged.lib")
//#pragma comment(lib,"ippdcemerged.lib")
//#pragma comment(lib,"ippdcmerged.lib")
#pragma comment(lib,"ippiemerged.lib")
#pragma comment(lib,"ippimerged.lib")
#pragma comment(lib,"ippjemerged.lib")
#pragma comment(lib,"ippjmerged.lib")
//#pragma comment(lib,"ippmemerged.lib")
//#pragma comment(lib,"ippmmerged.lib")
//#pragma comment(lib,"ippremerged.lib")
//#pragma comment(lib,"ipprmerged.lib")
//#pragma comment(lib,"ippscemerged.lib")
//#pragma comment(lib,"ippscmerged.lib")
#pragma comment(lib,"ippsemerged.lib")
#pragma comment(lib,"ippsmerged.lib")

#endif

namespace Maid
{
	namespace CJPEGLoader
	{

	//	libjpeg をメモリから使えるようにするラッパ


/* メモリソースからのJPEG展開用マネージャ */
typedef struct {
	struct jpeg_source_mgr pub;	/* public fields */

	JOCTET * buffer;
	unsigned long buffer_length;
} memory_source_mgr;
typedef memory_source_mgr *memory_src_ptr;


METHODDEF(void) memory_init_source (j_decompress_ptr cinfo)
{
}


METHODDEF(boolean) memory_fill_input_buffer (j_decompress_ptr cinfo)
{
	memory_src_ptr src = (memory_src_ptr) cinfo->src;

	if( src->pub.bytes_in_buffer<=0 )
	{
		src->buffer[0] = (JOCTET) 0xFF;
		src->buffer[1] = (JOCTET) JPEG_EOI;
		src->pub.next_input_byte = src->buffer;
		src->pub.bytes_in_buffer = 2;
	}

	return TRUE;
}


METHODDEF(void) memory_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
	memory_src_ptr src = (memory_src_ptr) cinfo->src;

	if (num_bytes > 0) {
		src->pub.next_input_byte += (size_t) num_bytes;

		if( src->pub.bytes_in_buffer < (size_t) num_bytes )
		{
			src->pub.bytes_in_buffer = 0;
		}else
		{
			src->pub.bytes_in_buffer -= (size_t) num_bytes;
		}
	}
}

METHODDEF(void) memory_term_source (j_decompress_ptr cinfo)
{
}

GLOBAL(void)
jpeg_memory_src (j_decompress_ptr cinfo, const void* data, unsigned long len)
{
	memory_src_ptr src;

	if (cinfo->src == NULL) {	/* first time for this JPEG object? */
		cinfo->src = (struct jpeg_source_mgr *)
		(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
		  sizeof(memory_source_mgr));
		src = (memory_src_ptr) cinfo->src;
		src->buffer = (JOCTET *)
		(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
		  len * sizeof(JOCTET));
	}


	src = (memory_src_ptr) cinfo->src;

	src->pub.init_source = memory_init_source;
	src->pub.fill_input_buffer = memory_fill_input_buffer;
	src->pub.skip_input_data = memory_skip_input_data;
	src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
	src->pub.term_source = memory_term_source;

	src->pub.bytes_in_buffer = len;
	src->pub.next_input_byte = (JOCTET*)data;

//	src->EOI[0] = (JOCTET) 0xFF;
//	src->EOI[1] = (JOCTET) JPEG_EOI;

}


struct my_error_mgr {
  struct jpeg_error_mgr pub;	/* "public" fields */

};

typedef struct my_error_mgr * my_error_ptr;

METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{

}

/*!
 	\brief	JPGファイル操作クラス
\n			使い方は　http://www.syuhitu.org/other/jpeg/jpeg.html　を参照
 */





/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! Jpegファイルをメモリ上に読み込む
/*!
 */
void   Load( const mstring& FileName, CTextureBufferMemory& dst )
{
	my_error_mgr jerr;
	jpeg_decompress_struct cinfo;

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

	jpeg_create_decompress(&cinfo);

	MySTL::vector<unt08> FileImage;
	CFileRead::Read( FileName, FileImage );
	jpeg_memory_src(&cinfo, &(FileImage[0]), (int)FileImage.size() );

	jpeg_read_header(&cinfo, TRUE);
	jpeg_start_decompress(&cinfo);

	const int row_stride = cinfo.output_width * cinfo.output_components;

	const SIZE2DI size(cinfo.output_width, cinfo.output_height);
	PIXELFORMAT fmt = PIXELFORMAT_R08G08B08I;

	if( cinfo.out_color_components==3 )
	{	//	グレースケールなら cinfo.out_color_components==1 
		//	そのときには cinfo.colormap も設定される
		fmt = PIXELFORMAT_R08G08B08I;
	}else
	{
		MAID_ASSERT( true, "未対応" );
	}
	
	dst.Create( size, fmt );

	unt08* pSurface = (unt08*)dst.GetSurfaceEx(0).GetPlanePTR();



/*
	MySTL::vector<JSAMPLE*>	buffer(cinfo.output_height);

	for( int i=0; i<(int)buffer.size(); ++i )
	{
		buffer[i] = &(p[row_stride*i]);
	}

	//USE_WARNING
	while (cinfo.output_scanline < cinfo.output_height) {
		jpeg_read_scanlines(&cinfo,
			&buffer[cinfo.output_scanline],
			cinfo.output_height - cinfo.output_scanline);
	}
*/


//	MAID_WARNING( MAIDTEXT("jpeg_read_scanlines") );
	{
		MySTL::vector<JSAMPLE>	buffer((row_stride+15)&(~15));

		JSAMPLE* pBuff = &buffer[0];

		unt08* pDst = pSurface;

		while (cinfo.output_scanline < cinfo.output_height) {
			jpeg_read_scanlines(&cinfo, &pBuff, 1);

			memcpy( pDst, pBuff, row_stride );
			pDst += row_stride;
		}
	}

//	MAID_WARNING( MAIDTEXT("jpeg_finish_decompress") );
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
}


void   Save( const mstring& FileName, CTextureBufferMemory& src )
{

}

}
}