?
2012年12月25日,晚上我找到問題所在了,JPEG解碼源圖像地址必須是16字節(jié)(128位)對齊的,也就是最低4位必須為0,這個害的我好久,還好終于解決了。
修復(fù)了已知的bug;
這個是我實驗用的原圖,用工具把他變成了數(shù)組后直接放在程序里面了.
解碼后的圖片
附上代碼
/************************************************************************************************************* ?*?文件名 : JpegCodec.c ?*?功能 : S3C6410?JPEG解碼底層驅(qū)動函數(shù) ?*?作者 : cp1300@139.com ?*?創(chuàng)建時間 : 2012年9月20日20:59 ?*?最后修改時間 : 2012年12月02日 ?*?詳細 : JPEG硬解碼 ?*? 通過S3C6410?DATASHEETV1.2版以及官方WINCE的JPEG驅(qū)動的分析,得出結(jié)論,S3C6410的JPEG解碼模塊不支持硬件控制自動解碼 ?*? 只能使用軟件控制解碼模式 ?*? 20121202:修復(fù)連續(xù)解碼BUG,目前有少數(shù)jpeg420,jpeg444會解碼出錯,就像windows也有可能有不支持的jpeg圖片一樣,少數(shù)圖片硬解碼 ?*? 失敗可以嘗試使用軟解碼即可。 ?*? 20121225:發(fā)現(xiàn)JPEG必須16字節(jié)(128位)地址對齊,否則可能會出現(xiàn)解碼失敗問題。 ?*? 20130113:增加尺寸非8或16倍數(shù)的jpeg圖片解碼功能 ?*? 20130113:將程序外部依賴降低,目前只依賴外部的數(shù)據(jù)類型定義(高類聚,低耦合),打印調(diào)試也依賴外部,不用可以修改宏,JPEG_DBUG=0來取消,方便移植。 *************************************************************************************************************/ #include?"JpegCodec.h" #include?"jpeg_tables.h" //調(diào)試宏開關(guān) #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) //使能動態(tài)編碼 #define?DISABLE_MOTION_ENC??????(0x0<<3) #define?ENABLE_HW_DEC???????????(0x1<<2) #define?DISABLE_HW_DEC??????????(0x0<<2) #define?ENABLE_MOTION_DEC???????(0x1<<0) //使能動態(tài)解碼 #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 //等待超時計數(shù)器 //定義最大圖像寬高度 #define?MAX_JPG_WIDTH 4096 #define?MAX_JPG_HEIGHT 4096 //JPEG寄存器結(jié)構(gòu)定義 typedef?struct { u32 Mode; //模式寄存器 u32 Status; //狀態(tài)寄存器 u32 QTblNo; u32 RSTPos; u32 Vertical; //垂直分辨率 u32 Horizontal; //水平分辨率 u32 DataSize; //壓縮數(shù)據(jù)字節(jié)數(shù) u32 IRQ; //中斷設(shè)置寄存器 u32 IRQStatus; //中斷狀態(tài)寄存器 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復(fù)位 u32 Cntl; //控制寄存器 u32 COEF1; u32 COEF2; u32 COEF3; u32 Misc; //雜項寄存器 u32 FramIntv; }JPEG_TypeDef; //定義JPEG文件標(biāo)記 enum { ????UNKNOWN, ????BASELINE?=?0xC0, ????EXTENDED_SEQ?=?0xC1, ????PROGRESSIVE?=?0xC2 }JPG_SOF_MARKER; //S3C6410?jpeg編解碼器基址 #define?JPEG_BASE 0x78800000 //寄存器結(jié)構(gòu)指針 #define?JPEG ((JPEG_TypeDef?*)JPEG_BASE) //內(nèi)部靜態(tài)函數(shù)聲明 static?void?JPEG_Reset(void); //JPEG解碼器軟件復(fù)位 static?JPEG_TYPE?JPEG_GetJpegType(void); //獲取JPEG采樣模式 static?void?JPEG_GetWidthHeight(u16*?width,?u16*?height);//獲取圖像大小 static?JPEG_ERROR?JPEG_WaitForIRQ(void); //等待中斷,并返回狀態(tài) 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); /************************************************************************************************************************* *函數(shù)???? : void?JPEG_Init(void) *功能???? : JPEG解碼初始化 *參數(shù)???? : 無 *返回???? : 無 *依賴 :? 底層宏定義 *作者????? : cp1300@139.com *時間????? : 20120920 *最后修改時間 : 20120923 *說明????? : 無 *************************************************************************************************************************/ void?JPEG_Init(void) { //rCLK_DIV0?|=?0x03?<<?24; //Set_GateClk(SCLK_JPEG,ENABLE); //使能JPEG模塊時鐘 } /************************************************************************************************************************* *函數(shù)???? : static?void?JPEG_Reset(void) *功能???? : JPEG解碼器軟件復(fù)位 *參數(shù)???? : 無 *返回???? : 無 *依賴 :? 底層宏定義 *作者????? : cp1300@139.com *時間???? : 20120920 *最后修改時間 : 2010113 *說明???? : 無 *************************************************************************************************************************/ static?void?JPEG_Reset(void) { JPEG->SofReset?=?0; } /************************************************************************************************************************* *函數(shù)???? : static?JPEG_TYPE?JPEG_Reset(void) *功能???? : 獲取JPEG采樣模式 *參數(shù)???? : 無 *返回???? : 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; } } /************************************************************************************************************************* *函數(shù)???? : static?void?JPEG_GetWidthHeight(u16*?width,?u16*?height) *功能???? : 獲取圖像尺寸大小 *參數(shù)???? : HSize:圖像寬度緩沖區(qū)指針;VSize:圖像高度緩沖區(qū)指針 *返回???? : 無 *依賴 :? 底層宏定義 *作者????? : cp1300@139.com *時間???? : 20120920 *最后修改時間 : 2010113 *說明???? : 16BIT *************************************************************************************************************************/ static?void?JPEG_GetWidthHeight(u16*?width,?u16*?height) { *width?=?JPEG->Horizontal; //在水平方向上定義圖像大小的值 *height?=?JPEG->Vertical; //在垂直方向上定義圖像大小的值 } /************************************************************************************************************************* *函數(shù)???? : u32?JPEG_GetYUVSize(JPEG_TYPE?jpegType,u16?width,?u16?height) *功能???? : 獲取解碼后數(shù)據(jù)大小 *參數(shù)???? : 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); } } /************************************************************************************************************************* *函數(shù)???? : void?JPEG_ReadClearStatus(u8*?Status,?u8*?IrqStatus) *功能???? : 讀取并清除JPEG狀態(tài) *參數(shù)???? : Status:解碼器狀態(tài)緩沖區(qū)指針;IrqStatus:中斷狀態(tài)緩沖區(qū)指針 *返回???? : 無 *依賴 :? 底層宏定義 *作者????? : cp1300@139.com *時間???? : 20120920 *最后修改時間 : 2010113 *說明???? : JPGSTS和JPGIRQ;JPGIRQ讀取后自動清除 *? JPGIRQ: BIT6結(jié)果狀態(tài) 0:不正常的處理結(jié)束;?1:正常的處理完成 *? BIT4位流的錯誤狀態(tài)。只有在解壓縮期間有效。0:在被壓縮的文件上,沒有語法錯誤。1:在被壓縮的文件上,有語法錯誤。 *? BIT3標(biāo)題狀態(tài)。只有在解壓縮期間有效。0:圖像大小和取樣因素值不可讀。1:圖像大小和取樣因素值可讀。 *************************************************************************************************************************/ void?JPEG_ReadClearStatus(u8*?Status,?u8*?IrqStatus) { *Status?=?JPEG->Status; *IrqStatus?=?JPEG->IRQStatus?&?((1<<6)|(1<<4)|(1<IRQStatus; //讀取中斷狀態(tài)寄存器,并消除狀態(tài)? ????????TimeOut?--;????????????? //計數(shù)器自減?? ????}?? ????while((IRQStatus?==?0)?&&?TimeOut);?????//當(dāng)發(fā)生中斷或者計數(shù)器為0時退出等待? ????IRQStatus?&=?((1<<6)|(1<<4)|(1<Status; ????return?error; }? /************************************************************************************************************************* *函數(shù)???? : static?void?JPEG_DecodeHeader(u32?JpegAddr) *功能???? : 開始解碼JPEG頭部信息(軟件控制解碼) *參數(shù)???? : JpegAddr: jpeg圖像地址 *返回???? : 無 *依賴 :? 底層宏定義 *作者????? : cp1300@139.com *時間???? : 20120920 *最后修改時間 : 2010113 *說明???? : 用于軟件解碼的第一步,用于獲取JPEG分辨率以及采樣模式信息 *************************************************************************************************************************/ static?void?JPEG_DecodeHeader(u32?JpegAddr) { JPEG->JpegAddr0?=?JpegAddr; JPEG->JpegAddr1?=?JpegAddr;? //jpeg圖片數(shù)據(jù)地址 JPEG->Mode?=?0x8;? //設(shè)置為解碼模式 JPEG->IRQ?=?ENABLE_IRQ; //使能中斷 JPEG->Cntl?=?DISABLE_HW_DEC; //解碼JPEG頭部 JPEG->Misc?=?(NORMAL_DEC?|?YCBCR_MEMORY); JPEG->Start?=?1; //開始JPEG處理 } /************************************************************************************************************************* *函數(shù)???? : static?void?JPEG_DecodeBody(u32?ImageAddr) *功能???? : 開始JPEG主體解碼(軟件控制解碼) *參數(shù)???? : ImageAddr: 解碼后圖像地址 *返回???? : 無 *依賴 :? 底層宏定義 *作者????? : cp1300@139.com *時間???? : 20120920 *最后修改時間 : 2010113 *說明???? : 軟件控制解碼的第二步,一定要先調(diào)用JPEG_StartParsingHeader *************************************************************************************************************************/ static?void?JPEG_DecodeBody(u32?ImageAddr) { JPEG->ImageAddr0?=?ImageAddr; JPEG->ImageAddr1?=?ImageAddr; //解碼數(shù)據(jù)緩沖器地址 JPEG->Cntl?=?0; //解碼JPEG頭部 JPEG->Misc?=?0; JPEG->ReStart?=?1; //開始主解碼處理 } /************************************************************************************************************************* *函數(shù)???? : JPEG_ERROR?JPEG_DecodeOneFrame(u32?JpgAddr,?u32?ImageAddr,?u32?jpegSize,?JPEG_INFO?*JpegInfo) *功能???? : 開始解碼一幀JPEG *參數(shù)???? : JpegAddr: jpeg圖像地址 *? ImageAddr: 解碼后圖像地址 *? jpegSize: 圖片數(shù)據(jù)大小 *? JpegInfo: 圖像信息結(jié)構(gòu)指針 *返回???? : JPEG_ERROR *依賴 :? JPEG_StartParsingHeader;JPEG_StartDecodingBody *作者????? : cp1300@139.com *時間???? : 20120920 *最后修改時間 : 2010113 *說明???? : 軟件控制解碼模式 *? 修改源圖像地址128位對齊bug *? 20120113:增加尺寸非8或16倍數(shù)的jpeg圖片解碼功能,需要傳遞一個參數(shù),即圖片大小,通過FileSize傳遞 *? 非對齊的jpeg解碼效率將低于對齊的圖片,由于解碼前需要先改寫數(shù)據(jù)。 *************************************************************************************************************************/ 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字節(jié)(128位)對齊的,否則會出現(xiàn)各種意想不到的問題,這個問題困擾了我5個多月。 { jpeg_debug("jpeg?addr?errorrn"); return?JPEG_OTHER_ERROR; } JpegInfo->FileSize?=?jpegSize; //存儲圖片大小 jpeg_debug("rn"); jpeg_debug("start?jpeg?decoding...rn"); JPEG_Reset(); JPEG_DecodeHeader(JpgAddr); //分析JPEG文信息 status?=?JPEG_WaitForIRQ(); //等待完成 if(status?!=?JPEG_HEADER_OK) //圖像分析錯誤 { return?status; } JpegInfo->Type?=?JPEG_GetJpegType(); //獲取圖片類型 jpeg_debug("Jpeg?Mod:%srn",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*%drn",JpegInfo->Width,JpegInfo->Height); if(JpegInfo->Width?Width?>?MAX_JPG_WIDTH?||?JpegInfo->Height?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)rn",status); //JPEG_GetStreamLen(&(JpegInfo->DataSize)); //獲取解碼后圖像大小 } else { jpeg_debug("Jpeg?decode?error(%d)rn",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)rn",status); } else { jpeg_debug("Jpeg?decode?error(%d)rn",status); return?status; } } JpegInfo->DataSize?=?JPEG_GetYUVSize(JpegInfo->Type,JpegInfo->Width,JpegInfo->Height); return?status; //返回錯誤 } /************************************************************************************************************************* *函數(shù)???? : JPEG_ERROR?JPEG_EncodeOneFrame(u32?JpgAddr,?u32?ImageAddr,?JPEG_INFO?*JpegInfo) *功能???? : 壓縮一張JPEG *參數(shù)???? : JpegAddr: jpeg圖像地址 *? ImageAddr: 解碼后圖像地址 *? JpegInfo: 圖像信息結(jié)構(gòu)指針 *返回???? : JPEG_ERROR *依賴 :? 無 *作者????? : cp1300@139.com *時間???? : 20130114 *最后修改時間 : 201310114 *說明???? : 只支持YCbCr4:2:2,YCbCr4:2:0的輸入格式 *? 只測試了編碼,能成功,但是沒有生成jpeg文件進行測試,如果要生成jpeg文件應(yīng)該還需要添加相應(yīng)的文件頭和尾部。 *************************************************************************************************************************/ 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?Width?>?MAX_JPG_WIDTH?||?JpegInfo->Height?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<Cntl?=?DISABLE_MOTION_ENC; ???? ????//?Quantiazation?and?Huffman?Table?setting ????for?(i=0;?iQTBL0[i]?=?(u32)QTBL_Luminance[jpegQuality][i]; ????for?(i=0;?iQTBL1[i]?=?(u32)QTBL_Chrominance[jpegQuality][i]; ????for?(i=0;?iHDCTBL0[i]?=?(u32)HDCTBL0[i]; ????for?(i=0;?iHDCTBLG0[i]?=?(u32)HDCTBLG0[i]; ????for?(i=0;?iHACTBL0[i]?=?(u32)HACTBL0[i]; ????for?(i=0;?iHACTBLG0[i]?=?(u32)HACTBLG0[i]; ????JPEG->Start?=?0; ???? ????status?=?JPEG_WaitForIRQ(); ????if(status?==?JPEG_OK) ????{ ???? jpeg_debug("Jpeg?encode?OK!(%d)rn",status); ???? JpegInfo->FileSize?=?JPEG->DataSize; ????} ????else ????{ ???? JpegInfo->FileSize?=?0; ???? jpeg_debug("Jpeg?encode?error!(%d)rn",status); ????} ???? return?status; } /************************************************************************************************************************* *函數(shù)???? : static?bool?JPEG_CorrectHeader(JPEG_TYPE?jpegType,?u16?*width,?u16?*height) *功能???? : 檢查圖像的寬高時候滿足要求 *參數(shù)???? : jpegType: jpeg類型,見JPEG_TYPE *? width: 圖像寬度 *? height: 圖像高度 *返回???? : TRUE:需要重寫寬度,高度 *? FALSE:無需重寫寬度,高度 *依賴 :? 無 *作者????? : cp1300@139.com *時間???? : 20130113 *最后修改時間 : 20130113 *說明???? : 直接由S3C6410官方代碼移植而來 *? 如果不滿足要求,將計算最接近的滿足要求的分辨率,JPEG分辨率需要能被8或者16整除,具體可以查閱相關(guān)資料 *************************************************************************************************************************/ 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); } /************************************************************************************************************************* *函數(shù)???? : static?void?JPEG_WriteHeader(u32?JpgAddr,?u32?fileSize,?u16?width,?u16?height) *功能???? : 重寫jpeg頭部信息 *參數(shù)???? : JpgAddr: jpeg文件的起始指針 *? fileSize: jpeg文件大小 *? width: jpeg文件寬度,需要重寫的寬度 *? height: jpeg文件高度,需要重寫的寬度 *返回???? : 無 *依賴 :? 無 *作者????? : cp1300@139.com *時間???? : 20130113 *最后修改時間 : 20130113 *說明???? : 重寫的只是內(nèi)存中的數(shù)據(jù) *************************************************************************************************************************/ 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?MCUrn"); ????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)rn",?i); ????????????????SOF1?=?ptr2+1; ????????????????break;???????????????? ????????????} ????????} ????} ????jpeg_debug("jpeg?start?header?correctionrn"); ????if(i?>8)?&?0xFF; ????????*header++; ????????*header?=?height?&?0xFF; ????????*header++; ????????*header?=?(width>>8)?&?0xFF; ????????*header++; ????????*header?=?width?&?0xFF; ????} } /************************************************************************************************************************* *函數(shù)???? : static?void?JPEG_MemMove(u8*?dest,?u8*?src,u32?count) *功能???? : 由src所指內(nèi)存區(qū)域復(fù)制count個字節(jié)到dest所指內(nèi)存區(qū)域 *參數(shù)???? : src: 源地址 *? dest: 目標(biāo)地址 *? count: 數(shù)據(jù)數(shù)量 *返回???? : 無 *依賴 :? 無 *作者????? : cp1300@139.com *時間???? : 2013014 *最后修改時間 : 2013114 *說明???? : 內(nèi)存復(fù)制,8bit對齊,為了減少外部函數(shù)的依賴 *************************************************************************************************************************/ static?void?JPEG_MemMove(u8*?dest,?u8*?src,u32?count) { u32?i; for(i?=?0;i?<?count;i?++) { dest[i]?=?src[i]; } } /************************************************************************************************************************* *函數(shù)???? : static?void?JPEG_WriteYUV(u32?ImageAddr,?u16?width,?u16?orgwidth,?u16?height,?u16?orgheight) *功能???? : 重寫YUV數(shù)據(jù),將數(shù)據(jù)對齊 *參數(shù)???? : 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; ????} }
?
/************************************************************************************************************* ?*?文件名 : JpegCodec.H ?*?功能 : S3C6410?JPEG解碼底層驅(qū)動函數(shù) ?*?作者 : cp1300@139.com ?*?創(chuàng)建時間 : 2012年9月20日20:59 ?*?最后修改時間 : 2012年12月02日 ?*?詳細 : JPEG硬解碼 ?*? 通過S3C6410?DATASHEETV1.2版以及官方WINCE的JPEG驅(qū)動的分析,得出結(jié)論,S3C6410的JPEG解碼模塊不支持硬件控制自動解碼 ?*? 只能使用軟件控制解碼模式 ?*? 20121202:修復(fù)連續(xù)解碼BUG,目前有少數(shù)jpeg420,jpeg444會解碼出錯,就像windows也有可能有不支持的jpeg圖片一樣,少數(shù)圖片硬解碼 ?*? 失敗可以嘗試使用軟解碼即可。 ?*? 20121225:發(fā)現(xiàn)JPEG必須16字節(jié)(128位)地址對齊,否則可能會出現(xiàn)解碼失敗問題。 ?*? 20130113:增加尺寸非8或16倍數(shù)的jpeg圖片解碼功能 ?*? 20130113:將程序外部依賴降低,目前只依賴外部的數(shù)據(jù)類型定義,打印調(diào)試也依賴外部,不用可以修改宏,JPEG_DBUG=0來取消,方便移植。 *************************************************************************************************************/ #ifndef?__JPEGCODEC_H__ #define?__JPEGCODEC_H__ #include?"sys_types.h" //數(shù)據(jù)類型定義 //JPEG類型定義 typedef?enum { TYPE_JPEG_444?=?0,? //JPEG?444 TYPE_JPEG_422?=?1,? //JPEG?422 TYPE_JPEG_420?=?2,? //JPEG?420 TYPE_JPEG_400?=?3,? //JPEG?400?(Gray) TYPE_JPEG_411?=?4, //JPEG?411 TYPE_JPEG_UNKNOWN?=?5 //未知 }?JPEG_TYPE; //JPEG?DEC模式 typedef?enum { DEC_HEADER?=?0,? //只解碼頭部信息 DEC_BODY?=?1,? //只解碼主體 }?JPEG_DEC_MODE; //JPEG?DEC模式 typedef?enum { JPEG_OK = 0, //正常處理完成 JPEG_HEADER_OK = 1, //圖像大小和取樣因素值可讀。 JPEG_BITSTRE_ERROR= 2, //在被壓縮的文件上,有語法錯誤 JPEG_WAIT_TIME_OUT= 3, //等待超時 JPEG_TYPE_ERROR???=?4, //不支持的圖像類型,圖像類型錯誤 JPEG_SIZE_ERROR???=?5, //圖像大小錯誤,圖像分辨率為0,或超出范圍 JPEG_OTHER_ERROR= 6 //其它未知錯誤,一般是地址未16字節(jié)對齊 }?JPEG_ERROR; //JPEG?文件信息 typedef?struct { u16?Width; //圖像寬度 u16?Height; //圖像高度 u32?FileSize; //JPEG圖片大小 u32?DataSize; //圖像解碼后數(shù)據(jù)大小 JPEG_TYPE?Type; //圖像類型定義 }?JPEG_INFO; //圖像壓縮質(zhì)量等級 typedef?enum { ????JPEG_QUALITY_LEVEL_1?=?0,? //高質(zhì)量 ????JPEG_QUALITY_LEVEL_2?=?1, ????JPEG_QUALITY_LEVEL_3?=?2, ????JPEG_QUALITY_LEVEL_4?=?3 //低質(zhì)量??? }JPEG_QUALITY_TYPE; //相關(guān)函數(shù)聲明 void?JPEG_Init(void); //JPEG解碼初始化 void?JPEG_ReadClearStatus(u8*?Status,?u8*?IrqStatus);//讀取并清除JPEG狀態(tài) u32?JPEG_GetYUVSize(JPEG_TYPE?jpegType,u16?width,?u16?height); //獲取解碼后數(shù)據(jù)大小 JPEG_ERROR?JPEG_DecodeOneFrame(u32?JpgAddr,?u32?ImageAddr,?u32?jpegSize,?JPEG_INFO?*JpegInfo);//開始解碼一幀JPEG JPEG_ERROR?JPEG_EncodeOneFrame(u32?JpgAddr,?u32?ImageAddr,?JPEG_QUALITY_TYPE?jpegQuality,?JPEG_INFO?*JpegInfo); //開始編碼一張JPEG #endif?//?__JPEGCODEC_H__
?
/************************************************************************************************************* ?*?文件名: jpeg_tables.h ?*?功能: S3C6410?jpeg編碼表 ?*?作者: cp1300@139.com ?*?創(chuàng)建時間: 2013年01月14日 ?*?最后修改時間:2013年01月14日 ?*?詳細: 直接使用的官方的代碼 *************************************************************************************************************/ #ifndef?__JPEG_TABLES_H__ #define?__JPEG_TABLES_H__ const?unsigned?char?QTBL_Luminance[4][64]= { ????//?level?1?-?high?quality ????{ ????????8,?6,?6,?8,?12,?14,?16,?17, ????????6,?6,?6,?8,?10,?13,?12,?15, ????????6,?6,?7,?8,?13,?14,?18,?24, ????????8,?8,?8,?14,?13,?19,?24,?35, ????????12,?10,?13,?13,?20,?26,?34,?39, ????????14,?13,?14,?19,?26,?34,?39,?39, ????????16,?12,?18,?24,?34,?39,?39,?39, ????????17,?15,?24,?35,?39,?39,?39,?39 ????},???? ????//?level?2 ????{ ????????12,?8,?8,?12,?17,?21,?24,?23,? ????????8,?9,?9,?11,?15,?19,?18,?23,? ????????8,?9,?10,?12,?19,?20,?27,?36,? ????????12,?11,?12,?21,?20,?28,?36,?53,? ????????17,?15,?19,?20,?30,?39,?51,?59,? ????????21,?19,?20,?28,?39,?51,?59,?59,? ????????24,?18,?27,?36,?51,?59,?59,?59,? ????????23,?23,?36,?53,?59,?59,?59,?59? ????}, ????//?level?3 ????{ ????????16,?11,?11,?16,?23,?27,?31,?30,? ????????11,?12,?12,?15,?20,?23,?23,?30,? ????????11,?12,?13,?16,?23,?26,?35,?47,? ????????16,?15,?16,?23,?26,?37,?47,?64,? ????????23,?20,?23,?26,?39,?51,?64,?64,? ????????27,?23,?26,?37,?51,?64,?64,?64,? ????????31,?23,?35,?47,?64,?64,?64,?64,? ????????30,?30,?47,?64,?64,?64,?64,?64? ????}, ????//?level?4?-?low?quality ????{ ????????20,?16,?25,?39,?50,?46,?62,?68,? ????????16,?18,?23,?38,?38,?53,?65,?68,? ????????25,?23,?31,?38,?53,?65,?68,?68,? ????????39,?38,?38,?53,?65,?68,?68,?68,? ????????50,?38,?53,?65,?68,?68,?68,?68,? ????????46,?53,?65,?68,?68,?68,?68,?68,? ????????62,?65,?68,?68,?68,?68,?68,?68,? ????????68,?68,?68,?68,?68,?68,?68,?68? ????} }; const?unsigned?char?QTBL_Chrominance[4][64]= { ????//?level?1?-?high?quality ????{ ????????9,?8,?9,?11,?14,?17,?19,?24,? ????????8,?10,?9,?11,?14,?13,?17,?22,? ????????9,?9,?13,?14,?13,?15,?23,?26,? ????????11,?11,?14,?14,?15,?20,?26,?33,? ????????14,?14,?13,?15,?20,?24,?33,?39,? ????????17,?13,?15,?20,?24,?32,?39,?39,? ????????19,?17,?23,?26,?33,?39,?39,?39,? ????????24,?22,?26,?33,?39,?39,?39,?39 ????}, ????//?level?2 ????{ ????????13,?11,?13,?16,?20,?20,?29,?37,? ????????11,?14,?14,?14,?16,?20,?26,?32,? ????????13,?14,?15,?17,?20,?23,?35,?40,? ????????16,?14,?17,?21,?23,?30,?40,?50,? ????????20,?16,?20,?23,?30,?37,?50,?59,? ????????20,?20,?23,?30,?37,?48,?59,?59,? ????????29,?26,?35,?40,?50,?59,?59,?59,? ????????37,?32,?40,?50,?59,?59,?59,?59? ????}, ????//?level?3 ????{ ????????17,?15,?17,?21,?20,?26,?38,?48,? ????????15,?19,?18,?17,?20,?26,?35,?43,? ????????17,?18,?20,?22,?26,?30,?46,?53,? ????????21,?17,?22,?28,?30,?39,?53,?64,? ????????20,?20,?26,?30,?39,?48,?64,?64,? ????????26,?26,?30,?39,?48,?63,?64,?64,? ????????38,?35,?46,?53,?64,?64,?64,?64,? ????????48,?43,?53,?64,?64,?64,?64,?64? ? ????}, ????//?level?4?-?low?quality ????{ ????????21,?25,?32,?38,?54,?68,?68,?68,? ????????25,?28,?24,?38,?54,?68,?68,?68,? ????????32,?24,?32,?43,?66,?68,?68,?68,? ????????38,?38,?43,?53,?68,?68,?68,?68,? ????????54,?54,?66,?68,?68,?68,?68,?68,? ????????68,?68,?68,?68,?68,?68,?68,?68,? ????????68,?68,?68,?68,?68,?68,?68,?68,? ????????68,?68,?68,?68,?68,?68,?68,?68? ? ????} }; const?unsigned?char?QTBL0[64]= { #if?1 ????0x10,?0x0B,?0x0A,?0x10,?0x18,?0x28,?0x33,?0x3D, ????0x0C,?0x0C,?0x0E,?0x13,?0x1A,?0x3A,?0x3C,?0x37, ????0x0E,?0x0D,?0x10,?0x18,?0x28,?0x39,?0x45,?0x38, ????0x0E,?0x11,?0x16,?0x1D,?0x33,?0x57,?0x50,?0x3E, ????0x12,?0x16,?0x25,?0x38,?0x44,?0x6D,?0x67,?0x4D, ????0x18,?0x23,?0x37,?0x40,?0x51,?0x68,?0x71,?0x5C, ????0x31,?0x40,?0x4E,?0x57,?0x67,?0x79,?0x78,?0x65, ????0x48,?0x5C,?0x5F,?0x62,?0x70,?0x64,?0x67,?0x63 #else ????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01, ????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01, ????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01, ????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01, ????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01, ????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01, ????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01, ????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01 #endif }; //Added?Quantization?Table const?unsigned?char?std_chrominance_quant_tbl_plus[64]= {???? ????0x11,?0x12,?0x18,?0x2F,?0x63,?0x63,?0x63,?0x63, ????0x12,?0x15,?0x1A,?0x42,?0x63,?0x63,?0x63,?0x63, ????0x18,?0x1A,?0x38,?0x63,?0x63,?0x63,?0x63,?0x63, ????0x2F,?0x42,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63, ????0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63, ????0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63, ????0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63, ????0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63 }; //Quantization?Table0 unsigned?char?std_luminance_quant_tbl[64]?= { ????1,???1,???2,???1,???1,???2,???2,???2, ????2,???3,???2,???2,???3,???3,???6,???4, ????3,???3,???3,???3,???7,???5,???8,???4, ????6,???8,???8,??10,???9,???8,???7,??11, ????8,??10,??14,??13,??11,??10,??10,??12, ????10,???8,???8,??11,??16,??12,??12,??13, ????15,??15,??15,??15,???9,??11,??16,??17, ????15,??14,??17,??13,??14,??14,??14,???1 ?}; //Quantization?Table1 unsigned?char?std_chrominance_quant_tbl[64]?= { ????4,???4,???4,???5,???4,???5,???9,???5, ????5,???9,??15,??10,???8,??10,??15,??26, ????19,???9,???9,??19,??26,??26,??26,??26, ????13,??26,??26,??26,??26,??26,??26,??26, ????26,??26,??26,??26,??26,??26,??26,??26, ????26,??26,??26,??26,??26,??26,??26,??26, ????26,??26,??26,??26,??26,??26,??26,??26, ????26,??26,??26,??26,??26,??26,??26,??26 }; //Huffman?Table unsigned?char?HDCTBL0[16]??=?{0,?1,?5,?1,?1,?1,?1,?1,?1,?0,?0,?0,?0,?0,?0,?0}; unsigned?char?HDCTBLG0[12]?=?{0,?1,?2,?3,?4,?5,?6,?7,?8,?9,?0xa,?0xb}; unsigned?char?HACTBL0[16]=?{0,?2,?1,?3,?3,?2,?4,?3,?5,?5,?4,?4,?0,?0,?1,?0x7d}; const?unsigned?char?HACTBLG0[162]= { ????0x01,?0x02,?0x03,?0x00,?0x04,?0x11,?0x05,?0x12, ????0x21,?0x31,?0x41,?0x06,?0x13,?0x51,?0x61,?0x07, ????0x22,?0x71,?0x14,?0x32,?0x81,?0x91,?0xa1,?0x08, ????0x23,?0x42,?0xb1,?0xc1,?0x15,?0x52,?0xd1,?0xf0, ????0x24,?0x33,?0x62,?0x72,?0x82,?0x09,?0x0a,?0x16, ????0x17,?0x18,?0x19,?0x1a,?0x25,?0x26,?0x27,?0x28, ????0x29,?0x2a,?0x34,?0x35,?0x36,?0x37,?0x38,?0x39, ????0x3a,?0x43,?0x44,?0x45,?0x46,?0x47,?0x48,?0x49, ????0x4a,?0x53,?0x54,?0x55,?0x56,?0x57,?0x58,?0x59, ????0x5a,?0x63,?0x64,?0x65,?0x66,?0x67,?0x68,?0x69, ????0x6a,?0x73,?0x74,?0x75,?0x76,?0x77,?0x78,?0x79, ????0x7a,?0x83,?0x84,?0x85,?0x86,?0x87,?0x88,?0x89, ????0x8a,?0x92,?0x93,?0x94,?0x95,?0x96,?0x97,?0x98, ????0x99,?0x9a,?0xa2,?0xa3,?0xa4,?0xa5,?0xa6,?0xa7, ????0xa8,?0xa9,?0xaa,?0xb2,?0xb3,?0xb4,?0xb5,?0xb6, ????0xb7,?0xb8,?0xb9,?0xba,?0xc2,?0xc3,?0xc4,?0xc5, ????0xc6,?0xc7,?0xc8,?0xc9,?0xca,?0xd2,?0xd3,?0xd4, ????0xd5,?0xd6,?0xd7,?0xd8,?0xd9,?0xda,?0xe1,?0xe2, ????0xe3,?0xe4,?0xe5,?0xe6,?0xe7,?0xe8,?0xe9,?0xea, ????0xf1,?0xf2,?0xf3,?0xf4,?0xf5,?0xf6,?0xf7,?0xf8, ????0xf9,?0xfa }; //Huffman?Table0 unsigned?char?len_dc_luminance[16]?={?0,?1,?5,?1,?1,?1,?1,?1,?1,?0,?0,?0,?0,?0,?0,?0?}; unsigned?char?val_dc_luminance[12]?={?0,?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11?}; unsigned?char?len_ac_luminance[16]?={?0,?2,?1,?3,?3,?2,?4,?3,?5,?5,?4,?4,?0,?0,?1,?0x7d?}; unsigned?char?val_ac_luminance[162]?= { ????0x01,?0x02,?0x03,?0x00,?0x04,?0x11,?0x05,?0x12, ????0x21,?0x31,?0x41,?0x06,?0x13,?0x51,?0x61,?0x07, ????0x22,?0x71,?0x14,?0x32,?0x81,?0x91,?0xa1,?0x08, ????0x23,?0x42,?0xb1,?0xc1,?0x15,?0x52,?0xd1,?0xf0, ????0x24,?0x33,?0x62,?0x72,?0x82,?0x09,?0x0a,?0x16, ????0x17,?0x18,?0x19,?0x1a,?0x25,?0x26,?0x27,?0x28, ????0x29,?0x2a,?0x34,?0x35,?0x36,?0x37,?0x38,?0x39, ????0x3a,?0x43,?0x44,?0x45,?0x46,?0x47,?0x48,?0x49, ????0x4a,?0x53,?0x54,?0x55,?0x56,?0x57,?0x58,?0x59, ????0x5a,?0x63,?0x64,?0x65,?0x66,?0x67,?0x68,?0x69, ????0x6a,?0x73,?0x74,?0x75,?0x76,?0