S3C6410 裸机硬件JPEG解码


2012年12月25日,晚上我找到问题所在了,JPEG解码源图像地址必须是16字节(128位)对齐的,也就是最低4位必须为0,这个害的我好久,还好终于解决了。

修复了已知的bug;

这个是我实验用的原图,用工具把他变成了数组后直接放在程序里面了.

解码后的图片

附上代码

/*************************************************************************************************************
 * 文件名   : JpegCodec.c
 * 功能   : S3C6410 JPEG解码底层驱动函数
 * 作者   : cp1300@139.com
 * 创建时间  : 2012年9月20日20:59
 * 最后修改时间 : 2012年12月02日
 * 详细   : JPEG硬解码
 *      通过S3C6410 DATASHEETV1.2版以及官方WINCE的JPEG驱动的分析,得出结论,S3C6410的JPEG解码模块不支持硬件控制自动解码
 *      只能使用软件控制解码模式
 *    20121202:修复连续解码BUG,目前有少数jpeg420,jpeg444会解码出错,就像windows也有可能有不支持的jpeg图片一样,少数图片硬解码
 *      失败可以尝试使用软解码即可。
 *    20121225:发现JPEG必须16字节(128位)地址对齐,否则可能会出现解码失败问题。
 *    20130113:增加尺寸非8或16倍数的jpeg图片解码功能
 *    20130113:将程序外部依赖降低,目前只依赖外部的数据类型定义(高类聚,低耦合),打印调试也依赖外部,不用可以修改宏,JPEG_DBUG=0来取消,方便移植。
*************************************************************************************************************/
#include "JpegCodec.h"
#include "jpeg_tables.h"


//调试宏开关
#define JPEG_DBUG 0
#if JPEG_DBUG
 #include "system.h"
 #define jpeg_debug(format,...) uart_printf(format,##__VA_ARGS__)
#else
 #define jpeg_debug(format,...) /\
/
#endif //JPEG_DBUG

 

//jpeg编解码模式配置
#define COEF1_RGB_2_YUV        0x4d971e
#define COEF2_RGB_2_YUV        0x2c5783
#define COEF3_RGB_2_YUV        0x836e13

#define ENABLE_MOTION_ENC      (0x1<<3)  //使能动态编码
#define DISABLE_MOTION_ENC      (0x0<<3)

#define ENABLE_HW_DEC          (0x1<<2)
#define DISABLE_HW_DEC          (0x0<<2)

#define ENABLE_MOTION_DEC      (0x1<<0)  //使能动态解码
#define DISABLE_MOTION_DEC      (0x0<<0) 

#define INCREMENTAL_DEC   (0x1<<3)  //增量解码模式
#define NORMAL_DEC              (0x0<<3)  //正常解码模式
#define YCBCR_MEMORY   (0x1<<5)

#define ENABLE_IRQ    (0xf<<3)

//等待超时定义
#define WaitTimeOut    0xffffff   //等待超时计数器

//定义最大图像宽高度
#define MAX_JPG_WIDTH  4096
#define MAX_JPG_HEIGHT  4096

//JPEG寄存器结构定义
typedef struct
{
 u32  Mode;    //模式寄存器
 u32  Status;    //状态寄存器
 u32  QTblNo;
 u32  RSTPos;
 u32  Vertical;   //垂直分辨率
 u32  Horizontal;   //水平分辨率
 u32  DataSize;   //压缩数据字节数
 u32  IRQ;    //中断设置寄存器
 u32  IRQStatus;   //中断状态寄存器 0x20
 u32  Reserved0[247];
 u32  QTBL0[64];       //0x400
 u32  QTBL1[64];
 u32  QTBL2[64];
 u32  QTBL3[64];
 u32  HDCTBL0[16];      //0x800
 u32  HDCTBLG0[12];
 u32  Reserved1[4];
 u32  HACTBL0[16];
 u32  HACTBLG0[162];      //0x8c0
 u32  Reserved2[46];
 u32  HDCTBL1[16];      //0xc00
 u32  HDCTBLG1[12];
 u32  Reserved3[4];
 u32  HACTBL1[16];
 u32  HACTBLG1[162];      //0xcc0
 u32  Reserved4[46];
 u32  ImageAddr0;   //目的图像地址1
 u32  ImageAddr1;   //目的图像地址2
 u32  JpegAddr0;   //源JPEG图像地址1
 u32  JpegAddr1;   //源JPEG图像地址2
 u32  Start;    //JPEG解码开始
 u32  ReStart;   //重新开始JPEG解码
 u32  SofReset;   //JPEG复位
 u32  Cntl;    //控制寄存器
 u32  COEF1;
 u32  COEF2;
 u32  COEF3;
 u32  Misc;    //杂项寄存器
 u32  FramIntv;
}JPEG_TypeDef;

 

