/*=================================================================================
	IMPress V3
	    IMPress Sample Application (Decode JPEG to VRAM memory )

	 Copyright (C) 2007-2010 IT Access.,Co.Ltd. All Rights Reserved.

	2010/03/05 構造体確認用のCode追加他


 This software is the confidential and proprietary information
 of IT Access.,Co.Ltd.

=================================================================================*/

// CQ出版 SH-2A デモ開発環境向けのDEFINE
#ifndef	WIN32
	#define	_FOR_SHCQ
#endif

// 2010/03/05 構造体Packのためのテスト
//　構造体pack定義変更時は、jpegdec.c のdefineと併せて比較すること
//#define	_PACK_CHECK


#ifdef	_FOR_SHCQ

//	#include "cpu.h"
	#include "cpu_init.h"
	#include "cpu_uart.h"
	#include "tinylib.h"

	#include "ff.h"

	#ifndef	NULL
		#define	NULL	0
	#endif
	typedef	FIL FILE ;
	static FILE File1 ;
	#define	fclose	f_close

	// FileSystemがないための暫定Dummy
	//（Callback処理に渡すために宣言しますが、 Sample内部では使用しません）
/*	struct _iobuf {
			char *_ptr;
			int   _cnt;
			char *_base;
			int   _flag;
			int   _file;
			int   _charbuf;
			int   _bufsiz;
			char *_tmpfname;
			};
	typedef struct _iobuf FILE;	
*/

	// デバッグ用printf（JPEGファイル情報表示サンプル）
	#define	LogOut	t_printf

	// VRAMアドレスを指定する場合にDEFINEします。UNDEFした場合は、ヒープメモリにAllocします。
	#define	_USE_VRAM_ADDRESS

#else
	// Set bench for windows only
//	#define	_BENCH
	#define	_USE_VRAM_ADDRESS

	#include <stdio.h>
	#include <string.h>
	#define	LogOut	printf
	#ifdef	_BENCH
		#include <time.h>
		unsigned long tickcounter;
		#define GET_TIME()		clock()
	#endif
#endif



#ifdef	WIN32
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif

#include "impress.h"
#include "lserr.h"
#include "lsjpg.h"

//#define	_LINE_DECODE	//09/08/31 test

/*---------------------------------------------------------
  main()関数を使用する場合に_USE_MAINをDEFINEします。

　main()関数時は、console からJPEGファイル名を指定します。
	Ex) Program <JPEG filename>

　そうでない場合は、INCLUDE_SAMPLE_JPEGをDEFINEして、
 　埋め込まれたCデータのJPEGファイルを使用します。
 　（ファイルシステムがない場合のサンプル）

 　宣言：　jpegdec_sample( 表示用VRAMアドレス )

　データを埋め込まず、ICE等からJPEGデータをLoadする場合などは、
　JPEG_MEM_ADDR　にJPEGファイルをLoadするメモリのアドレス
　JPEG_MEM_MAX	 にメモリ空間のMAX
　を入れてください。

---------------------------------------------------------*/
//#define	INCLUDE_SAMPLE_JPEG
//#define	JPEGFILENAME "C:\\test1.jpg"
//#define	JPEGFILENAME "C:\\test2.jpg"

#ifdef	INCLUDE_SAMPLE_JPEG
	#include "jpegdata.c" 
	#define	JPEG_MEM_ADDR		JPEG_DATA
	#define	JPEG_MEM_MAX		sizeof(JPEG_DATA)
#endif


/* -----------------------------------------
	出力画像空間の設定
	OUTPUT Image buffer Define 
------------------------------------------*/

// JPEGデータの表示サイズ（StretchJPEGを使用する場合のみ有効）
//	入力ファイルに画像サイズ如何に関わらず任意に設定可能
// 　但し、_USE_STRETCHもしくは、_USE_CLIPを使わない場合は、
//		必ず入力JPEG画像サイズより大きな値を設定すること。

//#define	DISPLAY_WIDTH	320
//#define	DISPLAY_HEIGHT	240
#define	DISPLAY_WIDTH	256
#define	DISPLAY_HEIGHT	176

#define	_USE_STRETCH

