數據壓縮實驗二 圖像文件的讀寫和轉換(bmp轉yuv)

一、實驗原理

圖像存儲時一般由兩部分組成:圖像說明部分和圖 像數據部分
圖像說明部分:圖像的格式、深度、高度、寬度、調色板、 壓縮方法等
圖像數據部分:描述圖像每個像素的數據

1.BMP圖像文件格式

位圖文件(Bitmap-File,BMP)格式是Windows採 用的圖像文件存儲格式,在Windows環境下運行的 所有圖像處理軟件都支持這種格式。BMP位圖文件 默認的文件擴展名是bmp或者dib。

BMP文件大體上分爲四個部分:

位圖文件頭BITMAPFILEHEADER
位圖信息頭BITMAPINFOHEADER
調色板Palette
實際的位圖數據ImageData

對於一種文件的格式,C語言中往往以結構體的方式描述,因此注意工程中的結構體是十分重要的。
(1)位圖頭文件數據結構

typedef struct tagBITMAPFILEHEADER 
{
    WORD bfType; /* 說明文件的類型 */  
    DWORD bfSize; /* 說明文件的大小,用字節爲單位 注意字節序*/  
    WORD bfReserved1; /* 保留,設置爲0 */  
    WORD bfReserved2; /* 保留,設置爲0 */  
    DWORD bfOffBits; /* 說明從BITMAPFILEHEADER結構開始到實際的圖像數據之間的字節偏移量 */  
} BITMAPFILEHEADER;

(2)位圖信息數據結構


typedef struct tagBITMAPINFOHEADER
{
    DWORD biSize; /* 說明結構體所需字節數 */
    LONG biWidth; /* 以像素爲單位說明圖像的寬度 */
    LONG biHeight; /* 以像素爲單位說明圖像的高度 */
    WORD biPlanes; /* 說明位面數,必須爲1 */
    WORD biBitCount; /* 說明位數/像素,1、2、4、8、24 */
    DWORD biCompression; /* 說明圖像是否壓縮及壓縮類型BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS */
    DWORD biSizeImage; /* 以字節爲單位說明圖像大小,必須是4的整數倍*/
    LONG biXPelsPerMeter; /*目標設備的水平分辨率,像素/米 */
    LONG biYPelsPerMeter; /*目標設備的垂直分辨率,像素/米 */
    DWORD biClrUsed; /* 說明圖像實際用到的顏色數,如果爲0,則顏色數爲2的biBitCount次方 */
    DWORD biClrImportant; /*說明對圖像顯示有重要影響的顏色索引的數目,如果是0,表示都重要。*/
} BITMAPINFOHEADER;

(3)調色板
調色板實際上是一個數組,它所包含的元素與位圖 所具有的顏色數相同,決定於biClrUsed和biBitCount字 段。數組中每個元素的類型是一個RGBQUAD結構。真 彩色無調色板部分。

typedef struct tagRGBQUAD
{
    BYTE rgbBlue; /*指定藍色分量*/
    BYTE rgbGreen; /*指定綠色分量*/
    BYTE rgbRed; /*指定紅色分量*/
    BYTE rgbReserved; /*保留,指定爲0*/
} RGBQUAD;

(4)圖像數據字節陣列:即位圖數據
緊跟在調色板之後的是圖像數據字節陣列。對於用到調 色板的位圖,圖象數據就是該象素顏色在調色板中的索引值 (邏輯色)。對於真彩色圖,圖象數據就是實際的R、G、B 值。

2.需要注意的地方

(1)DWORD 對齊
圖像的每一掃描行由表示圖像像素的連續的字節組成,每一行的字節數取決於圖像的顏色數目和用像素表示的圖像寬
度。規定每一掃描行的字節數必需是4的整倍數,也就是DWORD對齊的。寫入位圖文件數據時,如果圖像每行像素字節總數[寬 X biBiCount % 8 != 0 ],系統會自動在每行最後填充若干0值使滿足整數字節,接着,如果[每行像素字節數 % 4 != 0 ],系統會自動在每行最後填充若干字節0值使滿足DWORD對齊。所以我們對位圖加載處理時要注意判斷每行數據是否有0值填充,若有0值填充則從位圖中讀取數據的過程中要注意指針偏移量和即時跳轉。