//定义JPEG文件标记
enum
{
    UNKNOWN,
    BASELINE = 0xC0,
    EXTENDED_SEQ = 0xC1,
    PROGRESSIVE = 0xC2
}JPG_SOF_MARKER;


//S3C6410 jpeg编解码器基址
#define JPEG_BASE  0x78800000 


//寄存器结构指针
#define JPEG ((JPEG_TypeDef *)JPEG_BASE)


//内部静态函数声明
static void JPEG_Reset(void);  //JPEG解码器软件复位
static JPEG_TYPE JPEG_GetJpegType(void); //获取JPEG采样模式
static void JPEG_GetWidthHeight(u16* width, u16* height);//获取图像大小
static JPEG_ERROR JPEG_WaitForIRQ(void); //等待中断,并返回状态
static bool JPEG_CorrectHeader(JPEG_TYPE jpegType, u16 *width, u16 *height);
static void JPEG_WriteHeader(u32 JpgAddr, u32 fileSize, u16 width, u16 height);
static void JPEG_WriteYUV(u32 ImageAddr, u16 width, u16 orgwidth, u16 height, u16 orgheight);
static void JPEG_MemMove(u8* dest, u8* src,u32 count);


/*************************************************************************************************************************
*函数      : void JPEG_Init(void)
*功能      : JPEG解码初始化
*参数      : 无
*返回      : 无
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间     : 20120920
*最后修改时间 : 20120923
*说明     : 无
*************************************************************************************************************************/
void JPEG_Init(void)
{
 //rCLK_DIV0 |= 0x03 << 24;
 //Set_GateClk(SCLK_JPEG,ENABLE); //使能JPEG模块时钟
}


/*************************************************************************************************************************
*函数      : static void JPEG_Reset(void)
*功能      : JPEG解码器软件复位
*参数      : 无
*返回      : 无
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间      : 20120920
*最后修改时间 : 2010113
*说明      : 无
*************************************************************************************************************************/
static void JPEG_Reset(void)
{
 JPEG->SofReset = 0;
}


/*************************************************************************************************************************
*函数      : static JPEG_TYPE JPEG_Reset(void)
*功能      : 获取JPEG采样模式
*参数      : 无
*返回      : JPEG类型,见定义
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间      : 20120920
*最后修改时间 : 2010113
*说明      : 编码模式只有0x1,0x2两种模式
*************************************************************************************************************************/
static JPEG_TYPE JPEG_GetJpegType(void)
{
 switch (JPEG->Mode & 0x07) //通过判断0-2BIT
 {
  case 0 : return TYPE_JPEG_444;  //色度4:4:4格式
  case 1 :  return TYPE_JPEG_422;  //色度4:2:2格式
  case 2 :  return TYPE_JPEG_420;  //色度4:2:0格式
  case 3 :  return TYPE_JPEG_400;  //灰色格式(单一组成)
  case 6 :  return TYPE_JPEG_411;  //色度4:1:1格式
  default :  return TYPE_JPEG_UNKNOWN; 
 }
}

 

/*************************************************************************************************************************
*函数      : static void JPEG_GetWidthHeight(u16* width, u16* height)
*功能      : 获取图像尺寸大小
*参数      : HSize:图像宽度缓冲区指针;VSize:图像高度缓冲区指针
*返回      : 无
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间      : 20120920
*最后修改时间 : 2010113
*说明      : 16BIT
*************************************************************************************************************************/
static void JPEG_GetWidthHeight(u16* width, u16* height)
{
 *width = JPEG->Horizontal;  //在水平方向上定义图像大小的值
 *height = JPEG->Vertical;  //在垂直方向上定义图像大小的值
}