#ifdef	_WIN32
	// VRAM の横方向改行幅 16bitRGBなのでx2
	#define	DISPLAY_LINEINT	(320*2)
#else	// SH LCD向け
	// 現在512で改行　RAM4（Target)に直接描画する場合
	#define	DISPLAY_LINEINT	(512*2)
#endif


/*=============================================================

	Callback 関連定義

=============================================================*/

// JPEGデータを全てメモリに展開している場合のダミーCallBack
// filesystemがない場合にのみ使用

//#define	MEM_CALLBACK

/*-------------------------------------------------
	Memory based callback ( just use for seeking )
-------------------------------------------------*/

#ifdef	MEM_CALLBACK

#define	GetStreamCallBack	MemGetStreamCallBack
#define	SeekStreamCallBack	MemSeekStreamCallBack

/* Sample CallBack Function (Memory) */
int STD_CALL MemGetStreamCallBack(void *buffer, int size, void *param);
int STD_CALL MemSeekStreamCallBack(void *param,int size, int origin );

#ifndef	NULL
	#define	NULL	0
#endif

// Alloc whole size of JPEG file, not reentrant.
static unsigned long STREAMBUF_SIZ = 0 ;
static unsigned long StreamOffset = 0 ;
static unsigned char *StreamBuffer = NULL ;
static unsigned char  *StreamPointer = NULL ;


/*-----------------------------------------------------
	FILE based callback

  FileSystemがある場合は通常こちらを使う
  STREAMBUF_SIZに定義したバッファを用いてFileをLoadする
-----------------------------------------------------*/
#else

/* Stream Buffer */
#define STREAMBUF_SIZ	4096	/* バッファサイズは任意 */
static unsigned char StreamBuffer[STREAMBUF_SIZ];
#define	StreamPointer	StreamBuffer

#define	GetStreamCallBack	FileGetStreamCallBack
#define	SeekStreamCallBack	FileSeekStreamCallBack

/* Sample Stream CallBack (FILE) */
int STD_CALL FileGetStreamCallBack(void *buffer, int size, void *param);
int STD_CALL FileSeekStreamCallBack(void *param,int size, int origin );

#endif	//	#ifdef	MEM_CALLBACK


/*=====================================================
	Log sample
=====================================================*/

/*
void	LogOut( char *format, ... )
{
	va_list	ap;

	va_start( ap, format );
	if( logfp )
		vfprintf( logfp, format, ap );
	vprintf( format, ap );
	va_end(ap);
}
*/

/*-----------------------------------------------
	JFIF情報表示
-----------------------------------------------*/
void jfifinfo_console_out( LsJfifInfo *jfifinfo )
{
	LogOut("Major Version     : %d\n", (int)jfifinfo->v1 );
	LogOut("Minor Version     : %d\n", (int)jfifinfo->v2 );
	LogOut("Units             : %d\n", (int)jfifinfo->u );
	LogOut("Xdensity          : %d\n", (int)jfifinfo->xd );
	LogOut("Ydensity          : %d\n", (int)jfifinfo->yd );
	LogOut("Thumbnail-Width   : %d\n", (int)jfifinfo->xt );
	LogOut("Thumbnail-Height  : %d\n", (int)jfifinfo->yt );

	/* サムネイルがあるかどうか */
	if( jfifinfo->xt && jfifinfo->xt )
		LogOut("Thumbnail Image   : Exist\n");
	else
		LogOut("Thumbnail Image   : Not Exist\n");
}

