#include "jpeg_lcd.h"

BYTE Buff[4096] __attribute__ ((aligned(4)));


/*********************************************************************************************
  函数名称:    STM32_in_func
  函数功能:    用户自定义的用于输入文件数据的功能函数
  入口参数:    见函数头
  出口参数:    读取或者删除的数据量 
  备注说明:    本函数在解码准备工作中用于读取文件头信息
*********************************************************************************************/
UINT JPEG_In_Func( 
											JDEC* jd,    		/*储存待解码的对象信息的结构体 */ 
											BYTE* buff,   	/* 输入数据缓冲区 (NULL:删除数据) */ 
											UINT nd      		/*需要从输入数据流读出/删除的数据量*/ 
									) 
{
		FIL * dev;	
    UINT rb; 
    dev = (FIL *)jd->device;    		/* 待解码的文件的信息，使用FATFS中的FIL结构类型进行定义 */   
    if (buff)     									/* 读取数据有效，开始读取数据 */ 
    { 
        f_read(dev, buff, nd, &rb); /* 调用FATFS的f_read函数，用于把jpeg文件的数据读取出来 */
        return rb;        					/* 返回读取到的字节数目*/ 
    }  
    else  
    { 
        return (f_lseek(dev, f_tell(dev) + nd) == FR_OK) ? nd : 0;/* 重新定位数据点，相当于删除之前的n字节数据 */ 
    } 
}  


/*********************************************************************************************
  函数名称:    STM32_out_func
  函数功能:    用户自定义的用于输出RGB位图数据的功能函数
  入口参数:    见函数头 
  出口参数:    1：令解码函数继续执行 
*********************************************************************************************/
UINT JPEG_Out_Func( 
										JDEC*   jd,        /* 储存待解码的对象信息的结构体 */ 
										void*   bitmap,    /* 指向等待输出的RGB位图数据的指针 */ 
										JRECT*  rect       /* 等待输出的矩形图像的参数 */ 
									) 
{ 
	if (rect->left == 0) 
	{
		printf("\r%lu%%", (rect->top << jd->scale) * 100UL / jd->height);
	}
	JPEG_Display(rect->left, rect->right, rect->top, rect->bottom, (WORD*)bitmap);
	
	return 1;    /* 返回1，使解码工作继续执行 */ 
} 


/*********************************************************************************************
  函数名称:    JPEG_Display
  函数功能:    在TFTLCD屏幕上显示图片 
  入口参数:    见函数头
*********************************************************************************************/
void JPEG_Display( 
										INT left,                            /* 图片左方起始点，即一行的起始点 */ 
										INT right,                           /* 图片右方的结束点，即一行的结束点 */ 
										INT top,                             /* 图片上方的起始点，即一列的起始点 */ 
										INT bottom,                          /* 图像下方的结束点，即一列的结束点 */ 
										const WORD* RGB_Data_Pointer     		 /* 待显示的图像数据，RGB格式 */ 
									) 
{ 
	uint16_t* address = 0;
	uint32_t count = 0;
	uint32_t i,j;
	int width = right - left + 1;
	int hight = bottom - top + 1;

	for (j = 0; j < hight; j++)
	{
		count = (LCD_ADDR + left*2 + (top + j)*TFTLCD_WIDTH*2);
		address = (uint16_t*)count;
		for (i = 0; i < width; i++)
		{
			*address++ = RGB_Data_Pointer[i+j*width];
		}	
	}
} 


/*********************************************************************************************
  函数名称:    STM32_JPEG_DISPLAY
  函数功能:    在主函数中调用的JPEG图片显示函数
  入口参数:    f_Jpeg：指向JPEG图片文件的指针，其值不定
							 filename：JPEG图片文件的名称
  出口参数:    0：函数执行成功
  其他：函数执行失败
*********************************************************************************************/
UINT JPEG_Decomp(FIL* f_Jpeg,const BYTE* filename) 
{ 
	FRESULT    Res_FatFs;/* FATFS系统函数返回值 */
	JDEC       jd;         /* 待解码的对象的信息记录表 */ 
	JRESULT    Res_TjpgDec; /* TjpgDec系统函数返回值 */

	Res_FatFs = f_open(f_Jpeg,(const TCHAR*)filename,FA_READ); 
	if(Res_FatFs!= FR_OK) /* 打开文件失败，返回 */
	{ 
		printf("f_open error -- %s\r\n",filename);
		f_close(f_Jpeg); 
		return Res_FatFs; 
	} 

	/* 执行解码的准备工作，调用TjpgDec模块的jd_prepare函数 */
	Res_TjpgDec = jd_prepare(&jd, JPEG_In_Func,Buff, sizeof(Buff), f_Jpeg); 

	if (Res_TjpgDec == JDR_OK)  
	{ 	
		/* 执行解码工作，调用TjpgDec模块的jd_decomp函数 */
		Res_TjpgDec = jd_decomp(&jd, JPEG_Out_Func, 0);
		if (Res_TjpgDec == JDR_OK) 
		{
			/* Decompression succeeded. You have the decompressed image in the frame buffer here. */
			printf("\rOK\n");
		} 
		else 
		{
			printf("Failed to decompress: rc=%d\n", Res_TjpgDec);
		}			
	} 
	else/* 解码的准备工作失败，关闭文件，返回 */
	{ 		
		printf("prepare error\r\n");
		f_close(f_Jpeg); 
		return Res_TjpgDec; /* 返回错误代码 */
	} 
	
	f_close(f_Jpeg); 
	/* 解码工作执行成功，返回0 */
	return 0; 
}  