/*************************************************************************************************************************
*函数      : u32 JPEG_GetYUVSize(JPEG_TYPE jpegType,u16 width, u16 height)
*功能      : 获取解码后数据大小
*参数      : jpegType:jpeg图像类型,width,height:图像尺寸
*返回      : 无
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间      : 2010113
*最后修改时间 : 2010113
*说明      : 无
*************************************************************************************************************************/
u32 JPEG_GetYUVSize(JPEG_TYPE jpegType,u16 width, u16 height)
{
 switch(jpegType)
 {
  case TYPE_JPEG_444 :  return(width*height*3);
    case TYPE_JPEG_422 :  return(width*height*2);
    case TYPE_JPEG_420 : 
    case TYPE_JPEG_411 :  return((width*height) + (width*height>>1));
    case TYPE_JPEG_400 :  return(width*height);
    default :     return(0);
 }
}

 

/*************************************************************************************************************************
*函数      : void JPEG_ReadClearStatus(u8* Status, u8* IrqStatus)
*功能      : 读取并清除JPEG状态
*参数      : Status:解码器状态缓冲区指针;IrqStatus:中断状态缓冲区指针
*返回      : 无
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间      : 20120920
*最后修改时间 : 2010113
*说明      : JPGSTS和JPGIRQ;JPGIRQ读取后自动清除
*     JPGIRQ: BIT6结果状态 0:不正常的处理结束; 1:正常的处理完成
*      BIT4位流的错误状态。只有在解压缩期间有效。0:在被压缩的文件上,没有语法错误。1:在被压缩的文件上,有语法错误。
*      BIT3标题状态。只有在解压缩期间有效。0:图像大小和取样因素值不可读。1:图像大小和取样因素值可读。 
*************************************************************************************************************************/
void JPEG_ReadClearStatus(u8* Status, u8* IrqStatus)
{
 *Status = JPEG->Status;
 *IrqStatus = JPEG->IRQStatus & ((1<<6)|(1<<4)|(1<<3));
}


/*************************************************************************************************************************
*函数      : static JPEG_ERROR JPEG_WaitForIRQ(void)
*功能      : 等待中断,并返回状态
*参数      : 无
*返回      : 返回中断状态,见定义
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间      : 20120922
*最后修改时间 : 2010113
*说明      : 通过判断JPGIRQ中断寄存器的值返回相应状态
*************************************************************************************************************************/
static JPEG_ERROR JPEG_WaitForIRQ(void)

    vu32 TimeOut = WaitTimeOut;  //初始化计数器值 
    vu8 IRQStatus,Status;
    JPEG_ERROR error;
   
    do 
    {   
        IRQStatus = JPEG->IRQStatus;  //读取中断状态寄存器,并消除状态
        TimeOut --;               //计数器自减 
    } 
    while((IRQStatus == 0) && TimeOut);    //当发生中断或者计数器为0时退出等待
    IRQStatus &= ((1<<6)|(1<<4)|(1<<3));
 switch (IRQStatus)                //判断中断状态 
    { 
  case 0x00 : error =  JPEG_WAIT_TIME_OUT;break;  //超时错误
        case 0x40 : error =  JPEG_OK;break;    //正常完成 
        case 0x08 : error =  JPEG_HEADER_OK;break;   //头分析完成,可以读取大小以及采样信息 
        case 0x10 : error =  JPEG_BITSTRE_ERROR;break;  //语法错误 
        case 0x18 : error =  JPEG_BITSTRE_ERROR;break;  //语法错误 
        default : error =  JPEG_OTHER_ERROR;break;      //其它错误 
    }
    Status = JPEG->Status;
    return error;
}

 