/*-----------------------------------------------
	EXIF情報表示
-----------------------------------------------*/
void exifinfo_console_out( LsTiffInfo *exifinfo )
{
	exifinfo->ImageDescription[63] = '\0';
	exifinfo->Make[63] = '\0';
	exifinfo->Model[63] = '\0';
	exifinfo->DateTime[19] = '\0';

	LogOut("ImageDescription      : %s\n",		exifinfo->ImageDescription);
	LogOut("Make                  : %s\n",		exifinfo->Make);
	LogOut("Model                 : %s\n",		exifinfo->Model);
	LogOut("Orientation           : %d\n",		(int)exifinfo->Orientation );
	LogOut("XResolution           : %d/%d\n",	(int)exifinfo->XResolution[0], (int)exifinfo->XResolution[1] );
	LogOut("YResolution           : %d/%d\n",	(int)exifinfo->YResolution[0], (int)exifinfo->YResolution[1] );
	LogOut("ResolutionUnit        : %d\n",		(int)exifinfo->ResolutionUnit );
	LogOut("DateTime              : %s\n",		exifinfo->DateTime);
	LogOut("YCbCrPositioning      : %d\n",		(int)exifinfo->YCbCrPositioning );
	LogOut("ExifIFDPointer        : %d\n",		(int)exifinfo->ExifIFDPointer );

	LogOut("ExifVersion             : %c%c%c%c\n",
			(char)exifinfo->ExifVersion[0], (char)exifinfo->ExifVersion[1], 
			(char)exifinfo->ExifVersion[2], (char)exifinfo->ExifVersion[3] );
	LogOut("ComponentsConfiguration : %08lX\n", (long)exifinfo->ComponentsConfiguration);
	LogOut("FlashPixVersion         : %c%c%c%c\n",
		(char)exifinfo->FlashPixVersion[0], (char)exifinfo->FlashPixVersion[1],
		(char)exifinfo->FlashPixVersion[2], (char)exifinfo->FlashPixVersion[3] );
	LogOut("ColorSpace              : %d\n", (int)exifinfo->ColorSpace);
	LogOut("PixelXDimension         : %d\n", (int)exifinfo->PixelXDimension);
	LogOut("PixelYDimension         : %d\n", (int)exifinfo->PixelYDimension);
}

/*-----------------------------------------------
	Jpeg情報表示
-----------------------------------------------*/
void jpginfo_console_out( unsigned char appmode, LsJpgInfo *jpginfo )
{
	char	*mes_appmode[3]={"NOTHING","JFIF","EXIF"};

	if( appmode < 3 )
		LogOut("APP_MODE : %s\n" ,mes_appmode[appmode]);
	else 
		LogOut("APP_MODE : UNKNOWN\n");

	switch(appmode){
	case JFIF_MODE:
		jfifinfo_console_out(&jpginfo->JfifInfo);
		break;
	case EXIF_MODE:
		exifinfo_console_out(&jpginfo->MainExifInfo);
		exifinfo_console_out(&jpginfo->ThmExifInfo);
		break;
	}
}


/*===============================================================
	メモリ処理用のラッパー関数群

  IMPress のライブラリからもCallされるため、
  ターゲットの標準関数もしくは独自実装関数をインプリメントすること。

  ※JPEGデコーダのみの実装時は、LsAlloc,LsFreeは不要。
 
===============================================================*/
//#define RAM_PAGE1		0x3C028000	/* 大容量内蔵RAM ページ1( 80KB) */
//#define RAM_PAGE2		0x3C03C000	/* 大容量内蔵RAM ページ2( 80KB) */
//#define RAM_PAGE3		0x3C050000	/* 大容量内蔵RAM ページ3(160KB) */
//#define RAM_PAGE4		0x3C078000	/* 大容量内蔵RAM ページ4(240KB) */
//#define RAM_PAGE5		0x3C0B4000	/* 大容量内蔵RAM ページ5(304KB) */
// 現在、GealではPAGE5→ PAGE4にRedrawしている

//#define RAM_PAGE		0x3C050000	/* 大容量内蔵RAM ページ3 Cacheなし */
#define RAM_PAGE		0x1C050000	/* 大容量内蔵RAM ページ3 Cacheあり */
// ほとんどDecode時間は変わらず...
//#define	RAM_PAGE		0xFFF80000	// 高速RAM -FFF8FFFF (64KB)  ちょっと足りない?

#define	_USER_MALLOC_ADR		// mallocがない場合の実装

#ifdef	_USER_MALLOC_ADR		// mallocがない場合、Staticなワークを使う
static	unsigned char *Heap_Addr ;

// W720 のJPEGで、全ワークが約40KBなので、80KBあればOKのはず
#ifdef	_FOR_SHCQ
	#define	HEAP_ADR	RAM_PAGE