(2)自下而上掃描
掃描行是由底向上存儲的,這就是說,陣列中的第一個字節表示位圖左下角的像素,而最後一個字節表示位圖右上角的像素。(只針對於倒向DIB,如果是正向DIB,則掃描行是由頂向下存儲)

(3)字節序
計算機系統存儲數據採用的字節序有兩種:小尾字節序(Little Endian)和大尾字節序(Big Endian)。以Intel處理器爲代表大多數採用小端字節序,”低位在前高位在後“既地址低位存儲值的低位,地址高位存儲值的高位;以Motorola處理器爲代表大多數使用大端字節序,”高位在前低位在後“即地址低位存儲值的高位,地址高位存儲值的低位。BMP文件中僅除了文件頭中文件類型WORD bfType爲大端字節序,剩餘結構體內的定義均是小端字節序。

(4)掩碼組
調色板信息中指示了RGB比特位的掩碼組信息。因爲圖像深度可選爲1、4、8、16、24、32bit,所以不同深度的RGB比特位自然不同。
以bmp位圖中使用16bit爲例,位運算的圖示:
這裏寫圖片描述
若讀入的BMP位圖的biBiCount爲8bit或更小,類似的需要位的移位、與操作。
再以2bit圖像舉例,其數據塊中的第一個字節,對應着第一個像素的索引值爲:b’xx zz zz zz,其中只有頭兩位包含該像素的索引信息,而後六位爲其他像素的索引信息。這時候需要與b’11 00 00 00=0xC0相與,再進行6位右移,得到b’00 00 00 xx=index,這便是其對應的索引值,代入pRGB[index]獲得其對應的RGB分量值。
當處理像素是第二個像素是,其對應的索引值應爲該字節中的第五第六位,即b’zz xx zz zz,這時候掩碼值也相應跟着位移,遂引入turn–掩碼位移變量,turn可用作循環判斷用,當turn爲零時——說明該字節中所有像素信息已讀取完,可以結束循環,進行下一個字節的讀取。
同時,應注意到右移的位數也發生了變換,引入shiftcnt變量,用於不同像素點需位移的長度。每進行一次像素數據讀取後,shiftcnt++,因爲下一個像素(不是該字節最後一個像素時)需要位移的位數減少了shift*biBitCount個。

二、實驗流程

(1)初始化:打開文件,定義變量建立緩衝區
(2)解析BMP文件,抽取或生成RGB數據寫入緩衝區
(3)調用RGB2YUV函數進行數據轉換
(4)寫入YUV文件,關閉文件,釋放緩衝區
這裏寫圖片描述

三、實驗具體算法代碼

1.BMP2YUV.h

#ifndef BMP2YUV_H_
#define BMP2YUV_H_

//define mask struct
typedef struct bit32Mask
{
    unsigned int rgbRed;
    unsigned int rgbGreen;
    unsigned int rgbBlue;   
    unsigned int reserved;
}Mas32;
typedef struct bit16Mask
{
    unsigned int rgbRed;
    unsigned int rgbGreen;
    unsigned int rgbBlue;
}Mas16;

int BMP2RGB32bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask);
int BMP2RGB24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf);
int BMP2RGB16bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf,void *mask);
int BMP2RGBNOT24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *pRGB);
int RGB2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip);
void InitLookupTable();
void adjust(unsigned char *b, unsigned char *g, unsigned char *r, unsigned char *y, unsigned char *u, unsigned char  *v);
#endif

2.main.c


#include <stdio.h>
#include <stdlib.h>
#include <windows.h> 
#include <math.h> 
#include "bmp2yuv.h"

#define u_int8_t    unsigned __int8
#define u_int       unsigned __int32
#define u_int32_t   unsigned __int32

