打印
[STM32F0]

原图和解码图对比

[复制链接]
2630|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zongyu123|  楼主 | 2014-12-17 19:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zongyu123 于 2014-12-17 19:25 编辑

此图为原图

此图为解码后显示到LCD的图。

硬件:STM32F072的CPU。解码用的是ChaN的解码,原子迷你版的代码。结果出来就是这样子。
差距为什么这么大呢?求大神指点!谢谢。
代码如下:
/********************COPYRIGHT (C)  2013 Creator Lab of embedded systems *******************************
* 文件名  :main.c
* 描述    :结合FATFS文件系统与TjpgDec图片解码系统,实现最基本的图片显示功能
* 实验平台:MINI开发板,MINI自带的2.4寸TFTLCD屏幕
* 库版本  :ST3.5.0
* 调试方法:在SD卡中存储短文件名的JPG图片,图片直接放入SD卡中,不需要建立文件夹。
                         程序烧进板子以后,插上SD卡,然后复位一下板子,就可以在2.4寸的TFTLCD上
                         看到存储进SD卡中的图片了。
* 备注说明:图片应使用短文件名(8.3格式),且图片类型必须是JPG/JPEG类型,且图片须
                         为240像素宽度的图片,图片的高度如果过高,请不要超过320像素太多,不然图
                         片显示不完全。
********************************************************************************************************/
#include "takepic.h"
#include "stm32f0xx.h"
#include "jpeg_lcd.h"

//全局变量定义
uint8_t res,Counts_A,SiJi;
uint8_t fname_temp[32];
//有关文件的全局变量
FIL     fsrc,fdst; //文件结构体
//FATFS   fs;               //文件系统工作区注册信息结构体
//UINT    br,bw;           //文件读写字节数
//DIR     dir;       //目录结构体
FILINFO fileInfo;  //文件信息结构体,包含文件名称及修改日期等信息,在读取目录的时候可以得到这些信息
/*--------------------------------------------------------------------
* 函数名:main
* 描述  :主函数
* 输入  :无
* 输出  :无
---------------------------------------------------------------------*/
int main(void)
{                 
        system_init();
        while(1)
        {
                res= f_opendir(&dir,"0:");//读取文件夹信息,即打开一级目录
                if(res==FR_OK) //打开目录成功,则开始循环显示图片
                {
                        while(1)
                        {
                                res =f_readdir(&dir,&fileInfo);//读取目录中其中一个目录项的信息,即从目录中读取一个文件的信息
                                if(res!=0||fileInfo.fname[0]==0)break;//目录读取完,或者目录读取出现错误,则跳出循环,重新读取目录
                                if(fileInfo.fname[0]=='.')continue  ;//文件名中的第一个字符是个点,则忽略这个文件,读取下一个文件
                                strcpy(fname_temp,"0:/");
                                strcat(fname_temp,fileInfo.fname);//处理二级目录的名称,即图片文件的路径:“0:/fileInfo.fname”,也是文件名
                                res=STM32_JPEG_DISPLAY(&fsrc,fname_temp);
//                                delay_ms(55555);
//                                LCD_Set_Window(0,0,319,239);
//                                LCD_Fill(0,0,319,239,WHITE);
                        }
                }
        }
}


/********************  COPYRIGHT (C) 2013 Creator Lab of embedded systems *******************************/


/********************COPYRIGHT (C)  2013 Creator Lab of embedded systems *******************************
* 文件名  :main.c
* 描述    :
* 实验平台:MINI开发板
* 库版本  :ST3.5.0
* 调试方法:
********************************************************************************************************/

#include "jpeg_lcd.h"
UINT Height_Of_Jpeg=0;//记录图片高度的全局变量
BYTE Buff[4096] __attribute__ ((aligned(4)));    //定义全局数组变量,作为输入的缓冲区,强制4字节对齐
/*********************************************************************************************
  函数名称:    STM32_in_func
  函数功能:    用户自定义的用于输入文件数据的功能函数
  入口参数:    见函数头
  出口参数:    读取或者删除的数据量
  全局变量:           无
  备注说明:    本函数在解码准备工作中用于读取文件头信息
*********************************************************************************************/
UINT STM32_in_func (
                            JDEC* jd,        /*储存待解码的对象信息的结构体 */
                            BYTE* buff,        /* 输入数据缓冲区 (NULL:删除数据) */
                            UINT nd            /*需要从输入数据流读出/删除的数据量*/
                      )
{
    UINT  rb;
    FIL * 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 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,使解码工作继续执行 */
}