#else
	static unsigned char HEAP_ADR[0x14000] ;
#endif

void Init_LsAlloc( void )
{
	Heap_Addr = (void *)HEAP_ADR ;
}

void *LsAlloc(unsigned int size)
{
	void * addr = Heap_Addr ;
	Heap_Addr += size ;	// ポインタをインクリメントするだけ
	return ( addr );
}

void LsFree(void *ptr)
{
	// 常にInit_LsAllocからStartするので、なにもしない
}

#else

//static int Alloc_Total = 0 ;

void *LsAlloc(unsigned int size)
{
//	Alloc_Total += size ;
	return malloc( size );
}

void LsFree(void *ptr)
{
	if(ptr) free(ptr);
}

#endif


void *LsMemcpy( void *dst, const void *src, unsigned int len )
{
	return memcpy( dst, src, len );
}

void *LsMemmove( void *dst, const void *src, unsigned int len )
{
	return memmove( dst, src, len );
}

void *LsMemset( void *dst, int c, unsigned int len)
{
	return memset( dst, c, len );
}


/*=====================================================================

	Callback 

=====================================================================*/

#ifdef	MEM_CALLBACK

/* -----------------------------------------
	Memory based callback
------------------------------------------*/
/* Sample CallBack Function (Memory) */

// No need to use this function, without filesystem
#ifndef	INCLUDE_SAMPLE_JPEG	// Use JPEG data as C data

void *read_file_to_mem( FILE *fp )
{
	fpos_t fsize ;
	void *po ;

	fseek( fp, 0, SEEK_END ) ;
	fgetpos( fp,&fsize );
	fseek( fp, 	StreamOffset =0, SEEK_SET ); 

	StreamPointer = po = LsAlloc( STREAMBUF_SIZ = (unsigned long)fsize ) ;
	fread( po, sizeof(char), STREAMBUF_SIZ, fp );
	return po ;
}

#endif	// INCLUDE_SAMPLE_JPEG 


int STD_CALL MemGetStreamCallBack(void *data, int size, void *param)
{
	// Just set offset
	StreamOffset += size ;
	StreamPointer += size ;
	return size ;
}


int STD_CALL MemSeekStreamCallBack(void *param,int size, int origin )
{
	if( origin == LS_SEEK_SET ) {
		StreamOffset = size ;
		StreamPointer = &((unsigned char *)StreamBuffer)[size] ;
		return 0 ;
	}
	else if( origin == LS_SEEK_CUR ) {
		StreamOffset += size ;
		StreamPointer += size ;
		return 0 ;
	}
	return	-1;
}


/* -----------------------------------------
	FILE based callback
------------------------------------------*/
#else

int STD_CALL FileGetStreamCallBack(void *data, int size, void *param)
{
	int	readlen;

#ifdef	_FOR_SHCQ
	int ret = f_read((FILE*)param, data, size, &readlen );
	if ( ret != FR_OK ) return 0 ;
#else
	readlen = fread(data, sizeof(char), size, (FILE*)param);
#endif

	return readlen;
}

int STD_CALL FileSeekStreamCallBack(void *param,int size, int origin )
{
#ifdef	_FOR_SHCQ
	int ret ;
	if( origin == LS_SEEK_SET )
		ret = f_lseek((FILE*)param, size );
	else if( origin == LS_SEEK_CUR )
		ret = f_lseek((FILE*)param, ((FILE*)param)->fptr + size );
	if ( ret == FR_OK ) return 0 ; 
#else
	if( origin == LS_SEEK_SET )
		return fseek((FILE*)param, size, SEEK_SET );
	if( origin == LS_SEEK_CUR )
		return fseek((FILE*)param, size, SEEK_CUR );
#endif
	return	-1;
}

#endif	//#ifdef	MEM_CALLBACK



/*=====================================================================
	Sample LsImage Control

　Decode用imageデータの処理関数群。
　表示がVRAM固定の場合などは定数にて実装するなど、任意に変更可。

=====================================================================*/