int main(int argc,char **argv)
{
    int count;
    BITMAPFILEHEADER File_header;
    BITMAPINFOHEADER Info_header;
    RGBQUAD *pRGB = NULL;
    FILE* bmp = NULL;
    FILE* yuvFile = NULL;   
    Mas16 *mask16 = NULL;
    Mas32 *mask32 = NULL;

    u_int8_t* yBuf = NULL;
    u_int8_t* uBuf = NULL;
    u_int8_t* vBuf = NULL;
    u_int8_t* rgbBuf = NULL;
    u_int8_t* bmpBuf = NULL;
    u_int8_t* mask = NULL;
    u_int frameWidth;       /* --width=<uint> */
    u_int frameHeight;
    u_int bitcount;
    u_int py;
    u_int m;
    u_int8_t i;
    int sum = 0;

    char bmpf[][50] = { "park.bmp", "tree.bmp", "girlstwo.bmp", "02.bmp", "bea.bmp", "street.bmp" };
    char yuvname[50] = "CometoYUV.yuv";
    FILE *yuv=NULL;
    int framenumber;

    /* build the RAW file */
    fopen_s(&yuv, yuvname, "wb+");
    if (yuv == NULL)
    {
        printf("Fail to Build yuv file\n");
        exit(0);
    }
    else
    {
        printf("The output rgb file is %s\n", yuvname);
        printf("\n");
        printf("-------------------------------------------------------------------------\n");
    }


    for (i = 0; i<6; i++)
    {

        count = 0;
        framenumber = atoi(argv[i + 1]);
        //open the bmp file
        fopen_s(&bmp, bmpf[i], "rb");
        if (!bmp)
        {
            printf("cannot find the specific file %s:\n", bmpf[i]);
            exit(0);
        }
        else
        {
            printf("The input bmp file:   %s\n", bmpf[i]);
        }
        if (!framenumber)
        {
            printf("\n寫入幀數:0\n");
            continue;
        }
        else
        {
            if (fread(&File_header, sizeof(BITMAPFILEHEADER), 1, bmp) != 1)
            {
                printf("read file header error!");
                exit(0);
            }
            if (File_header.bfType != 0x4D42)
            {
                printf("Not bmp file!");
                exit(0);
            }
            //printf("this is a 0x%04X:\n", File_header.bfType);    
            if (fread(&Info_header, sizeof(BITMAPINFOHEADER), 1, bmp) != 1)
            {
                printf("read info header error!");
                exit(0);
            }
            //  end read header
            frameWidth = Info_header.biWidth;           /* --width=<uint> */
            frameHeight = Info_header.biHeight;
            py = File_header.bfOffBits;
            bitcount = Info_header.biBitCount;
            /* get an output buffer for a frame */
            if ((frameWidth*bitcount % 8 == 0) && (frameWidth*bitcount / 8 % 4 == 0))//DWORD 對齊
            {
                yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
                uBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);
                vBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);

                /* get an input buffer for a frame */
                bmpBuf = (u_int8_t*)malloc(frameWidth * frameHeight * bitcount / 8);

                /* get an output buffer for a frame */
                rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);               

                if (rgbBuf == NULL || yBuf == NULL || uBuf == NULL || vBuf == NULL || bmpBuf == NULL)
                {
                    printf("no enought memory\n");
                    exit(1);
                }

                ////////////////////////////////BMP 2 RGB
                while (framenumber)
                {
                    fseek(bmp, py, SEEK_SET);
                    if (!fread(bmpBuf, 1, frameWidth * frameHeight * bitcount / 8, bmp))
                    {
                        printf("the image has problems!");
                        return 0;
                    }
                    if (bitcount == 32)
                    {
                        if (Info_header.biCompression==0)
                        { 
                            if (BMP2RGB32bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf,0))
                            {
                                printf("32bit BMP2RGB program runs error!");
                                return 0;
                            }                       
                        }
                        else if (Info_header.biCompression == 3)
                        {
                            //取掩碼組
                            m = 4*4;
                            mask32 = (Mas32*)malloc(sizeof(Mas32));
                            fseek(bmp, sizeof(BITMAPFILEHEADER) + Info_header.biSize - m, SEEK_SET);
                            fread(mask32, sizeof(Mas32),1, bmp);
                            if (BMP2RGB32bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, mask32))
                            {
                                printf("32bit BMP2RGB program runs error!");
                                return 0;
                            }
                        }
                    }
                    else if (bitcount == 24)
                    {//真彩位圖
                        if (BMP2RGB24bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf))
                        {
                            printf("24bit BMP2RGB program runs error!");
                            return 0;
                        }
                    }
                    else if (bitcount == 16)
                    {                       
                        //16bit BMP RGB比特位根據biCompression確定
                        if (Info_header.biCompression == 0)//555
                        {
                            if (BMP2RGB16bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, 0))
                            {
                                printf("16bit BMP2RGB program runs error!");
                                return 0;
                            }
                        }
                        else if (Info_header.biCompression == 3)
                        {
                            //取掩碼組
                            m = 4 * 3;
                            mask16 = (Mas16*)malloc(sizeof(Mas16));
                            fseek(bmp, py-m, SEEK_SET);
                            fread(mask16, 1, m, bmp);                           
                            if (BMP2RGB16bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, mask16))
                            {
                                printf("16bit BMP2RGB program runs error!");
                                return 0;
                            }
                        }                       
                    }
                    else
                    {                       
                        if ((py - sizeof(BITMAPFILEHEADER) - Info_header.biSize) == sizeof(RGBQUAD)*pow(2, (double)bitcount))
                        {//1、2、4、8 bit 有調色板部分
                            m = (unsigned int)pow(2, (double)bitcount);
                            pRGB = (RGBQUAD *)malloc(sizeof(RGBQUAD)*m);
                            fseek(bmp, sizeof(BITMAPFILEHEADER) + Info_header.biSize, SEEK_SET);
                            fread(pRGB, sizeof(RGBQUAD), m, bmp);
                            if (BMP2RGBNOT24bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, pRGB))
                            {
                                printf("BMP 2 RGB program runs error!");
                                return 0;
                            }
                        }                       
                    }
                    /////////////////////////////RGB2YUV
                    if (RGB2YUV(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf, 0/*flip=0*/))//bmp圖像格式從最後一行起逐行掃描
                    {
                        printf("RGB2YUV program runs error!");
                        return 0;
                    }
                    fwrite(yBuf, 1, frameWidth * frameHeight, yuv);
                    fwrite(uBuf, 1, (frameWidth * frameHeight) / 4, yuv);
                    fwrite(vBuf, 1, (frameWidth * frameHeight) / 4, yuv);

                    printf("\r...%d", ++count);
                    framenumber--;
                }
                printf("\n寫入幀數:%u   %ux%u(%d bit)\n", count, frameWidth, frameHeight, bitcount);
                sum += count;
                printf("\n");
                printf("\n");
            }
        }               
    }
    printf("%d幀YUV寫入成功!\n",sum);

    /* cleanup */
    fclose(bmp);
    fclose(yuv);
    //free the memory   
    if (yBuf)   { free(yBuf); }
    if (uBuf)   { free(uBuf); }
    if (vBuf)   { free(vBuf); }
    if (rgbBuf) { free(rgbBuf); }
    if (bmpBuf) { free(bmpBuf); }
    if (pRGB)   { free(pRGB); }
    if (mask16) { free(mask16); }
    if (mask32)  { free(mask32); }
    return 0;
}