/*********************************************************************************************
  函数名称:    STM32_Display
  函数功能:    在TFTLCD屏幕上显示图片
  入口参数:    见函数头
  出口参数:    无
  全局变量:           无
  备注说明:    无
*********************************************************************************************/
void STM32_Display(
                            int left,                            /*图片左方起始点,即一行的起始点 */
                            int right,                           /*图片右方的结束点,即一行的结束点*/
                            int top,                             /* 图片上方的起始点,即一列的起始点 */
                            int bottom,                          /*图像下方的结束点,即一列的结束点 */
                            const uint16_t * RGB_Data_Pointer    /* 待显示的图像数据,RGB格式*/
                        )
{
    int       height_jpeg=0,width_jpeg=0,x_width=0,lines_change=0;   
    uint32_t  width_clip=0;  //变量一定要初始化,不然会遇到意想不到的麻烦
     if (left > right || top > bottom)  
                    {   
                        return;   //起始点错误,不执行显示功能         
                    }
    if (left > Mask_Right || right < Mask_Left  || top > Mask_Bottom || 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_Bottom)     // 裁减掉在图片底部超出显示范围的部分数据  
                    {
                                height_jpeg-= bottom - Mask_Bottom;
                        bottom = Mask_Bottom;
                    }
    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;
                    }
        if(Height_Of_Jpeg<TFTLCD_HEIGHT)//当图片的高度小于LCD显示屏的高度时,使图片能够居中显示
        lines_change=(TFTLCD_HEIGHT-Height_Of_Jpeg)/2;//调整图片高度                        
        
        //设置TFTLCD显示屏的显示参数
        LCD_SetWindow(left,top+lines_change,right,bottom+lines_change);//在此处加入设置TFTLCD屏幕显示图片的窗口的功能函数,设置矩形显示区域
        LCD_WR_REG_DATA(R32,left);
        LCD_WR_REG_DATA(R33,top+lines_change); //在此处加入设置TFTLCD光标位置的功能函数,把像素点定位到起始点(左上角)
        
        //向TFTLCD显示屏控制器写入数据
  LCD_WR_REG(R34); //在此处加入开始写入TFTLCD的GRAM功能的函数,
                        //根据TFTLCD的控制器的特性,接下来可以连续地向上面设置好的矩形区域丢数据
        while(height_jpeg--)  //控制显示区域的高度
                {   
                        x_width=width_jpeg;
                        //在此处加入向TFTLCD写入数据的功能函数,在水平方向输出矩形区域一行的数据
                        while(x_width--)   LCD_WR_DATA(*RGB_Data_Pointer++);
                        //图片的水平方向的调整,去除裁减掉的像素数据
                        RGB_Data_Pointer+= width_clip;                        
                }
}
/*********************************************************************************************
  函数名称:    STM32_JPEG_DISPLAY
  函数功能:    在主函数中调用的JPEG图片显示函数
  入口参数:    f_Jpeg:指向JPEG图片文件的指针,其值不定
                           filename:JPEG图片文件的名称
  出口参数:    0:函数执行成功
                           其他:函数执行失败
  全局变量:           无
  备注说明:    无
*********************************************************************************************/
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_ms(1000);
                        f_close(f_Jpeg);
                        return Res_FatFs;
    }
                //执行解码的准备工作,调用TjpgDec模块的jd_prepare函数
    Res_TjpgDec = jd_prepare(&jd,STM32_in_func,Buff,sizeof(Buff),f_Jpeg);
                Height_Of_Jpeg=jd.height;//保存图片的高度数据
    if (Res_TjpgDec == JDR_OK)  
    {
                        for (scale = 0; scale < 3; scale++) //确定输出图像的比例因子
                        {
                                //if ((jd.width >> scale) <= 240 && (jd.height >> scale) <= 320)  break;
                                if ((jd.width >> scale) <= lcddev.width && (jd.height >> scale) <= lcddev.height)  break;
                }
                if(scale)scale--;  //处理标准240宽度的图片时,对于高度过高的情况进行降低一级比例的处理
      //执行解码工作,调用TjpgDec模块的jd_decomp函数
       Res_TjpgDec = jd_decomp(&jd, STM32_out_func, scale);
    }
    else    //解码的准备工作失败,关闭文件,返回
    {
                        delay_ms(1000);
                        f_close(f_Jpeg);
                        return Res_TjpgDec; //返回错误代码
    }
    //解码工作执行成功,返回0
    f_close(f_Jpeg);
    return 0;
}