int image_alloc( LsImage *image )
{
	if( image->size == 0 )
		image->size = image->lineint * image->height;

#ifdef	_USE_VRAM_ADDRESS
	// Set VRAM Address for decode image
//	image->pixels = ( void *)_USE_VRAM_ADDRESS ;
#else
	if( image->pixels == NULL )
		image->pixels = LsAlloc( image->size );
#endif
	if( image->pixels == NULL )
		return (-1);

	if( image->mode == LS_MODE_INDEX ){
//		面倒なので今回INDEXモードはサポートしない　（stretchでは対応できているはずだけど）
//		image->palcount = 256;
//		image->palbuf = LsAlloc( sizeof(LSPAL) * image->palcount );
//		if( image->palbuf == 0 )
			return (-1);
	}
	if( image->palbuf )
		memset( image->palbuf, 0, sizeof(LSPAL) * image->palcount );

	memset( image->pixels, 0, image->size );

	return 0;
}

int image_free( LsImage *image )
{
	if( image->object )
		LsFree( image->object );

#ifndef	_USE_VRAM_ADDRESS
	if( image->pixels )
		LsFree( image->pixels );
#endif
	if( image->palbuf )
		LsFree( image->palbuf );

//	memset( image, 0, sizeof(LsImage) );

	return 0;
}




/*=====================================================================
	DECODE JPG Sample code
=====================================================================*/
#if 0 //今回使わない(SHサンプル）
/*---------------------------------------------------
	主画像デコード
	（Stretch(拡縮)なし）
---------------------------------------------------*/
static int JpgDec( FILE *fp, LsImage *image )
{
	HJpgDec			hjpg;
	HLsStream		hstream;
	LsImageInfo		info;
	int				ret;
	long			wksize;
	void			*wkbuf;
	unsigned char	appmode	= 0;
	LsJpgInfo		jpginfo	= {0};

	hjpg    = NULL;
	hstream = NULL;
	wkbuf   = NULL;
	ret     = 0;

	if( fp == NULL )	return 1;
	if( image == NULL )	return 1;
	memset( &info, 0, sizeof(LsImageInfo) );

	/*----------------------------
		ハンドル確保
	----------------------------*/
	{	long	siz = LsJpgDecGetHandleSize();
	hjpg = LsAlloc( siz );
	ret = LsJpgDecInitHandle(hjpg);
	if(ret)		goto error;
	}

	/*----------------------------
	  ストリーム登録
	----------------------------*/
	{	long	siz = LsStreamGetHandleSize();
	hstream = LsAlloc( siz );
	ret = LsStreamInitHandle(hstream, StreamPointer, STREAMBUF_SIZ, fp, GetStreamCallBack);
	if(ret)		goto error;
	}

	ret = LsStreamSetSeek(hstream,SeekStreamCallBack);
	if(ret)		goto error;

	ret = LsJpgDecSetStream(hjpg, hstream);
	if(ret)		goto error;
	
	/*----------------------------
	  画像情報の取得
	----------------------------*/
	//TEST
	ret = sizeof(LsJpgInfo) ;
 	ret = LsJpgDecGetInfo( hjpg, &info, &wksize, &appmode, &jpginfo );
	if(ret)		goto error;

	/* Jpeg情報を表示 */
	jpginfo_console_out( appmode, &jpginfo );

	/*----------------------------
	  出力画像メモリを設定します
	----------------------------*/
	*((LsImageInfo*)image) = info;
	image->lineint = DISPLAY_LINEINT ;	// 表示サイズは画像情報を元に。改行幅のみVRAM等に合わせて指定。

	ret = image_alloc( image );
	if(ret)		goto error;

	/*----------------------------
	  ワークバッファ設定
	----------------------------*/
	if(!ret && wksize > 0) {
		wkbuf = LsAlloc(wksize);
		ret= LsJpgDecSetBuffer( hjpg, wkbuf );
		if(ret)		goto error;
	}

	/*----------------------------
	  出力画像登録
	----------------------------*/
	ret = LsJpgDecStart( hjpg, (LsImageInfo*)image );
	if(ret)		goto error;

	/*----------------------------
	  ライン単位実行 / 一括実行
	----------------------------*/
#ifndef	_LINE_DECODE
	{	// Decode one image
		unsigned char *plane;
		plane = (unsigned char*)image->pixels;
		ret = LsJpgDecExec( hjpg, (void*)plane );
		if(ret)
			goto error;
	}
#else
	{	// Decode each line
		unsigned char *line;
		int y ;	
		for( y=0; y< image->height; y++ ){
			line = (unsigned char*)image->pixels + image->lineint * y;
			ret = LsJpgDecLine( hjpg, (void*)line );
			if( ret )
				goto error;
		}
	}
#endif
	/*----------------------------
	  終了処理
	----------------------------*/
error:

	/* データ終了 */
	if( ret==ErrEnd && image->height!=0 )
		ret = 0;

	if( hjpg )		LsFree( hjpg );
	if( hstream )	LsFree(hstream);
	if( wkbuf )		LsFree( wkbuf );

	return ret;
}
#endif