3.BMP2RGB.c

#include "stdlib.h"
#include "bmp2yuv.h"
#include <windows.h> 
#include <math.h> 

int BMP2RGB32bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask)
{
    long i;
    unsigned char *bmp, *rgb;
    Mas32 *mas;
    long size = x_dim*y_dim;
    bmp = (unsigned char *)bmpbuf;
    rgb = (unsigned char *)rgbbuf;
    mas = (Mas32 *)mask;

    if (mask == NULL)
    {
        for (i = 0; i < size; i++)
        {
            *(rgb + 0) = *(bmp + 0);
            *(rgb + 1) = *(bmp + 1);
            *(rgb + 2) = *(bmp + 2);
            rgb += 3;
            bmp += 4;
        }
        return 0;
    }
    else
    {//根據掩碼確定RGB比特位
        int Gkey, Bkey, Rkey;
        if (mas->rgbGreen == 0)
            Gkey= 0;
        else if (mas->rgbGreen == 0xFF000000)
            Gkey = 3;
        else if (mas->rgbGreen == 0xFF0000)
            Gkey = 2;
        else if (mas->rgbGreen == 0xFF00)
            Gkey = 1;
        else
            return 1;

        if (mas->rgbBlue == 0)
           Bkey = 0;
        else if (mas->rgbBlue == 0xFF000000)
            Bkey = 3;
        else if (mas->rgbBlue == 0xFF0000)
            Bkey = 2;
        else if (mas->rgbBlue == 0xFF00)
            Bkey = 1;
        else
            return 1;

        if (mas->rgbRed == 0)
            Rkey = 0;
        else if (mas->rgbRed == 0xFF000000)
            Rkey = 3;
        else if (mas->rgbRed == 0xFF0000)
            Rkey = 2;
        else if (mas->rgbRed == 0xFF00)
            Rkey = 1;
        else
            return 1;

        for (i = 0; i < size; i++)
        {
            *(rgb + 0) = *(bmp + Bkey);
            *(rgb + 1) = *(bmp + Gkey);
            *(rgb + 2) = *(bmp + Rkey);
            rgb += 3;
            bmp += 4;
        }
        return 0;
    }

}

