TjpgDec技术手册(中文版) - 图文
更新时间:2024-04-26 18:47:01 阅读量: 综合文库 文档下载
TjpgDec技术手册 -------R0.01b版
前言
相信大家对FATFS文件系统都不陌生了,2012年FATFS的作者推出了JPG/JPEG图片的解码函数库TJpgDec的R0.01b版,使用方法和FATFS文件系统的使用一样,仅仅调用2个简单的库函数就能完成对JPG/JPEG图片的解码,而且输出的数据格式为RGB888或RGB565。
本文档是根据ChaN的专用网页提供的英文版技术手册翻译而来,因个人水平有限以及时间仓促,错误之处在所难免。本文档原始版权归TJpgDec的作者所有,本人只是做了一下翻译的工作,把这篇文档献给所有嵌入式开发人员,希望能够帮到你们。 嵌入式奋勇前进 2013-10-20
一.前言:
TJpgDec是一款为小型嵌入式系统服务的高效且完善的JPEG图片解码模块。它占用内存极少,因此可以移植入像AVR,8051,PIC,Z80,Cortex-M0等等小型单片机中。 二.特点:
? ? ? ?
?
库函数是按照ANSI-C规范编写的,所以应用平台不受约束。
易于使用的主模式操作方式。 完全可重入的架构。 非常小的内存占用:
o RAM仅占用3KB,而不受图片大小的影响。 o ROM 占用3.5-8.5KB,主要用于存储代码和const常量。 输出格式:
o 输出图片比例: 1/1, 1/2, 1/4 ,1/8 可选 o 输出像素格式: RGB888/RGB565(可预设)
三.应用程序接口:
共有2个应用程序接口函数,用于分析和解码JPEG图片(译者注:移植TJpgDec时需要在主程序中调用这两个库函数)
? jd_prepare –为解码一个JPEG图片做准备 ? jd_decomp –解码JPEG图片
四.I/O接口函数:
TJpgDec需要用户自定义2个I/O接口函数,用于输入JPEG数据和输出解码后得到的像素数据。
Input funciotn - 从输入的数据流中读取JPEG的数据
? Output function – 把解码后得到的像素数据发送到输出设备
?
五.备注说明:
TJpgDec应用模块是一款可用于教育和研发的开源软件。你完全可以根据自己的项目需要或者商业产品的需要,自由更改本软件,而不用担负任何个人责任。
六.ChaN的个人网页:(即TjpgDec库函数下载地址)http://elm-chan.org/fsw/tjpg/00index.html 注:其他信息,如各版本信息,在此不作翻译了。
第一章 TjpgDec使用方法
1. 如何使用TjpgDec
首先创建并运行下面的例程中的程序,这是使用TjpgDec的基础,同时,这也是TjpgDec的典型用法,而且这种用法可以减少调试中的错误出现。TjpgDec模块分为两个部分,第一个部分对JPEG图片的信息进行分析,第二个部分用于解码JPEG图片。(译者注:原技术手册中的例程是一个在PC机上运行的例程,能够作为MCU移植的一个参考。在本文最后面,本人根据自己对TjpgDec的移植情况写出来了一个移植到STM32单片机的例程。)
使用步骤:
1. 初始化输入的数据流(例如:打开一个图片文件)。 2. 分配JPEG解压缩对象和工作区。
3. 调用函数jd_prepare() ,用于分析JPEG图片的信息,并为接下来的解码做好准备。 4. 根据JPEG图片信息分析得到的数据,对输出设备进行初始化 。 5. 调用函数jd_decomp() ,对JPEG图片进行解码。 2.系统架构
3.例程: /*------------------------------------------------*/ /* 可以在PC机上运行的TjpgDec 模块快速评估测试例程*/ /*------------------------------------------------*/ #include
1. jd_prepare
函数功能:此函数用于分析JPEG图片的信息,并为后续的解码过程创建一个解压对象。
函数头:JRESULT jd_prepare ( JDEC* jdec, /* 指向空白的待解压的对象的指针 */ UINT(*infunc)(JDEC*,BYTE*,UINT), /* 指向输入函数的指针*/ void* work, /* 指向本次解压工作区的指针 */ UINT sz_work, /* 解压工作区的大小 */ void* device /* 应用信息接口 */ ); 入口参数:
Jdec:用于后续进行解压的图片对象。
(*infunc):用于读取JPEG图片数据的输入函数,需要用户自定义。
Work:指向一次解压时使用的工作区的指针,它必须是一个字对齐(4字节对齐)的数据 sz_work:指定解压工作区的大小,根据JPEG内置参数表的不同,工作区最多需要3092字节的空间。 Device: 指向本次解码使用的用户定义的对象信息的指针. 它被存储到解压对象的成员中。在一次
解码工作中可以参考I/0函数来定义它。如果I/0接口在一个项目中是固定的,或者这个功能不需要,那么可以把它设置为NULL。
返回值:
JDR_OK:函数执行成功,并且解压对象有效。
JDR_INP:由于磁盘错误或者错误的数据结束而导致输入函数运行失败 JDR_MEM1:为解码工作配置的工作区大小不够
JDR_MEM2:输入缓冲区的容量过小, JD_SZBUF数据过小。 JDR_PAR:入口参数错误,指定的工作区指针为NULL. JDR_FMT1: 入口参数错误,指定的JPEG数据无法读取 JDR_FMT2:非JPEG图像
JDR_FMT3:非标准格式的彩色JPEG图像 备注:
jd_prepare函数是执行JPEG图片解码的第一步工作. 此函数用于分析JPEG图片的信息,并为后续的解码过程创建一个解码对象。此函数调用成功后,便可以调用jd_decomp函数执行解码的工作。此函数可以提取JPEG的尺寸参数,可用于配置用户自定义的对象信息,以及用于后续的解压工作。
2. jd_decomp
函数功能:解压JPEG图片,并输出RGB格式的数据 函数头:JRESULT jd_decomp (
JDEC* jdec, /* 指向一个已定义的解码对象 */ UINT(*outfunc)(JDEC*,void*,JRECT*), /* 指向输出函数的指针 */ BYTE scale /* 图像解压尺寸比例配置 */ ); 入口参数:
Jdec:指向一个已定义的解码对象
(*outfunc):指向一个用户定义的输出函数.用于以RGB格式输出图片的数据。
Scale:配置图像解压缩输出尺寸比例,输出图像的比例被配置为 1 / 2 ^ N (N = 0 to 3).这里需要配置的便是N的大小,如果输出比例功能被关闭 (JD_USE_SCALE == 0),那么这个数据必须是0; 返回值:
JDR_OK:函数执行成功 JDR_INTR:解压缩的工作被输出函数中断,即输出函数中出现错误或者输出函数命令本函数解码中止。 JDR_INP:由于磁盘错误或者错误的数据结束标识而导致输入函数运行失败 JDR_PAR:给定的图像输出比例参数错误
JDR_FMT1:数据结构错误,无法加载JPEG图片的数据 备注:
jd_decomp函数是解码一个JPEG图片的第二步工作.此函数解码JPEG图片,并通过用户提供的输出函数输出解码得到的RGB数据.此函数执行过以后,待解码对象自动失效。
图像输出比例参数可以被预设.它可以被预设为 1/2, 1/4 或者 1/8.例如: 当使用1/4的图像输出比例解码一个大小为1024x768的JPEG 图像时,它的输出尺寸将会是 256x192. 一般情况下,图像输出比例为1/2、1/4时,与不进行比例输出时相比会轻微的降低解码的速度。但是当图像输出比例等于 1/8 时,将会比无输出比例时快 2/3 时间,因为解码的部分功能将会被省略. 这个特性被用于产生缩略图。 3.Input Function
函数功能:用户自定义的用于输入数据的函数
函数头:UINT in_func ( JDEC* jdec, /* 指向待解码对象的指针 */ BYTE* buff, /* 指向用于存储读取的数据的缓冲区的指针 */ UINT ndata /* 待读取数据的数量 */ );
入口参数:
Jdec:指向待解码对象的指针 Buff:指向用于存储读取的数据的缓冲区的指针. 当此指针为NULL时,将从输入数据流中删除数据。 Ndata:指定将要从输入数据流中读取/删除的数据的字节数。 返回值:
返回读取/删除的字节数目;如果返回值为0,则jd_prepare和jd_decomp函数将返回JDR_INP。 备注:
此函数是TjpgDec模块的数据输入接口. 相应的解码流程会使用被传递给函数jd_prepare的第5个入口参数的数据进行解码工作,此参数是用户自定义的解码对象信息,被存储于 jdec->device 。(译者注:在MCU的应用中,此数据类型仅使用FIL类型用以指向一个待解码的JPEG文件) 4. Output Function
函数功能:用户自定义的输出函数,用于向输出设备输出解码后的图片数据 函数头:UINT out_func ( JDEC* jdec, /*指向一个已定义的解码对象*/ void* bitmap, /*指向已解码好但等待输出的RGB位图数据的指针*/ JRECT* rect /* bitmap所代表的待输出的像素块的大小 */ ); 入口参数:
Jdec:指向一个已定义的解码对象
Bitmap:指向已解码好但等待输出的RGB位图数据的指针
Rect: bitmap所代表的待输出的像素块的尺寸大小(译者注:看其定义可知,此结构体使用“上下左右”的值来表示一个矩形图片像素块的四个点)
返回值:一般情况下返回1.这个返回值将允许TjpgDec模块继续进行解码工作。当它的返回值为0时,jd_decomp函数将会终止解码工作,并返回JDR_INTR。这种利用out_func的返回值来终止解码的方式,是非常有用的。 备注: 此函数是TjpgDec模块的输出接口。相应的解码流程会使用被传递给函数jd_prepare的第5个入口参数的数据进行解码工作,此参数是用户自定义的解码对象信息,被存储于 jdec->device 。(译者注:在MCU的应用中,此数据类型仅使用FIL类型用以指向一个待解码的JPEG文件) 解压后得到的RGB位图数据可以在此函数中被发送到显示设备或者数据缓冲区,RGB位图数据的第一个数据是图片的左上角的矩形块的像素数据,第二个数据是右边一个矩形块的像素数据,最后一个数据是图片右下角的矩形块的像素数据。 每一个矩形像素块的大小是根据裁剪方式和图像输出比例的不同而从1x1到16x16不等的(译者注:像素块的大小是TjpgDec自由选择的,用户无法指定)。如果矩形块的大小超过了数据缓冲区的容量,那么在这个输出函数中需要进行一定的裁剪。
(译者注:在TjpgDec模块中,图像的像素数据的输出是以像素块为单位的,例如:当使用LCD显示图片时,可以看到图片是以一块一块的形式从左上角到右下角把整个图片显示出来的。所以,在MCU的使用中,当使用TFTLCD显示图片时,需要在这个输出函数中先根据rect提供的值在LCD上定义出一个图片显示的矩形窗口,然后再把bitmap数据输出到这个矩形窗口中,而TjpgDec会根据图片的信息自动改变rect的值,用户不用计算下一个像素块的显示位置。) RGB位图数据的格式需要使用配置选项中的JD_FORMAT进行定义。(在文件tjpgd.h中) 当定义为24位真彩色(RGB888)时,RGB位图数据使用3个字节表示一个像素点:RRRRRRRR, GGGGGGGG, BBBBBBBB, RRRRRRRR, GGGGGGGG, BBBBBBBB, ... 当定义为RGB565格式时,RGB位图数据使用一个半字(16位)的数据表示一个像素点:RRRRRGGGGGGBBBBB, RRRRRGGGGGGBBBBB, RRRRRGGGGGGBBBBB, ...
第三章 函数中使用的结构体
1. JDEC:此结构体存储有关解码使用的数据、指针和各种标志。(待解码对象信息记录表) struct JDEC {
UINT dctr; /* 输入缓冲区的容量 */
BYTE* dptr; /* 指向当前正在读取的数据的指针 */ BYTE* inbuf; /* 指向输入缓冲区的指针 */
BYTE dmsk; /* 当前正在读取的字节中的当前的一个位 */ BYTE scale; /* 图像输出比例 */
BYTE msx, msy; /* 单片机一个内存块的大小 (宽度和高度) */ BYTE qtid[3]; /* 每个组件的量化表的编号 */
SHORT dcv[3]; /* Previous DC element of each component */ WORD nrst; /* Restart inverval */
UINT width, height; /* 输入的图片的大小(像素) */
BYTE* huffbits[2][2];
/*霍夫曼比特分布表 [yc][dcac] */
WORD* huffcode[2][2]; /* 霍夫曼码字表 [yc][dcac] */ BYTE* huffdata[2][2]; /* 霍夫曼解码数据表 [yc][dcac] */ LONG* qttbl[4]; /* De-quaitizer tables [id] */ void* workbuf; /* 指向解码工作区的指针 */ BYTE* mcubuf; /* MCU工作区的指针 */ void* pool; /* 可用的内存指针 */
UINT sz_pool; /* 可用的内存的大小(以字节为单位) */ UINT (*infunc)(JDEC*, BYTE*, UINT); /* 指向数据输入函数的指针 */ UINT (*outfunc)(JDEC*, void*, JRECT*); /* 指向数据输出函数的指针 */ void* device; /* 指向解码工作中用到的应用信息的指针 */ };
2. JRESULT:应用函数的返回值定义 typedef enum { JDR_OK = 0, /* 0: 成功*/ JDR_INTR, /* 1: 被输出函数中断 */ JDR_INP, /* 2: 磁盘错误,或输入数据错误 */ JDR_MEM1, /* 3: 为解码工作配置的工作区大小不够*/ JDR_MEM2, /* 4: 输入缓冲区的容量过小,JD_SZBUF数据过小*/ JDR_PAR, /* 5: 参数错误 */ JDR_FMT1, /* 6: 图片数据错误 */ JDR_FMT2, /* 7: 不支持的图片类型 */ JDR_FMT3 /* 8: 不支持的JPEG 格式 */ } JRESULT;
3. JRECT:待输出的像素块的大小 typedef struct { WORD left, right, top, bottom; } JRECT;
此结构体中的各个数值分别表示一个矩形图像的像素块的上下左右的点在整个图片中的位置
第四章 TjpgDec在STM32单片机上的移植
第五章
//移植TJpgDec时需要补充和更改的相关配置 // 以下4句在tjpgd.h中修改 #define JD_SZBUF 2048 /* 输入缓冲区的大小 (必须是512的倍数) */ #define JD_FORMAT 1 /* 输出RGB格式:0:RGB888 (3 字节/像素), 1:RGB565 (1 半字/) */ #define JD_USE_SCALE 1 /* 使用去除图片冗余数据的功能 */ #define JD_TBLCLIP 1 /* 使用快速裁剪换算表(表的大小为1kB) */ //有关TFTLCD的尺寸的定义 #define TFTLCD_WIDTH 240 //2.4寸TFTLCD屏幕的宽度 #define TFTLCD_HEIGHT 320 //2.4寸TFTLCD屏幕的高度 static int Mask_Left = 0; //TFTLCD最左边的起始点 static int Mask_Right = TFTLCD_WIDTH - 1; //TFTLCD最右边的结束点 static int Mask_Top = 0; //TFTLCD最上方的起始点 static int Mask_Bottom= TFTLCD_HEIGHT - 1; //TFTLCD最下方的结束点 //用户自定义的用于输入文件数据的功能函数 UINT STM32_ in_func ( JDEC* jd, /*储存待解码的对象信息的结构体 */ BYTE* buff, /* 输入数据缓冲区 (NULL:删除数据) */ UINT nd /*需要从输入数据流读出/删除的数据量*/ ) { UINT rb; FIL *fil = (FIL*)jd->device; /* 待解码的文件的信息,使用FATFS中的FIL结构类型进行定义 */ if (buff) /*读取数据有效,开始读取数据 */ { f_read(fil, buff, nd, &rb); //调用FATFS的f_read函数,用于把jpeg文件的数据读取出来 return rb; /* 返回读取到的字节数目*/ } else { return (f_lseek(fil, f_tell(fil) + nd) == FR_OK) ? nd : 0;/* 重新定位数据点,相当于删除之前的n字节数据 */ } } //用户自定义的用于输出RGB位图数据的功能函数 UINT STM32_ out_func ( JDEC* jd, /*储存待解码的对象信息的结构体*/ void* bitmap, /* 指向等待输出的RGB位图数据 的指针*/ JRECT* rect /* 等待输出的矩形图像的参数 */ ) { jd = jd; /* 说明:输出函数中JDEC结构体没有用到 */ STM32_ Display (rect->left, rect->right, rect->top, rect->bottom, (uint16_t*)bitmap); return 1; /*返回1,使解码工作继续执行 */ } // 在TFTLCD屏幕上显示图片 void STM32_ Display ( int left, /*图片左方起始点,即一行的起始点 */ int right, /*图片右方的结束点,即一行的结束点*/ int top, /* 图片上方的起始点,即一列的起始点 */ int bottom, /*图像下方的结束点,即一列的结束点 */ const uint16_t * RGB_Data_Pointer /* 待显示的图像数据,RGB格式*/ ) { int height_jpeg, width_jpeg ,width_clip=0; u32 i,len,width_clip; if (left > right || top > bottom) { return; //起始点错误,不执行显示功能 } if (left > Mask_Right || right < Mask_Left || top > Mask_Bottm || bottom < Mask_Top) { return; // 图像超出屏幕的显示范围,则不执行显示功能 } //开始对图片的宽度和高度进行裁剪和修改 height_jpeg = bottom - top + 1; // 计算图像的高度 width_jpeg = right - left + 1; //计算图像的宽度 if (top < Mask_Top) // 裁减掉在图片顶部超出显示范围的部分数据 { RGB_Data_Pointer += width_jpeg * (Mask_Top- top); //计算出需要删除的数据量 height_jpeg-= Mask_Top- top; top = Mask_Top; } if (bottom > Mask_Bottm) // 裁减掉在图片底部超出显示范围的部分数据 { height_jpeg-= bottom - Mask_Bottm; bottom = Mask_Bottm; } if (left < Mask_Left) // 裁减掉在图片左边超出显示范围的部分数据 { RGB_Data_Pointer += Mask_Left - left; //水平方向的数据指针右移 width_jpeg -= Mask_Left - left; //水平宽度减小 width_clip+= Mask_Left - left;//记录裁减掉的宽度 left = Mask_Left; } if (right > Mask_Right) // 裁减掉在图片右边超出显示范围的部分数据 { width_jpeg -= right - Mask_Right; width_clip+=right - Mask_Right; right = Mask_Right; } //设置TFTLCD显示屏的显示参数 LCD_Set_Window(left,top,right,bottom);//在此处加入设置TFTLCD屏幕显示图片的窗口的功能函数,设置矩形显示区域 LCD_WR_REG(R32,left); LCD_WR_REG(R33,top); //在此处加入设置TFTLCD光标位置的功能函数,把像素点定位到起始点(左上角) //向TFTLCD显示屏控制器写入数据 LCD_WR_REG(R34); //在此处加入开始写入TFTLCD的GRAM功能的函数, //根据TFTLCD的控制器的特性,接下来可以连续地向上面设置好的矩形区域丢数据 while(height_jpeg --) //控制显示区域的高度 { x_width=width_jpeg; //在此处加入向TFTLCD写入数据的功能函数,在水平方向输出矩形区域一行的数据 wehile(x_width --) LCD_WR_DATA(*data_after_clip ++); //图片的水平方向的调整,去除裁减掉的像素数据 RGB_Data_Pointer+= width_clip; } } //在主函数中调用的JPEG图片显示函数 BYTE Buff[4096] __attribute__ ((aligned(4))); //定义全局数组变量,作为输入和输出的缓冲区,强制4字节对齐 uint32_t STM32_JPEG_DISPLAY(FIL* f_Jpeg,const char* filename) { FRESULT Res_FatFs;//FATFS系统函数返回值 JDEC jd; /* 待解码的对象的信息记录表 */ JRESULT Res_TjpgDec; // TjpgDec系统函数返回值 BYTE scale; //图像输出比例 //使用FATFS的f_open函数以读方式打开文件 Res_FatFs = f_open(f_Jpeg,filename,FA_READ); if(Res_FatFs!= FR_OK) //打开文件失败,返回 { Delay(10000); f_close(f_Jpeg); return Res_FatFs; } //执行解码的准备工作,调用TjpgDec模块的jd_prepare函数 Res_TjpgDec = jd_prepare(&jd, STM32_ in_func, Buff, sizeof(Buff), f_Jpeg); if (Res_TjpgDec == JDR_OK) { for (scale = 0; scale < 3; scale++) //确定输出图像的比例因子 { if ((jd.width >> scale) <= 240 && (jd.height >> scale) <= 320) { break; } } //执行解码工作,调用TjpgDec模块的jd_decomp Res_TjpgDec = jd_decomp(&jd, STM32_ out_func, scale); } else //解码的准备工作失败,关闭文件,返回 { Delay(10000); f_close(f_Jpeg); return Res_FatFs; //返回错误代码 } //解码工作执行成功,返回0 f_close(f_Jpeg); return 0; } 函数
//在主函数中调用的JPEG图片显示函数 BYTE Buff[4096] __attribute__ ((aligned(4))); //定义全局数组变量,作为输入和输出的缓冲区,强制4字节对齐 uint32_t STM32_JPEG_DISPLAY(FIL* f_Jpeg,const char* filename) { FRESULT Res_FatFs;//FATFS系统函数返回值 JDEC jd; /* 待解码的对象的信息记录表 */ JRESULT Res_TjpgDec; // TjpgDec系统函数返回值 BYTE scale; //图像输出比例 //使用FATFS的f_open函数以读方式打开文件 Res_FatFs = f_open(f_Jpeg,filename,FA_READ); if(Res_FatFs!= FR_OK) //打开文件失败,返回 { Delay(10000); f_close(f_Jpeg); return Res_FatFs; } //执行解码的准备工作,调用TjpgDec模块的jd_prepare函数 Res_TjpgDec = jd_prepare(&jd, STM32_ in_func, Buff, sizeof(Buff), f_Jpeg); if (Res_TjpgDec == JDR_OK) { for (scale = 0; scale < 3; scale++) //确定输出图像的比例因子 { if ((jd.width >> scale) <= 240 && (jd.height >> scale) <= 320) { break; } } //执行解码工作,调用TjpgDec模块的jd_decomp Res_TjpgDec = jd_decomp(&jd, STM32_ out_func, scale); } else //解码的准备工作失败,关闭文件,返回 { Delay(10000); f_close(f_Jpeg); return Res_FatFs; //返回错误代码 } //解码工作执行成功,返回0 f_close(f_Jpeg); return 0; } 函数
正在阅读:
财政部PPP项目合同指南(试行)12-08
大学生职业生涯规划范文-化工09-07
mysql命令大全10-01
期权考试样题及答案04-26
415399TANGYEHONG电工测量仪表导学案及练习07-28
2021年中国渗滤液处理行业市场展望06-05
1-第2章 机械加工精度05-28
geostudio操作步骤(详细)06-17
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 中文版
- TjpgDec
- 手册
- 图文
- 技术
- 《计算机组成原理》运算器实验报告
- 怀化市城市总体规划
- 第五章 肺结核患者治疗管理
- 黄鹤楼送别课堂实录
- 地理辨证直解
- CO2气体保护焊培训教1
- 导数和微分产生的背景
- 关于进一步完善查处取缔无证无照经营行为工作机制的通知
- 民主生活会意见和建议
- 通信网原理实验报告Ethernet and ARP
- 中考英语语法练习题练习及答案
- 建设工程招标投标评委复习题多选题
- 河南中粮大户
- TS16949 - 2009考试试题(答案) - 图文
- 抽水试验基本方法
- 重新构建认知体系,维护心理健康
- 初中(中考)数学常见解题模型及思路(压轴题题眼全覆盖)
- 2018年浙江学考选考物理二轮专题:专题训练21 电学实验 - 图文
- 2015-2016拓展模块语文第一学期试卷
- 对中学语文作业设计依据和原则的几点思考-2019年作文