/*-------------------------------------------------------------

	サムネイルデコード

-------------------------------------------------------------*/
//#if 0 //今回使わない(SHサンプル）

static int ThmDec( FILE *fp, LsImage *image )
{
	HJpgDec			hjpg	= NULL;
	HLsStream		hstream	= NULL;
	LsImageInfo		info	= {0};
	int				ret		= 0;
	long			wksize	= 0;
	void			*wkbuf	= NULL;
	LsJpgInfo		jpginfo	= {0};
	unsigned char	appmode	= 0;

	if( fp == NULL )	return 1;
	if( image == NULL )	return 1;

	/*----------------------------
	  ハンドル確保 
	----------------------------*/
	hjpg = LsAlloc(LsJpgDecGetHandleSize());
	ret = LsJpgDecInitHandle(hjpg);
	if(ret)		goto error;

	/*----------------------------
	  ストリーム登録
	----------------------------*/
	hstream = LsAlloc(LsStreamGetHandleSize());
	ret = LsStreamInitHandle(hstream, StreamPointer, STREAMBUF_SIZ, fp, GetStreamCallBack);
	if(ret)		goto error;
	ret = LsStreamSetSeek(hstream,SeekStreamCallBack);
	if(ret)		goto error;

	ret = LsJpgDecSetStream(hjpg, hstream);
	if(ret)		goto error;
	
	/*----------------------------
	  画像情報の取得
	----------------------------*/
	ret = LsThmDecGetInfo( hjpg, &info, &wksize, &appmode, &jpginfo );
	if(ret)		goto error;

	/*----------------------------
	  出力画像メモリを設定します
	----------------------------*/
	*((LsImageInfo*)image) = info;

//	image->mode   = LS_MODE_RGB ;
//	image->width  = DISPLAY_WIDTH ;
//	image->height = DISPLAY_HEIGHT ;
	image->lineint = DISPLAY_LINEINT ;	

	ret = image_alloc( image );
	if(ret)		goto error;

	/*----------------------------
	  ワークバッファ設定
	----------------------------*/
	if(!ret && wksize > 0) {
		wkbuf = LsAlloc(wksize);
		ret= LsJpgDecSetBuffer( hjpg, wkbuf );
		if(ret)		goto error;
	}

	/*----------------------------
	  出力画像登録
	----------------------------*/
	ret = LsThmDecStart( hjpg, (LsImageInfo*)image );
	if(ret)		goto error;

	/*----------------------------
	  デコード実行
	----------------------------*/
	ret = LsThmDecExec( hjpg, image->pixels );
	if(ret)		goto error;

	/*----------------------------
	  終了処理
	----------------------------*/
error:
	if( hjpg )		LsFree( hjpg );
	if( hstream )	LsFree(hstream);
	if( wkbuf )		LsFree( wkbuf );

	return ret;
}
//#endif