/*************************************************************************************************************************
*函数      : static void JPEG_DecodeHeader(u32 JpegAddr)
*功能      : 开始解码JPEG头部信息(软件控制解码)
*参数      : JpegAddr: jpeg图像地址
*返回      : 无
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间      : 20120920
*最后修改时间 : 2010113
*说明      : 用于软件解码的第一步,用于获取JPEG分辨率以及采样模式信息
*************************************************************************************************************************/
static void JPEG_DecodeHeader(u32 JpegAddr)
{
 JPEG->JpegAddr0 = JpegAddr;
 JPEG->JpegAddr1 = JpegAddr;   //jpeg图片数据地址
 JPEG->Mode = 0x8;      //设置为解码模式
 JPEG->IRQ = ENABLE_IRQ;    //使能中断
 JPEG->Cntl = DISABLE_HW_DEC;  //解码JPEG头部
 JPEG->Misc = (NORMAL_DEC | YCBCR_MEMORY);
 JPEG->Start = 1;     //开始JPEG处理
}

 

/*************************************************************************************************************************
*函数      : static void JPEG_DecodeBody(u32 ImageAddr)
*功能      : 开始JPEG主体解码(软件控制解码)
*参数      : ImageAddr: 解码后图像地址
*返回      : 无
*依赖  :  底层宏定义
*作者      : cp1300@139.com
*时间      : 20120920
*最后修改时间 : 2010113
*说明      : 软件控制解码的第二步,一定要先调用JPEG_StartParsingHeader
*************************************************************************************************************************/
static void JPEG_DecodeBody(u32 ImageAddr)
{
 JPEG->ImageAddr0 = ImageAddr;
 JPEG->ImageAddr1 = ImageAddr;  //解码数据缓冲器地址
 JPEG->Cntl = 0;      //解码JPEG头部
 JPEG->Misc = 0;
 JPEG->ReStart = 1;     //开始主解码处理
}


