微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > ARM技术讨论 > ARM9 JPEG软解码

ARM9 JPEG软解码

时间:10-02 整理:3721RD 点击:
?我在U盘里面放了个分辨率为32*16的JPEG,红绿蓝各占一点,然后利用网上的函数进行解码(自己对解码具体算法不是很懂),解码出来把RGB数据放到缓冲数组里面,发现解码值不对~~不知道哪里的问题,程序昨天又核对了一遍,没发现什么错误。求大神指教!程序如下:#ifndef __ALLCLRJPEGDEAL_H_#define __ALLCLRJPEGDEAL_H_#include "ffconf.h"#include "ff.h"#include "diskio.h"#include "stdint.h"#include "gen.h"typedef char CHAR ;typedef short SHORT ;typedef long LONG ;typedef unsigned long DWORD ;typedef int BOOL ;typedef unsigned char BYTE ;typedef unsigned short WORD ;#define JPEG_START_ADDR 41943040//函数返回值定义#define FUNC_OK                         0#define FUNC_MEMORY_ERROR         1#define FUNC_FILE_ERROR         2#define FUNC_FORMAT_ERROR         3#define Decode_OK                         4//#define FALSE 0 //#define TRUE 1 //图象数据压缩的类型#define BI_RGB       0L#define BI_RLE8      1L#define BI_RLE4      2L#define BI_BITFIELDS 3L #define M_SOF0  0xc0#define M_DHT   0xc4#define M_EOI   0xd9#define M_SOS   0xda#define M_DQT   0xdb#define M_DRI   0xdd#define M_APP0  0xe0  #define MAKEWORD(a, b)      ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))#define MAKELONG(a, b)      ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16))#define LOWORD(l)           ((WORD)(l))#define HIWORD(l)           ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))#define LOBYTE(w)           ((BYTE)(w))#define HIBYTE(w)           ((BYTE)(((WORD)(w) >> 8) & 0xFF))#define WIDTHBYTES(i) ((i+31)/32*4)#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */#define W7 565  /* 2048*sqrt(2)*cos(7*pi/16) */#define ByteAlignedNum 24static int Zig_Zag[8][8]={              {0,1,5,6,14,15,27,28},                          {2,4,7,13,16,26,29,42},                          {3,8,12,17,25,30,41,43},                          {9,11,18,24,31,40,44,53},                          {10,19,23,32,39,45,52,54},                          {20,22,33,38,46,51,55,60},                          {21,34,37,47,50,56,59,61},                          {35,36,48,49,57,58,62,63}                         };         BOOL JPEGDeal(void);void InitTable(void);int InitTag(void);void showerror(int funcret);unsigned int P_Cal(unsigned char *pc);int Decode(void);void Initialize_Fast_IDCT(void);int DecodeMCUBlock(void);void IQtIZzMCUComponent(short flag);void GetYUV(short flag);void StoreBuffer(void);int HufBlock(u8 dchufindex,u8 achufindex);int DecodeElement(void);u8 ReadByte(void);void IQtIZzBlock(short  *s,int *d,short flag);void Fast_IDCT(int * block);void idctrow(int * blk);void idctcol(int * blk);#endif#include "AllClrJPEGDeal.h"const TCHAR *filename = "Test.jpg";u8 jpg_buffer[1024];                //数据缓存区DWORD ImgWidth=0,ImgHeight=0 ;DWORD LineBytes ;DWORD sizei,sizej ;short rrun,vvalue ;short BitPos,CurByte ;BOOL  IntervalFlag ;short interval=0 ;short restart ;short qt_table[3][64];short comp_num ;BYTE HufTabIndex ;BYTE comp_index[3];short code_pos_table[4][16],code_len_table[4][16];unsigned short huf_max_value[4][16],huf_min_value[4][16];unsigned short code_value_table[4][256];short MCUBuffer[10*64];//short QtZzMCUBuffer[10*64];int QtZzMCUBuffer[10*64];short BlockBuffer[64];//short Y[4*64],U[4*64],V[4*64];int Y[4*64],U[4*64],V[4*64];short ycoef,ucoef,vcoef ;unsigned char   *lp;                //取代lpJpegBufshort        SampRate_Y_H,SampRate_Y_V;short        SampRate_U_H,SampRate_U_V;short        SampRate_V_H,SampRate_V_V;short        *YQtTable,*UQtTable,*VQtTable;BYTE        YDcIndex,YAcIndex,UVDcIndex,UVAcIndex;short H_YtoU,V_YtoU,H_YtoV,V_YtoV ;short Y_in_MCU,U_in_MCU,V_in_MCU ;static long iclip[1024];static long*iclp ;char   *hImgData = NULL ;uint32_t size;unsigned long RGBSize;uint8_t rgbdatatemp[4096];uint32_t rgbnum = 0;BYTE And[9]={    0,1,3,7,0xf,0x1f,0x3f,0x7f,0xff };FIL pic_to_show;                        //要显示的图片文件缓存UINT byte_left;                                //文件剩余可读取字节DWORD pic_offset;                        //文件偏移变量extern FATFS Fatfs;                        /* File system object */extern void die (                    /* Stop with dying message */        FRESULT rc                    /* FatFs return value */);BOOL JPEGDeal(){                FRESULT rc;                                        /* Result code */        //DIR dir;                                        /* Directory object */        FILINFO fileinfo;                        /* File information object */                DWORD ImgSize;        u8 houxu[3];                           //文件名缓存        u8 i;        int funcret;                          //返回值        pic_offset = 0;                        //初始化偏移变量        byte_left = 0;                        //初始化文件剩余字节                /*注册磁盘卷 0表示 U盘*/        f_mount(0, &Fatfs);                /* Register volume work area (never fails) */        f_stat(filename, &fileinfo);     //获取文件名        for(i=0; i<13; i++)        {                if(fileinfo.fname == '.') break;        }        houxu[0] = fileinfo.fname[i+1];        houxu[1] = fileinfo.fname[i+2];        houxu[2] = fileinfo.fname[i+3];        if(((houxu[0]=='J')&&(houxu[1]=='P')&&(houxu[2]=='G'))||((houxu[0]=='J')&&(houxu[1]=='P')&&(houxu[2]=='E')))//是JPG或者JPEG文件        {                if(f_open(&pic_to_show, filename, FA_READ) == FR_OK)                                   //打开图片                {                        f_lseek(&pic_to_show,pic_offset);                                                                   //移动读取指针到相应位置                        if(f_read(&pic_to_show,jpg_buffer,1024,&byte_left) == FR_OK)        //读取1024个字节                        {                                pic_offset += 1024;                                                                                        //表头读取完毕,移动到数据区                                InitTable();                                                                                                //初始化各个数据表                                if((funcret=InitTag())!=FUNC_OK)                                                        //初始化表头不成功                                {                                        showerror(funcret);                                        return FALSE;                                                                }                                                                LineBytes = (unsigned long)WIDTHBYTES((LONG)(ImgWidth) * (LONG)(ByteAlignedNum));                                ImgSize = (DWORD)LineBytes * (LONG)(ImgHeight);                                                                if((hImgData=(char*)malloc(ImgSize))==NULL)                                   {                                        showerror(FUNC_MEMORY_ERROR);                                 return FALSE ;                                   }                                   printf("hImgDataaddress = %p\n\r",hImgData);                                                                                                   if((SampRate_Y_H==0)||(SampRate_Y_V==0))                                {                                        free(hImgData);                                hImgData=NULL ;                                        showerror(FUNC_FORMAT_ERROR);                                        return FALSE;                                //采样率错误                                }                                                                        funcret = Decode();                                //Jpeg解码                                                        printf("%d\r\n", RGBSize);                                printf("%d\r\n", rgbnum);                        }                        f_close(&pic_to_show);                                //解码结束,关闭文件                                                free(hImgData);                                                RGBSize = 0;                        rgbnum = 0;                }        }        else         {                f_close(&pic_to_show);                        return FALSE;        }                        if(funcret == FUNC_OK)        {                        showerror(Decode_OK);                return TRUE;   //解码成功                                }        else         {                showerror(FUNC_FORMAT_ERROR);                return FALSE;  //解码失败        }        //if (rc) die(rc);}void InitTable(void){        short i,j ;    sizei=sizej=0 ;    ImgWidth=ImgHeight=0 ;    rrun=vvalue=0 ;    BitPos=0 ;    CurByte=0 ;    IntervalFlag=FALSE ;    restart=0 ;    for(i=0;i<3;i++)    for(j=0;j<64;j++)    qt_table[j]=0 ;    comp_num=0 ;    HufTabIndex=0 ;    for(i=0;i<3;i++)    comp_index=0 ;    for(i=0;i<4;i++)    for(j=0;j<16;j++)    {        code_len_table[j]=0 ;        code_pos_table[j]=0 ;        huf_max_value[j]=0 ;        huf_min_value[j]=0 ;    }    for(i=0;i<4;i++)    for(j=0;j<256;j++)    code_value_table[j]=0 ;        for(i=0;i<10*64;i++) { MCUBuffer=0 ; QtZzMCUBuffer=0 ; }     for(i=0;i<64;i++) { Y=0 ; U=0 ; V=0 ; BlockBuffer=0 ; }     ycoef=ucoef=vcoef=0 ; }int InitTag(void){        BOOL finish = FALSE ;    BYTE id ;                short llength ;    short i,j,k ;    short huftab1,huftab2 ;    short huftabindex ;    BYTE hf_table_index ;    BYTE qt_table_index ;    BYTE comnum ;            //最长为256个字节        unsigned char  *lptemp;                         short  colorount;        lp=jpg_buffer+2;                //跳过两个字节SOI(0xFF,0xD8 Start of Image)         lp-=P_Cal(lp);                  while (!finish)        {                                         id=*(lp+1);//取出低位字节(高位在前,低位在后)                lp+=2;     //跳过取出的字节                lp-=P_Cal(lp);                           switch (id)                {                        case M_APP0: //JFIF APP0 segment marker (0xE0)                                     //标志应用数据段的开始                                             llength=MAKEWORD(*(lp+1),*lp);//得到应用数据段长度                                        lp+=llength;                                  lp-=P_Cal(lp);                                  break;                        case M_DQT: //定义量化表标记(0xFF,0xDB)                                 llength=MAKEWORD(*(lp+1),*lp);//(量化表长度)两个字节                                 qt_table_index=(*(lp+2))&0x0f;//量化表信息bit 0..3: QT 号(0..3, 否则错误)                                                                                           //bit 4..7: QT 精度, 0 = 8 bit, 否则 16 bit                                lptemp=lp+3;                                    //n 字节的 QT, n = 64*(精度+1)                                 //d_buffer里面至少有有512个字节的余度,这里最大用到128个字节                                if(llength<80)                                  //精度为 8 bit                                 {                                        for(i=0;i<64;i++)                                        qt_table[qt_table_index]=(short)*(lptemp++);                                  }                                else                                                  //精度为 16 bit                                 {                                        for(i=0;i<64;i++)                                        qt_table[qt_table_index]=(short)*(lptemp++);                           qt_table_index=(*(lptemp++))&0x0f;                                          for(i=0;i<64;i++)                                          qt_table[qt_table_index]=(short)*(lptemp++);                                              }                                                                        lp+=llength;  //跳过量化表                                 lp-=P_Cal(lp);                                          break;                        case M_SOF0:                                                //帧开始 (baseline JPEG 0xFF,0xC0)                                 llength=MAKEWORD(*(lp+1),*lp);                //长度 (高字节, 低字节), 8+components*3                                  ImgHeight=MAKEWORD(*(lp+4),*(lp+3));//图片高度 (高字节, 低字节), 如果不支持 DNL 就必须 >0                                  ImgWidth=MAKEWORD(*(lp+6),*(lp+5));        //图片宽度 (高字节, 低字节), 如果不支持 DNL 就必须 >0                     comp_num=*(lp+7);                                        //components 数量(1 u8), 灰度图是 1, YCbCr/YIQ 彩色图是 3, CMYK 彩色图是 4                                                                                                                                                                                                                     if((comp_num!=1)&&(comp_num!=3))return FUNC_FORMAT_ERROR;// 格式错误                                         if(comp_num==3)                                                //YCbCr/YIQ 彩色图                                {                                        comp_index[0]=*(lp+8);                    //component id (1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q)                                           SampRate_Y_H=(*(lp+9))>>4;                //水平采样系数                                           SampRate_Y_V=(*(lp+9))&0x0f;        //垂直采样系数                                           YQtTable=(short *)qt_table[*(lp+10)];//通过量化表号取得量化表地址                                                 comp_index[1]=*(lp+11);                                 //component id                                         SampRate_U_H=(*(lp+12))>>4;                         //水平采样系数                                          SampRate_U_V=(*(lp+12))&0x0f;                 //垂直采样系数                                           UQtTable=(short *)qt_table[*(lp+13)];//通过量化表号取得量化表地址                                                  comp_index[2]=*(lp+14);                                 //component id                                           SampRate_V_H=(*(lp+15))>>4;                         //水平采样系数                                          SampRate_V_V=(*(lp+15))&0x0f;                 //垂直采样系数                                         VQtTable=(short *)qt_table[*(lp+16)];//通过量化表号取得量化表地址                                  }                                else                                                                     //component id                                 {                                          comp_index[0]=*(lp+8);                                        SampRate_Y_H=(*(lp+9))>>4;                                          SampRate_Y_V=(*(lp+9))&0x0f;                                          YQtTable=(short *)qt_table[*(lp+10)];//灰度图的量化表都一样                                                comp_index[1]=*(lp+8);                                          SampRate_U_H=1;                                          SampRate_U_V=1;                                          UQtTable=(short *)qt_table[*(lp+10)];                                                comp_index[2]=*(lp+8);                                        SampRate_V_H=1;                                          SampRate_V_V=1;                                          VQtTable=(short *)qt_table[*(lp+10)];                                }                                   lp+=llength;                                  lp-=P_Cal(lp);                                                                      break;                        case M_DHT:         //定义哈夫曼表(0xFF,0xC4)                                             llength=MAKEWORD(*(lp+1),*lp);//长度 (高字节, 低字节)                                if (llength<0xd0)                          // Huffman Table信息 (1 u8)                                 {                                        huftab1=(short)(*(lp+2))>>4;     //huftab1=0,1(HT 类型,0 = DC 1 = AC)                                         huftab2=(short)(*(lp+2))&0x0f;   //huftab2=0,1(HT 号  ,0 = Y  1 = UV)                                        huftabindex=huftab1*2+huftab2;         //0 = YDC 1 = UVDC 2 = YAC 3 = UVAC                                          lptemp=lp+3;//!                                           //在这里可能出现余度不够,多于512字节,则会导致出错!                                        for (i=0; i<16; i++)             //16 bytes: 长度是 1..16 代码的符号数                                                code_len_table[huftabindex]=(short)(*(lptemp++));//码长为i的码字个数                                           j=0;                                        for (i=0; i<16; i++)                         //得出HT的所有码字的对应值                                         {                                                if(code_len_table[huftabindex]!=0)                                                {                                                        k=0;                                                        while(k<code_len_table[huftabindex])                                                        {                                                                code_value_table[huftabindex][k+j]=(short)(*(lptemp++));//最可能的出错地方                                                                k++;                                                        }                                                        j+=k;                                                        }                                        }                                        i=0;                                        while (code_len_table[huftabindex]==0)                                        i++;                                                   for (j=0;j<i;j++)                                        {                                                huf_min_value[huftabindex][j]=0;                                                huf_max_value[huftabindex][j]=0;                                        }                                        huf_min_value[huftabindex]=0;                                        huf_max_value[huftabindex]=code_len_table[huftabindex]-1;                                        for (j=i+1;j<16;j++)                                        {                                                huf_min_value[huftabindex][j]=(huf_max_value[huftabindex][j-1]+1)<<1;                                                huf_max_value[huftabindex][j]=huf_min_value[huftabindex][j]+code_len_table[huftabindex][j]-1;                                        }                                        code_pos_table[huftabindex][0]=0;                                        for (j=1;j<16;j++)                                                  code_pos_table[huftabindex][j]=code_len_table[huftabindex][j-1]+code_pos_table[huftabindex][j-1];                                        lp+=llength;                                                          lp-=P_Cal(lp);                                  }//if                                   else                                {                                                             hf_table_index=*(lp+2);                                        lp+=2;                                          lp-=P_Cal(lp);                                                 while (hf_table_index!=0xff)                                        {                                                huftab1=(short)hf_table_index>>4;     //huftab1=0,1                                                 huftab2=(short)hf_table_index&0x0f;   //huftab2=0,1                                                huftabindex=huftab1*2+huftab2;                                                lptemp=lp+1;                                                colorount=0;                                                for (i=0; i<16; i++)                                                {                                                        code_len_table[huftabindex]=(short)(*(lptemp++));                                                        colorount+=code_len_table[huftabindex];                                                }                                                colorount+=17;                                                        j=0;                                                for (i=0; i<16; i++)                                                {                                                        if(code_len_table[huftabindex]!=0)                                                         {                                                                k=0;                                                                while(k<code_len_table[huftabindex])                                                                {                                                                        code_value_table[huftabindex][k+j]=(short)(*(lptemp++));//最可能出错的地方,余度不够                                                                        k++;                                                                }                                                                j+=k;                                                        }                                                }                                                i=0;                                                while (code_len_table[huftabindex]==0)                                                i++;                                                for (j=0;j<i;j++)                                                {                                                        huf_min_value[huftabindex][j]=0;                                                        huf_max_value[huftabindex][j]=0;                                                }                                                huf_min_value[huftabindex]=0;                                                huf_max_value[huftabindex]=code_len_table[huftabindex]-1;                                                for (j=i+1;j<16;j++)                                                {                                                        huf_min_value[huftabindex][j]=(huf_max_value[huftabindex][j-1]+1)<<1;                                                        huf_max_value[huftabindex][j]=huf_min_value[huftabindex][j]+code_len_table[huftabindex][j]-1;                                                }                                                code_pos_table[huftabindex][0]=0;                                                for (j=1;j<16;j++)                                                        code_pos_table[huftabindex][j]=code_len_table[huftabindex][j-1]+code_pos_table[huftabindex][j-1];                                                lp+=colorount;                                                  lp-=P_Cal(lp);                                                         hf_table_index=*lp;                                        }  //while                                }  //else                                break;                        case M_DRI://定义差分编码累计复位的间隔                                llength=MAKEWORD(*(lp+1),*lp);                                restart=MAKEWORD(*(lp+3),*(lp+2));                                  lp+=llength;                                  lp-=P_Cal(lp);                                 break;                        case M_SOS:         //扫描开始 12字节                                llength=MAKEWORD(*(lp+1),*lp);                                comnum=*(lp+2);                                if(comnum!=comp_num)                                        return FUNC_FORMAT_ERROR; //格式错误                                   lptemp=lp+3;//这里也可能出现错误                                //这里也可能出错,但是几率比较小了                                for (i=0;i<comp_num;i++)//每组件的信息                                 {                                        if(*lptemp==comp_index[0])                                        {                                                YDcIndex=(*(lptemp+1))>>4;   //Y 使用的 Huffman 表                                                 YAcIndex=((*(lptemp+1))&0x0f)+2;                                        }                                        else                                        {                                                UVDcIndex=(*(lptemp+1))>>4;   //U,V                                                UVAcIndex=((*(lptemp+1))&0x0f)+2;                                        }                                        lptemp+=2;//comp_num<256,但是2*comp_num+3可能>=512                                }                                                  lp+=llength;                                  lp-=P_Cal(lp);                                         finish=TRUE;                                break;                        case M_EOI:return FUNC_FORMAT_ERROR;//图片结束 标记                             default:                                 if ((id&0xf0)!=0xd0)                                {                                                      llength=MAKEWORD(*(lp+1),*lp);                                        lp+=llength;                                          lp-=P_Cal(lp);                                 }                                else lp+=2;                                break;                  }  //switch        } //while        return FUNC_OK;}void showerror(int funcret){    switch(funcret)      {        case FUNC_MEMORY_ERROR :        printf("Error alloc memory\r\n!");        break ;        case FUNC_FILE_ERROR :        printf("File not found!\r\n");        break ;        case FUNC_FORMAT_ERROR :        printf("File format error!\r\n");        break ;        case Decode_OK :        printf("File Decode Finished!\r\n");        break;    }}//对指针地址进行改变!//pc    :当前指针//返回值:当前指针的减少量.在d_buffer里面自动进行了偏移unsigned int P_Cal(unsigned char*pc){                                                                                           unsigned short cont=0;                 //计数器        unsigned long buffer_val=0;  //寄存区首地址        unsigned long point_val=0;         //指针所指的当前地址        unsigned char secoff;                 unsigned short t;        unsigned char *p;        u16 read = 512;                  p = jpg_buffer+512;//偏移到中间        point_val = (unsigned long)pc;//得到当前指针所指地址        buffer_val = (unsigned long)&jpg_buffer;//得到缓存区首地址        cont = point_val-buffer_val;//得到两者之差        if(cont >= 512)//数据超过了中间        {                secoff = cont/512;//超出了多少secoff个512字节                         while(secoff)   //读取secoff次512个字节                {                        for(t=0;t<512;t++)jpg_buffer[t] = p[t];//复制后512个字节 给前512个字节                                            if((byte_left<read)&&(byte_left!=0))read = byte_left;                        else if(byte_left==0)break;//读取完毕,退出                        if(f_read(&pic_to_show,p,read,&byte_left)!=FR_OK)break;//读取失败,退出                        secoff--;                }                              }        return cont-cont%512;//指针地址缩减                                                                 }//解码JPG//调用顺序: Initialize_Fast_IDCT() :初始化 //          DecodeMCUBlock()       Huffman Decode //          IQtIZzMCUComponent()   反量化、反DCT //          GetYUV()               Get Y U V //          StoreBuffer()          YUV to RGB int Decode(void){        int funcret;                Y_in_MCU=SampRate_Y_H*SampRate_Y_V;//YDU YDU YDU YDU        U_in_MCU=SampRate_U_H*SampRate_U_V;//cRDU         V_in_MCU=SampRate_V_H*SampRate_V_V;//cBDU        H_YtoU=SampRate_Y_H/SampRate_U_H;        V_YtoU=SampRate_Y_V/SampRate_U_V;        H_YtoV=SampRate_Y_H/SampRate_V_H;        V_YtoV=SampRate_Y_V/SampRate_V_V;        Initialize_Fast_IDCT();        while((funcret=DecodeMCUBlock())==FUNC_OK) //After Call DecodeMCUBUBlock()        {                interval++;          &nb

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top