/*-------------------------------------------------------------

	DECODE JPG STRETCH
	（拡大縮小つきDecode。通常はこちらを使用する）

-------------------------------------------------------------*/
int JpgDecStretch( FILE *fp, LsImage *image )
{
	HJpgDec			hjpg;
	HLsStream		hstream;
	LsImageInfo		info;
	int				ret;
	void			*stchbuf;
	long			wksize;
	void			*wkbuf;
	unsigned char	appmode	= 0;
	LsJpgInfo		jpginfo	= {0};

	hjpg    = NULL;
	hstream = NULL;
	wkbuf   = NULL;
	stchbuf = NULL;
	ret     = 0;

	if( !fp )		return 1;
	if( !image )	return 1;

	memset( &info, 0, sizeof(LsImageInfo) );

	/*----------------------------
	  ハンドル確保
	----------------------------*/
	hjpg = LsAlloc(wksize=LsJpgDecGetHandleSize());
	if(!hjpg){
		ret = 1;
		goto error;
	}
	ret = LsJpgDecInitHandle(hjpg);
	if(ret)		goto error;

	/*----------------------------
	  ストリーム登録
	----------------------------*/
	hstream = LsAlloc(wksize=LsStreamGetHandleSize());
	if(!hstream){ 
		ret = 1;
		goto error;
	}
	ret = LsStreamInitHandle(hstream, StreamPointer, STREAMBUF_SIZ, fp, GetStreamCallBack);
	if(ret)		goto error;

	ret = LsStreamSetSeek(hstream,SeekStreamCallBack);
	if(ret)		goto error;

	ret = LsJpgDecSetStream(hjpg, hstream);
	if(ret)		goto error;

	/*----------------------------
	  画像情報の取得
	----------------------------*/
 	ret = LsJpgDecGetInfo( hjpg, &info, &wksize, &appmode, &jpginfo );
	if(ret)		goto error;

	/* Jpeg情報を表示 */
//	jpginfo_console_out( appmode, &jpginfo );
	
	/*----------------------------
	  出力画像メモリを設定します
	----------------------------*/
	*((LsImageInfo *)image) = info;

	// Stretch mode can change resolution and mode.
	image->mode   = LS_MODE_RGB ;
	image->width  = DISPLAY_WIDTH ;
	image->height = DISPLAY_HEIGHT ;
	image->lineint = DISPLAY_LINEINT ;	

	ret = image_alloc( image );
	if(ret)		goto error;

	/*----------------------------
	  ワークバッファ設定
	----------------------------*/
	if( !ret && wksize > 0) {
		wkbuf = LsAlloc(wksize);
		ret = LsJpgDecSetBuffer( hjpg, wkbuf );
		if(ret)		goto error;
	}
	
	/*----------------------------
	  クリッピング設定
	----------------------------*/
#ifdef		_USE_CLIP
	ret = LsJpgDecSetClipper( hjpg, &CripRect );	// with clip
#else
//	ret = LsJpgDecSetClipper( hjpg, NULL );	// No clip
#endif
	if(ret)		goto error;

	/*----------------------------
	  ワークバッファ設定
	----------------------------*/
	stchbuf = LsAlloc( info.width * sizeof(long) );
	ret = LsJpgDecSetStretchBuffer( hjpg, stchbuf );
	if(ret)		goto error;

	/*----------------------------
	  出力画像登録
	----------------------------*/
	ret = LsJpgDecStartStretch( hjpg, (LsImageInfo*)image );
	if(ret)		goto error;

	/*----------------------------
	  ライン単位実行 / 一括実行
	----------------------------*/
#ifndef	_LINE_DECODE
	{
		unsigned char *plane;
		plane = (unsigned char*)image->pixels;
		ret = LsJpgDecExecStretch(hjpg, (void*)plane );
		if(ret)		goto error;
	}
#else
	{
		unsigned char *line;
		int y ;

		line = (unsigned char*)image->pixels;
		for( y=0; y<image->height; y++ ) {
			ret = LsJpgDecLineStretch(hjpg, (void*)line);
			if(ret)		goto error;
			line += image->lineint;
		}
	} 
#endif

	/*----------------------------
	  終了処理
	----------------------------*/
error:

	/* データ終了 */
	if( ret==ErrEnd && image->height!=0 )
		ret = 0;

	if( hjpg )		LsFree( hjpg );
	if( hstream )	LsFree( hstream );
	if( wkbuf )		LsFree( wkbuf );
	if( stchbuf )	LsFree( stchbuf );

	return ret;
}