int BMP2RGB24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf)
{
    long i;
    unsigned char *rgb;// , *raw;
    unsigned char *bmp;
    long size = x_dim*y_dim;
    rgb = (unsigned char *)rgbbuf;
    bmp = (unsigned char *)bmpbuf;
    for (i = 0; i < size*3; i++)
    {
        *(rgb + i) = *(bmp + i);
    }
    return 0;
}
int BMP2RGB16bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask)
{
    long loop;
    unsigned char *Data, *rgbDataOut;
    long size = x_dim*y_dim*bitcount / 8;
    Data = (unsigned char*)bmpbuf;
    rgbDataOut = (unsigned char*)rgbbuf;
    Mas16 *mas;
    mas = (Mas16 *)mask;

    if (mask == NULL)
    {
        for (loop = 0; loop < size; loop += 2)
        {
            *rgbDataOut = (*(Data + loop) & 0x1F) << 3;
            *(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 2) + ((*(Data + loop + 1) & 0x03) << 6);
            *(rgbDataOut + 2) = (*(Data + loop + 1) & 0x7C) << 1;
            rgbDataOut += 3;
        }
    }
    else//555 OR 565決定於rgbGreen的比特位
    {
        if (mas->rgbGreen == 0x07E0)
        {
            for (loop = 0; loop < size; loop += 2)
            {
                *rgbDataOut = (*(Data + loop) & 0x1F) << 3;
                *(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 3) + ((*(Data + loop + 1) & 0x07) << 5);
                *(rgbDataOut + 2) = (*(Data + loop + 1) & 0xF8);
                rgbDataOut += 3;
            }
        }
        else
        {
            for (loop = 0; loop < size; loop += 2)
            {
                *rgbDataOut = (*(Data + loop) & 0x1F) << 3;
                *(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 2) + ((*(Data + loop + 1) & 0x03) << 6);
                *(rgbDataOut + 2) = (*(Data + loop + 1) & 0x7C) << 1;
                rgbDataOut += 3;
            }
        }
    }
    return 0;
}
int BMP2RGBNOT24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *ppRGB)//1\4\8 bit BMP
{
    unsigned char *rgb;
    unsigned char *bmp;
    unsigned char index;

    bmp = (unsigned char *)bmpbuf;
    rgb = (unsigned char *)rgbbuf;

    int shiftCnt;
    unsigned char mask;

    long loop = 0;
    unsigned char *Data, *rgbDataOut;
    RGBQUAD* p;

    long size = x_dim*y_dim*bitcount/8;
    Data = (unsigned char*)bmpbuf;
    rgbDataOut = (unsigned char*)rgbbuf;
    p = (RGBQUAD*)ppRGB;
    for (loop = 0; loop<size; loop++)
    {
        shiftCnt = 1;
        mask = (unsigned char)pow(2, (double)bitcount) - 1;
        mask = mask << (8-bitcount);
        while (mask)
        {
            //索引號的確定
            index = (mask == 0xFF) ? *(Data + loop) : (*(Data + loop) & mask) >> (8 - shiftCnt * bitcount);
            *rgbDataOut = (p + index)->rgbBlue;
            *(rgbDataOut + 1) = (p + index)->rgbGreen;
            *(rgbDataOut + 2) = (p + index)->rgbRed;
            if (bitcount == 8)
                mask = 0;
            else
                mask >>= bitcount;
            rgbDataOut += 3;
            shiftCnt++;
        }
    }
    return 0;
}