/*************************************************************************************************************************
*函数      : JPEG_ERROR JPEG_DecodeOneFrame(u32 JpgAddr, u32 ImageAddr, u32 jpegSize, JPEG_INFO *JpegInfo)
*功能      : 开始解码一帧JPEG
*参数      : JpegAddr: jpeg图像地址
*     ImageAddr: 解码后图像地址
*     jpegSize: 图片数据大小
*     JpegInfo: 图像信息结构指针
*返回      : JPEG_ERROR
*依赖  :  JPEG_StartParsingHeader;JPEG_StartDecodingBody
*作者      : cp1300@139.com
*时间      : 20120920
*最后修改时间 : 2010113
*说明      : 软件控制解码模式
*     修改源图像地址128位对齐bug
*     20120113:增加尺寸非8或16倍数的jpeg图片解码功能,需要传递一个参数,即图片大小,通过FileSize传递
*        非对齐的jpeg解码效率将低于对齐的图片,由于解码前需要先改写数据。
*************************************************************************************************************************/
JPEG_ERROR JPEG_DecodeOneFrame(u32 JpgAddr, u32 ImageAddr, u32 jpegSize, JPEG_INFO *JpegInfo)
{
 JPEG_ERROR status;
 u16  width,height;
 bool headerFixed = FALSE;
#if JPEG_DBUG 
 const char *JpegType[6] = {"JPEG 4:4:4","JPEG 4:2:2","JPEG 4:2:0","JPEG 4:0:0","JPEG 4:1:1","JPEG UNKNOWN"};
#endif
 
 if(JpgAddr % 16)     //源地址一定要是16字节(128位)对齐的,否则会出现各种意想不到的问题,这个问题困扰了我5个多月。
 { 
  jpeg_debug("jpeg addr error\r\n");
  return JPEG_OTHER_ERROR;
 }
 
 JpegInfo->FileSize = jpegSize;  //存储图片大小
 jpeg_debug("\r\n");
 jpeg_debug("start jpeg decoding...\r\n");
 JPEG_Reset();
 JPEG_DecodeHeader(JpgAddr);   //分析JPEG文信息
 status = JPEG_WaitForIRQ();   //等待完成
 if(status != JPEG_HEADER_OK)  //图像分析错误
 {
  return status;
 }
 
 JpegInfo->Type = JPEG_GetJpegType();  //获取图片类型
 jpeg_debug("Jpeg Mod:%s\r\n",JpegType[JpegInfo->Type]);
 if(JpegInfo->Type == TYPE_JPEG_UNKNOWN) //未定义类型
 {
  return JPEG_TYPE_ERROR;
 }
 
 JPEG_GetWidthHeight(&(JpegInfo->Width),&(JpegInfo->Height));    //获取图片分辨率
 
 width = JpegInfo->Width;
 height = JpegInfo->Height;
 if(!JPEG_CorrectHeader(JpegInfo->Type, &(JpegInfo->Width), &(JpegInfo->Height)))
 {
        JPEG_WriteHeader(JpgAddr,jpegSize,JpegInfo->Width, JpegInfo->Height);
        headerFixed = TRUE;
 }
 
 jpeg_debug("jpeg image size %d*%d\r\n",JpegInfo->Width,JpegInfo->Height);
 
 
 if(JpegInfo->Width <= 0 || JpegInfo->Width > MAX_JPG_WIDTH || JpegInfo->Height <= 0 || JpegInfo->Height > MAX_JPG_HEIGHT)
 {
  return JPEG_SIZE_ERROR;
 }
 
 if(headerFixed == TRUE)
 {
  JPEG_Reset();
  JPEG_DecodeHeader(JpgAddr);   //分析JPEG文信息
  status = JPEG_WaitForIRQ();   //等待完成
  if(status != JPEG_HEADER_OK)  //图像分析错误
  {
   return status;
  }
 
  JPEG_DecodeBody(ImageAddr);   //解码JPEG
  status = JPEG_WaitForIRQ();   //等待完成
  if(status == JPEG_OK)
  {
   jpeg_debug("Jpeg decode OK(%d)\r\n",status);
   //JPEG_GetStreamLen(&(JpegInfo->DataSize)); //获取解码后图像大小
  }
  else
  {
   jpeg_debug("Jpeg decode error(%d)\r\n",status);
   return status;
  }
 
  // for post processor, discard pixel
  if(width % 4 != 0)
   width = (width/4)*4;
 
        if(height % 2 != 0)
            height = (height/2)*2;
       
        JPEG_WriteYUV(ImageAddr,JpegInfo->Width,width,JpegInfo->Height,height);
     
        JpegInfo->Width = width;
        JpegInfo->Height = height;
 }
 else
 {
  JPEG_DecodeBody(ImageAddr);   //解码JPEG
  status = JPEG_WaitForIRQ();   //等待完成
  if(status == JPEG_OK)
  {
   jpeg_debug("Jpeg decode OK(%d)\r\n",status);
   
  }
  else
  {
   jpeg_debug("Jpeg decode error(%d)\r\n",status);
   return status;
  }
 }
 JpegInfo->DataSize = JPEG_GetYUVSize(JpegInfo->Type,JpegInfo->Width,JpegInfo->Height);
 
 return status; //返回错误
}

 