#ifdef	DUMP_FILENAME
void dump_image(  LsImage *image )
{
	FILE *fp ;
	if((fp = fopen( DUMP_FILENAME, "wb"))==NULL){
		LogOut("FILE : %s open error.\n", DUMP_FILENAME );
		return ;
	}
	fwrite( image->pixels, sizeof(char), image->size, fp ) ;
	fclose( fp ) ;
}
#endif


/*==============================================================

	Sample Main

==============================================================*/
#ifdef	INCLUDE_SAMPLE_JPEG
int jpegdec_sample( void *vram_addr )
#else
int jpegdec_sample( void *vram_addr, char *fname )
#endif
{
	LsImage	image;
	int		result;
	FILE	*fp ;

#ifdef	_PACK_CHECK
	extern void print_struct(void) ;
	print_struct() ;
#endif

#ifdef	_USER_MALLOC_ADR		// mallocがない場合、Staticなワークを使う
	Init_LsAlloc();
#endif

#ifdef	INCLUDE_SAMPLE_JPEG	// Use JPEG data as C data
	StreamOffset = 0 ;
	STREAMBUF_SIZ = JPEG_MEM_MAX ;
	StreamBuffer = StreamPointer = (unsigned char *)JPEG_MEM_ADDR  ;
	fp = (FILE *)1 ;	// DUMMY
#else
	// Load JPEG from file , come from argv[] 
//	if( argc < 2) 	return 1;

#ifdef	_FOR_SHCQ
	if ( f_open(fp=&File1, fname, (BYTE)FA_READ ) != FR_OK ) { 
#else
	if((fp = fopen( fname, "rb"))==NULL){
#endif
		LogOut("FILE : %s open error.\n", fname);
		return 2;
	}
	else	LogOut("Open File : %s\n" ,fname );

	// FileCallBack時は、CallBack関数内でFileReadを行うので、ここではReadしない
	// メモリCallBack（FileSystemがない）場合、この時点で全てメモリに展開する
#ifdef	MEM_CALLBACK
	StreamBuffer = read_file_to_mem( fp ) ;
	fclose(fp);
#endif

#endif

	memset(&image, 0, sizeof(LsImage));

#ifdef	_USE_VRAM_ADDRESS
	// Set VRAM address from upper routine.
	image.pixels = vram_addr ;
#endif

	//	If decode thumnail
//	result = ThmDec(fp, &image);

#ifndef	_USE_STRETCH
	//	If decode without scaling
	result = JpgDec(fp, &image);
#else
	// Decode fit to screen
	result = JpgDecStretch( fp, &image );
#endif
	
#ifndef	INCLUDE_SAMPLE_JPEG	// Use JPEG data as C data

#ifdef	MEM_CALLBACK
	free( StreamBuffer ) ;
#else
	fclose(fp);
#endif

#endif

	if(result){
//		LogOut("!!! error code = %04X\n", result);
	}

#ifdef	_BENCH
	tickcounter=GET_TIME() - tickcounter;
	printf("DECODE TIME : %f[sec]\n", ((float)tickcounter)/CLOCKS_PER_SEC);
#endif

//	Insert Display function here
//


	
	// For debug and test
#ifdef	DUMP_FILENAME
	dump_image( &image ) ;
#endif

	image_free(&image);

	return result ;
}


#ifdef	_PACK_CHECK
void print_struct( void )
{
	LogOut("LsJpgInfo size : %d\n", sizeof(LsJpgInfo) );
	LogOut("LsJfifInfo size : %d\n", sizeof(LsJfifInfo) );
	LogOut("LsJfxxInfo size : %d\n", sizeof(LsJfxxInfo) );
	LogOut("LsG3FaxInfo size : %d\n", sizeof(LsG3FaxInfo) );
	LogOut("LsTiffInfo size : %d\n\n", sizeof(LsTiffInfo) );

	LogOut("LsImageInfo size : %d\n", sizeof(LsImageInfo) );
	LogOut("LsImage size : %d\n", sizeof(LsImage) );
	LogOut("LsThm size : %d\n", sizeof(LsThm) );
	LogOut("LsMatrix size : %d\n\n", sizeof(LsMatrix) );
}
#endif