4.RGB2YUV.c

#include "stdlib.h"
#include "bmp2yuv.h"

static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];

int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
{
    static int init_done = 0;

    long i, j, size;
    unsigned char *r, *g, *b;
    unsigned char *y, *u, *v;
    unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
    unsigned char *y_buffer, *u_buffer, *v_buffer;
    unsigned char *sub_u_buf, *sub_v_buf;

    if (init_done == 0)
    {
        InitLookupTable();
        init_done = 1;
    }

    // check to see if x_dim and y_dim are divisible by 2
    if ((x_dim % 2) || (y_dim % 2)) return 1;
    size = x_dim * y_dim;

    // allocate memory
    y_buffer = (unsigned char *)y_out;
    sub_u_buf = (unsigned char *)u_out;
    sub_v_buf = (unsigned char *)v_out;
    u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
    v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
    if (!(u_buffer && v_buffer))
    {
        if (u_buffer) free(u_buffer);
        if (v_buffer) free(v_buffer);
        return 2;
    }

    b = (unsigned char *)bmp;
    y = y_buffer;
    u = u_buffer;
    v = v_buffer;

    // convert RGB to YUV
    if (!flip) 
    {
        for (j = 0; j < y_dim; j ++)
        {
            y = y_buffer + (y_dim - j - 1) * x_dim;
            u = u_buffer + (y_dim - j - 1) * x_dim;
            v = v_buffer + (y_dim - j - 1) * x_dim;

            for (i = 0; i < x_dim; i ++) {
                g = b + 1;
                r = b + 2;
                adjust(b, g, r, y, u, v);
                b += 3;
                y ++;
                u ++;
                v ++;
            }
        }
    } else {
        for (i = 0; i < size; i++)
        {
            g = b + 1;
            r = b + 2;          
            adjust(b, g, r, y, u,v);
            b += 3;
            y ++;
            u ++;
            v ++;
        }
    }
    // subsample UV
    for (j = 0; j < y_dim/2; j ++)
    {
        psu = sub_u_buf + j * x_dim / 2;
        psv = sub_v_buf + j * x_dim / 2;
        pu1 = u_buffer + 2 * j * x_dim;
        pu2 = u_buffer + (2 * j + 1) * x_dim;
        pv1 = v_buffer + 2 * j * x_dim;
        pv2 = v_buffer + (2 * j + 1) * x_dim;
        for (i = 0; i < x_dim/2; i ++)
        {
            *psu = (*pu1 + *(pu1+1) + *pu2 + *(pu2+1)) / 4;
            *psv = (*pv1 + *(pv1+1) + *pv2 + *(pv2+1)) / 4;
            psu ++;
            psv ++;
            pu1 += 2;
            pu2 += 2;
            pv1 += 2;
            pv2 += 2;
        }
    }
    free(u_buffer);
    free(v_buffer);
    return 0;
}

void InitLookupTable()
{
    int i;

    for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;
    for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;
    for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;
    for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;
    for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;
    for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;
    for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
}

void adjust(unsigned char *b, unsigned char *g, unsigned char *r, unsigned char *y, unsigned char *u, unsigned char  *v)
{
    float temp = 0;
    temp = (float)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
    temp = temp>235 ? 235 : temp;
    temp = temp<16 ? 16 : temp;
    *y = (unsigned char)temp;

    temp = (float)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
    temp = temp>240 ? 240 : temp;
    temp = temp<16 ? 16 : temp;
    *u = (unsigned char)temp;

    temp = (float)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
    temp = temp>240 ? 240 : temp;
    temp = temp<16 ? 16 : temp;
    *v = (unsigned char)temp;
}

四、實驗結果

由命令行設置每幅圖片播放幀數:4幅圖片,每幅轉成50幀yuv序列
這裏寫圖片描述
執行結果如圖所示:
這裏寫圖片描述
不同比特位的bmp位圖的對比:

biBitCount 原BMP圖像 生成YUV序列中的一幀
24bit right-aligned $1600
8bit centered $12
4bit are neat $1
1bit are neat $1

五、實驗總結

本次實驗中應重點掌握的是文件格式的概念、字節序、緩衝區分配、結構體操作、倒序讀寫文件、函數定義等操作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章