/*************************************************************************************************************************
*函数      : JPEG_ERROR JPEG_EncodeOneFrame(u32 JpgAddr, u32 ImageAddr, JPEG_INFO *JpegInfo)
*功能      : 压缩一张JPEG
*参数      : JpegAddr: jpeg图像地址
*     ImageAddr: 解码后图像地址
*     JpegInfo: 图像信息结构指针
*返回      : JPEG_ERROR
*依赖  :  无
*作者      : cp1300@139.com
*时间      : 20130114
*最后修改时间 : 201310114
*说明      : 只支持YCbCr4:2:2,YCbCr4:2:0的输入格式
*     只测试了编码,能成功,但是没有生成jpeg文件进行测试,如果要生成jpeg文件应该还需要添加相应的文件头和尾部。
*************************************************************************************************************************/
JPEG_ERROR JPEG_EncodeOneFrame(u32 JpgAddr, u32 ImageAddr, JPEG_QUALITY_TYPE jpegQuality, JPEG_INFO *JpegInfo)
{
 JPEG_ERROR status = JPEG_OK;
    u32    i;

    if(JpegInfo->Width <= 0 || JpegInfo->Width > MAX_JPG_WIDTH || JpegInfo->Height <= 0 || JpegInfo->Height > MAX_JPG_HEIGHT)
 {
  return JPEG_SIZE_ERROR;
 }
   
    JPEG_Reset();
    JPEG->Mode = (JpegInfo->Type == TYPE_JPEG_422) ? (0x01 << 0) : (0x02 << 0);  //亚抽样模式
    JPEG->RSTPos = 2;                // MCU inserts RST marker
    JPEG->QTblNo = (1 << 12) | (1 << 14);
    JPEG->Horizontal = JpegInfo->Width;
    JPEG->Vertical = JpegInfo->Height;

    JPEG->ImageAddr0 = ImageAddr;
    JPEG->ImageAddr1 = ImageAddr;
    JPEG->JpegAddr0 = JpgAddr;
    JPEG->JpegAddr1 = JpgAddr;
 
    JPEG->COEF1 = COEF1_RGB_2_YUV; // Coefficient value 1 for RGB to YCbCr
    JPEG->COEF2 = COEF2_RGB_2_YUV; // Coefficient value 2 for RGB to YCbCr
    JPEG->COEF3 = COEF3_RGB_2_YUV; // Coefficient value 3 for RGB to YCbCr

    JPEG->Misc = (1<<5) | (0<<2);
    JPEG->Cntl = DISABLE_MOTION_ENC;
   
    // Quantiazation and Huffman Table setting
    for (i=0; i<64; i++)
     JPEG->QTBL0[i] = (u32)QTBL_Luminance[jpegQuality][i];

    for (i=0; i<64; i++)
     JPEG->QTBL1[i] = (u32)QTBL_Chrominance[jpegQuality][i];

    for (i=0; i<16; i++)
     JPEG->HDCTBL0[i] = (u32)HDCTBL0[i];

    for (i=0; i<12; i++)
     JPEG->HDCTBLG0[i] = (u32)HDCTBLG0[i];

    for (i=0; i<16; i++)
     JPEG->HACTBL0[i] = (u32)HACTBL0[i];

    for (i=0; i<162; i++)
     JPEG->HACTBLG0[i] = (u32)HACTBLG0[i];

    JPEG->Start = 0;
   
    status = JPEG_WaitForIRQ();
    if(status == JPEG_OK)
    {
     jpeg_debug("Jpeg encode OK!(%d)\r\n",status);
     JpegInfo->FileSize = JPEG->DataSize;
    }
    else
    {
     JpegInfo->FileSize = 0;
     jpeg_debug("Jpeg encode error!(%d)\r\n",status);
    }
     
 return status;
}

 

/*************************************************************************************************************************
*函数      : static bool JPEG_CorrectHeader(JPEG_TYPE jpegType, u16 *width, u16 *height)
*功能      : 检查图像的宽高时候满足要求
*参数      : jpegType: jpeg类型,见JPEG_TYPE
*     width:  图像宽度
*     height:  图像高度
*返回      : TRUE:需要重写宽度,高度
*     FALSE:无需重写宽度,高度
*依赖  :  无
*作者      : cp1300@139.com
*时间      : 20130113
*最后修改时间 : 20130113
*说明      : 直接由S3C6410官方代码移植而来
*     如果不满足要求,将计算最接近的满足要求的分辨率,JPEG分辨率需要能被8或者16整除,具体可以查阅相关资料
*************************************************************************************************************************/
static bool JPEG_CorrectHeader(JPEG_TYPE jpegType, u16 *width, u16 *height)
{
    bool result = FALSE;

    switch(jpegType){
        case TYPE_JPEG_400 :
        case TYPE_JPEG_444 :  
         {
          if((*width % 8 == 0) && (*height % 8 == 0))
                 result = TRUE;
                if(*width % 8 != 0)
                 *width += 8 - (*width % 8);
                if(*height % 8 != 0)
                 *height += 8 - (*height % 8);
                       
         }break;
        case TYPE_JPEG_422 :
         {
          if((*width % 16 == 0) && (*height % 8 == 0))
           result = TRUE;
          if(*width % 16 != 0)
           *width += 16 - (*width % 16);
          if(*height % 8 != 0)
           *height += 8 - (*height % 8);
         }break;
        case TYPE_JPEG_420 :
        case TYPE_JPEG_411 :
         {
          if((*width % 16 == 0) && (*height % 16 == 0))
           result = TRUE;
          if(*width % 16 != 0)
           *width += 16 - (*width % 16);
          if(*height % 16 != 0)
           *height += 16 - (*height % 16);
         }break;
        default : break;
    }
 
    return(result);
}

 