/********************  COPYRIGHT (C) 2013 Creator Lab of embedded systems *******************************/




/********************COPYRIGHT (C)  2013 Creator Lab of embedded systems *******************************
* 文件名  :main.c
* 调试方法:
********************************************************************************************************/
#include <stdio.h>
#include "stm32f0xx.h"
#include "uart2.h"
#include "delay.h"
#include "ff.h"
#include "tjpgd.h"
#include "lcd.h"

typedef struct {
    FIL *fp;      /*指向输入文件的指针(JPEG文件)*/  //
    BYTE *fbuf;    /*指向输出缓冲区的指针*///
    UINT wfbuf;    /*输出缓冲区的宽度[pix] *///
} IODEV;

//有关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,UINT nd) ;
UINT      STM32_out_func (JDEC* jd,void* bitmap,JRECT* rect);
void      STM32_Display( int left,int right,int top,int bottom,const uint16_t * RGB_Data_Pointer);
uint32_t  STM32_JPEG_DISPLAY(FIL* f_Jpeg,const char* filename);

/********************  COPYRIGHT (C) 2013 Creator Lab of embedded systems *******************************/










沙发
zongyu123|  楼主 | 2014-12-17 19:46 | 只看该作者
大家都只是看看?没人搞过这个图片解码的吗???

使用特权

评论回复
板凳
airwill| | 2014-12-17 21:23 | 只看该作者
我的解码效果, 也发现有点不对劲, 不过只是颜色不柔和了
估计算法错误, 传两份资料, 给你参考一下
JPEG图像数据格式简明分析.pdf (190.04 KB)
JPEG文件编解码详解.zip (36.59 KB)

使用特权

评论回复
地板
zongyu123|  楼主 | 2014-12-18 08:37 | 只看该作者
airwill 发表于 2014-12-17 21:23
我的解码效果, 也发现有点不对劲, 不过只是颜色不柔和了
估计算法错误, 传两份资料, 给你参考一下

好的。谢谢你!

使用特权

评论回复
5
zongyu123|  楼主 | 2014-12-18 08:43 | 只看该作者
airwill 发表于 2014-12-17 21:23
我的解码效果, 也发现有点不对劲, 不过只是颜色不柔和了
估计算法错误, 传两份资料, 给你参考一下

这些资料我都有了。还是说声谢谢。

使用特权

评论回复
6
zongyu123|  楼主 | 2014-12-18 15:11 | 只看该作者
airwill 发表于 2014-12-17 21:23
我的解码效果, 也发现有点不对劲, 不过只是颜色不柔和了
估计算法错误, 传两份资料, 给你参考一下

解码搞定了,就是速度不够快。唉~~1~2秒才能显示出来一张5K左右打小的图片。

使用特权

评论回复
7
airwill| | 2014-12-18 17:44 | 只看该作者
嗯, 看来我的解码速度比你的快一些, 我把里面一些费事的计算转移部分改造了一下, 在 STM32F107 的板子上, 每秒可以刷几帧 320×240 的图片.

使用特权

评论回复
8
zongyu123|  楼主 | 2014-12-18 17:47 | 只看该作者
airwill 发表于 2014-12-18 17:44
嗯, 看来我的解码速度比你的快一些, 我把里面一些费事的计算转移部分改造了一下, 在 STM32F107 的板子上,  ...

你的代码运行速度确实比较快,但是我这直接拿别人的来用,也不知道怎么修改。所以没办法了,只能研究研究DMA了。内存也就只有16K,加上文件系统,读取SD卡,基本上就耗完了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

34

帖子

0

粉丝