一:實驗基本原理
yuv轉
rgb格式轉換公式:
r=y+1.4020*(
v-128)
g=y-0.3441*(u-128)-0.7141*(v-128)
b=y+1.7720*(u-128)
分析:
由rgb到
yuv格式的轉換公式: y=
0.2990r+0.5870g+0.1140b
r-y=
0.7010r-0.5870g-0.1140b
b-y=
-0.2990r-0.5870g+0.8860b
為了使色差訊號的動態範圍控制在0.5之間,需要進行歸一化,對色差訊號引入壓縮
係數。b-y和
r-y分別乘以歸一化係數
0.713
和0.564
進行歸一化後得到色度訊號u和
v: u=
-0.1684r-0.3316g+0.5b v=
0.5r-0.4187g-0.0813b
對分量訊號進行8位元量化時,共分為
256個等間隔的量化級。為了防止訊號
變動造成過載,在256級上端留
20級,下端留
16級作為訊號超越動態範圍的保護帶,即色差訊號零電平對應碼電平
128,則由
rgb到
yuv轉換後的實際色差訊號
u』和v』:
u』=u+128
v』=v+128
由上述進行逆向運算得到yuv到
rgb的轉換公式。
二:實驗流程分析
程式設計流程包括下面幾步驟:(基於vc++6.0開發平台)
1,建立乙個工程檔案;
2,建立2個
cpp檔案(
main.c
和yuv2rgb.c
)和乙個標頭檔案(
yuv2rgb.h);
其中標頭檔案放函式的宣告(這裡包括yuv2rgb函式和查詢表函式
initlookuptable
),yuv2rgb
檔案中放兩函式的具體實現。
3,命令列引數的設定:工程
->
設定->
除錯->
設定工作目錄和程式變數;
這裡注意工作目錄設定為需要讀取的yuv檔案所在目錄。
4,主函式中變數的宣告和初始化;
5,主函式讀取
yuv檔案並為變數指標分配記憶體空間;
6,呼叫
yuv2rgb
函式;
7,將轉換後的資料寫入
rgb檔案;
8,關閉檔案,釋放緩衝區;
三:關鍵**及其分析:
/*內部變數初始化 */
char* yuvfilename = null;
char* rgbfilename = null;
file* yuvfile = null;
file* rgbfile = null;
u_int8_t* rgbbuf = null;
u_int8_t* ybuf = null;
u_int8_t* ubuf = null;
u_int8_t* vbuf = null;
u_int32_t videoframeswritten = 0;
yuvfilename = argv[1];
rgbfilename = argv[2];
framewidth = atoi(argv[3]);
frameheight = atoi(argv[4]);
因為yuv是按
4:2:0
的取樣格式由
rgb下取樣得來的,因此u,
v的資料量只有
y的四分之一。
/* 分別為yuv開闢記憶體緩衝區 */
ybuf = (u_int8_t*)malloc(framewidth * frameheight);
ubuf = (u_int8_t*)malloc((framewidth * frameheight) / 4);
vbuf = (u_int8_t*)malloc((framewidth * frameheight) / 4);
/* 為輸出的rgb檔案開闢乙個緩衝區 */
rgbbuf = (u_int8_t*)malloc(framewidth * frameheight * 3);
if (rgbbuf == null || ybuf == null || ubuf == null || vbuf == null)
/* 從檔案中讀取資料到三個緩衝區中,並呼叫yuv2rgb轉換函式 */
while (fread(ybuf, 1, framewidth * frameheight , yuvfile)&&fread(ubuf, 1, (unsigned int)(framewidth * frameheight * 0.25), yuvfile)
&&fread(vbuf, 1, (unsigned int)(framewidth * frameheight * 0.25), yuvfile))
/*將緩衝區的資料寫入rgb檔案*/
fwrite(rgbbuf, 1, framewidth * frameheight*3, rgbfile);
printf("\r...%d", ++videoframeswritten);
} printf("\n%u %ux%u video frames written\n",
videoframeswritten, framewidth, frameheight);
/* 釋放緩衝區並關閉檔案 */
free(ybuf);
free(ubuf);
free(vbuf);
fclose(yuvfile);
fclose(rgbfile);
return(0);
}
/*查詢表函式的實現*/
void initlookuptable()
/*yuv2rgb函式的具體實現*/
int yuv2rgb (int x_dim, int y_dim, void *bmpy,void *bmpu,void *bmpv, void *rgb_out, int flip)
if ((x_dim % 2) || (y_dim % 2)) return 1;
size = x_dim * y_dim;
// 分配記憶體
rgb_buffer = (unsigned char *)rgb_out;
if (!rgb_buffer)
y = (unsigned char *)bmpy;
u = (unsigned char *)bmpu;
v = (unsigned char *)bmpv;
// 關鍵:下取樣
if (!flip) else
u++;
v++;}}
else if(j%2==1)
u++;
v++;}}
}}return 0;
}
四:實驗結果及其分析:
例項檔案對比:
出現的錯誤以及除錯:
錯誤1:影象只出一半;
出錯原因:在進行上取樣的**中,每次迴圈j值誤寫為
j+=2
,導致最後行數隻寫入一半,下半部分沒有影象。
除錯:將迴圈體中的j改為
j++。
錯誤2:影象中藍天變為「紅天」;
出錯原因:rgb在檔案中是以
bgr的順序儲存的,在進行公式帶入時,誤將
r的值賦給
b,誤將
b的值賦給r。
除錯:將賦值公式調換。
錯誤3:影象部分暗處出現彩色噪點
五:結論
可以通過資料上取樣的方法將yuv格式的檔案轉化為
rgb格式,且不會產生較大失真。
資料壓縮實驗 TGA檔案轉YUV檔案
實驗內容 將tga影象檔案轉化為yuv檔案 tga檔案頭有5個字段,共18個位元組 typedef struct tgafileheader tgafileheader tgaheader tga file.read char tgaheader,sizeof tgafileheader int p...
資料壓縮實驗報告2 bmp轉yuv
1 bmp檔案格式 bmp bitmap 是windows作業系統中的標準影象檔案格式,可分為裝置相關位圖 ddb 和裝置無關位圖 dib 使用十分廣泛。它採用位對映存貯格式,除了影象深度可選外,絕大多數無壓縮,因此所佔空間很大。bmp檔案的影象深度可選1bit,4bit,8bit,16bit及24...
資料壓縮實驗報告2 TGA轉YUV
寫在前面 由於大二上學習c 時沒有進行充分的練習,這次的實驗先是自己想了很久但是無果,最後只能參考同學的 看不懂的地方和同學討論並逐漸理解。感覺自己的情況就是知道大概的思路方法,但是不知道如何用 實現。在沒有參考的前提下沒法自己寫出完整的 還是需要多思考多練習。pga struct.h 用來建立pg...