/*************************************************************************************************************************
*函数      : static void JPEG_WriteHeader(u32 JpgAddr, u32 fileSize, u16 width, u16 height)
*功能      : 重写jpeg头部信息
*参数      : JpgAddr:  jpeg文件的起始指针
*     fileSize: jpeg文件大小
*     width:  jpeg文件宽度,需要重写的宽度
*     height:  jpeg文件高度,需要重写的宽度
*返回      : 无
*依赖  :  无
*作者      : cp1300@139.com
*时间      : 20130113
*最后修改时间 : 20130113
*说明      : 重写的只是内存中的数据
*************************************************************************************************************************/
static void JPEG_WriteHeader(u32 JpgAddr, u32 fileSize, u16 width, u16 height)
{
    u32    i;
    u8    *ptr = (u8 *)(JpgAddr + fileSize);
    u8    *ptr2;
    u8    *SOF1;
    u8    *header;

    jpeg_debug("DD::Header is not multiple of MCU\r\n");
    for(i=0; i < fileSize; i++)
    {
        ptr--;
        if(*ptr == 0xFF)
        {
            ptr2 = ptr+1;
            if((*ptr2 == BASELINE) || (*ptr2 == EXTENDED_SEQ) || (*ptr2 == PROGRESSIVE))
            {
             jpeg_debug("jpeg match FFC0(i : %d)\r\n", i);
                SOF1 = ptr2+1;
                break;               
            }
        }
    }
    jpeg_debug("jpeg start header correction\r\n");
    if(i <= fileSize){
        //header = (SOF2 == NULL) ? (SOF1) : (SOF2);
        header = SOF1;
        jpeg_debug("header: %x %x %x\r\n", header[0], header[1], header[2]);
        header += 3; //length(2) + sampling bit(1)
        *header = (height>>8) & 0xFF;
        *header++;
        *header = height & 0xFF;
        *header++;
        *header = (width>>8) & 0xFF;
        *header++;
        *header = width & 0xFF;

    }
}

 

/*************************************************************************************************************************
*函数      : static void JPEG_MemMove(u8* dest, u8* src,u32 count)
*功能      : 由src所指内存区域复制count个字节到dest所指内存区域
*参数      : src:  源地址
*     dest: 目标地址
*     count: 数据数量
*返回      : 无
*依赖  :  无
*作者      : cp1300@139.com
*时间      : 2013014
*最后修改时间 : 2013114
*说明      : 内存复制,8bit对齐,为了减少外部函数的依赖
*************************************************************************************************************************/
static void JPEG_MemMove(u8* dest, u8* src,u32 count)
{
 u32 i;
 
 for(i = 0;i < count;i ++)
 {
  dest[i] = src[i];
 }
}


/*************************************************************************************************************************
*函数      : static void JPEG_WriteYUV(u32 ImageAddr, u16 width, u16 orgwidth, u16 height, u16 orgheight)
*功能      : 重写YUV数据,将数据对齐
*参数      : ImageAddr: 解码后图像地址
*     width:  图像对齐后的宽度
*     orgwidth: 图像原始宽度
*     height:  图像对齐后的高度
*     orgheight: 图像原始高度 
*返回      : 无
*依赖  :  无
*作者      : cp1300@139.com
*时间      : 20120920
*最后修改时间 : 2010113
*说明      : 无
*************************************************************************************************************************/
static void JPEG_WriteYUV(u32 ImageAddr, u16 width, u16 orgwidth, u16 height, u16 orgheight)
{
    u32    src, dst;
    u32    i;
    u8    *streamPtr;

    streamPtr = (u8 *)ImageAddr;
    src = 2*width;
    dst = 2*orgwidth;
    for(i = 1; i < orgheight; i++)
    {
     JPEG_MemMove(&streamPtr[dst], &streamPtr[src], 2*orgwidth);
        src += 2*width;
        dst += 2*orgwidth;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 下一页

相关内容