女人夜夜春高潮爽A∨片传媒_国产精品VIDEOS麻豆_在线精品亚洲一区二区三区_亚洲熟妇无码av

圖像處理
新聞詳情

DIB位圖(Bitmap)的讀取和保存

發布時(shi)間:2021-01-19 13:43:34 最(zui)后更新:2021-01-21 08:43:48 瀏覽次數:3360

設備無關位圖(tu)(Device Independent Bitmap)是可(ke)(ke)以保(bao)存在(zai)磁(ci)盤的(de)位圖(tu)文(wen)件(jian)(jian),可(ke)(ke)以從磁(ci)盤讀取到(dao)內存或(huo)者(zhe)從內存保(bao)存到(dao)磁(ci)盤上。它的(de)文(wen)件(jian)(jian)結(jie)構是標準化的(de),可(ke)(ke)以在(zai)Windows/Linux/Unix等(deng)平臺上顯示相(xiang)同的(de)效果。本文(wen)主要介紹了

1.   如(ru)果將(jiang)位圖文件從(cong)磁盤讀到內(nei)存中

2.   在(zai)內存中對(dui)位(wei)圖文件進行操作后(hou),如何將位(wei)圖保存到(dao)磁盤


1 讀取位圖到內存中

1.1 DIB文件結構

要(yao)將(jiang)位(wei)圖文件(jian)(.bmp)從磁盤(pan)讀取(qu)到內(nei)存,首(shou)先要(yao)了解其(qi)文件(jian)結(jie)構(gou)。DIB的(de)文件(jian)組成(cheng)有以下(xia)4個部分:

1.   文(wen)(wen)件(jian)表頭,主要包含了(le)文(wen)(wen)件(jian)的類型(必(bi)須是BM),文(wen)(wen)件(jian)的大小(xiao)(所占(zhan)用的字節數)和位(wei)圖的像(xiang)素矩陣的便宜(yi)量。

2.   信(xin)息(xi)表(biao)頭,包含(han)了兩部(bu)分(fen)內容(rong):位圖的(de)相關(guan)信(xin)息(xi)(位圖的(de)大小、位深度、位面(mian)數、壓縮和編碼等(deng))和指(zhi)向RGB顏色表(biao)(調色盤)的(de)指(zhi)針(zhen)。

3.   RGB色彩(cai)對照表,也就是調色板,不(bu)一定會有。16位及以上直(zhi)接使(shi)用RGB通道(dao)表示顏(yan)色,一般不(bu)需要(yao)調色板。

4.   位圖(tu)的像(xiang)(xiang)素(su)信息矩陣,表示具(ju)體(ti)的像(xiang)(xiang)素(su)。1,4,8位顏色(se),保存的是調色(se)板(ban)的索引(yin),具(ju)體(ti)的顏色(se)根據索引(yin)在調色(se)板(ban)中查(cha)找;16位及其以(yi)上不(bu)使用(yong)調色(se)板(ban),直接使用(yong)RGB組成像(xiang)(xiang)素(su)顏色(se)。

1.2 在Windows下DIB的內存結構

要將DIB數據讀取到內存,就需要在內存中分配相應的空間。Windows提供了幾種結構體,結構體中的字段對應著DIB文件的各個信息值,具體如下

引用自 //blog.csdn.net/wenzhou1219/article/details/26162869

將DIB讀取到內存只需要將磁盤數據填充到相應到結構體即可。在磁盤上DIB需要連續的結構存儲,在內存中則不需要連續的存儲空間,可以分段將數據讀取到相應的結構體中。
讀(du)取DIB到內(nei)存的具體(ti)步(bu)驟:

1.   將文件頭(tou)信息讀取到(dao)BITMAPFILEHEADER結構(gou)體中。

2.   將位圖(tu)頭信息(xi)讀取到BITMAPINFOHEADER結構體中(zhong)。

3.   如果有(you)調色板,則將其信(xin)息讀取到RGBQUAD中。

4.   讀取(qu)位圖像(xiang)素信息到(dao)像(xiang)素矩(ju)陣中(zhong)。

fp.Read(&bmfileHeader, sizeof(BITMAPFILEHEADER)); // 讀取BMP文(wen)件頭 
...
//讀取文(wen)件(jian)信息(xi)頭
ret = fp.Read(&bmHeader, sizeof(BITMAPINFOHEADER)); 
...
fp.Read(m_dibBits, GetBodySize());  //讀取像(xiang)素信息 

1.3 結構體各字段信(xin)息

BITMAPFILEHEADER

代表(biao)文件(jian)頭信息的(de)結構(gou)體BITMAPFILEHEADER的(de)聲明如下:

typedef struct tagBITMAPFILEHEADER {
        WORD    bfType;
        DWORD   bfSize;
        WORD    bfReserved1;
        WORD    bfReserved2;
        DWORD   bfOffBits;
} BITMAPFILEHEADER  

其中,

·        bfType是文件類型,該字段必須是BM,如果(guo)不(bu)是(shi)則(ze)說(shuo)明該文件不(bu)是(shi)DIB。

·        bfSize是位圖(tu)文件的大小(字節數(shu))

·      ;  bfReserved1和bfReserved2是保留字段

·        bfOffBits 從BITMAPFILEHEADER的(de)起(qi)始位置(zhi)到位圖(tu)像素的(de)字(zi)節偏(pian)移量。

BITMAPINFO

在上面提到,位圖信息和位圖的調色板是存放在同一個(ge)結(jie)構體(ti)中的,該結(jie)構體(ti)就是BITMAPINFO,其聲(sheng)明如下

typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD          bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;

bmiHeader是位圖頭信息
bmiColors是調色板(ban)

BITMAPINFOHEADER

位(wei)圖的頭信(xin)息結(jie)構BITMAPINFOHEADER,該(gai)結(jie)構包(bao)含了DIB的尺寸和顏(yan)色格式等信(xin)息,聲明如下

ypedef struct tagBITMAPINFOHEADER{
        DWORD      biSize;
        LONG       biWidth;
        LONG       biHeight;
        WORD       biPlanes;
        WORD       biBitCount;
        DWORD      biCompression;
        DWORD      biSizeImage;
        LONG       biXPelsPerMeter;
        LONG       biYPelsPerMeter;
        DWORD      biClrUsed;
        DWORD      biClrImportant;
} BITMAPINFOHEADER  

其中,

·        biSize是該結構(gou)體(ti)所(suo)占用(yong)的字節說

·        biWidth DIB的寬(kuan)(以像(xiang)素為單位),如果biCompression是(shi)(shi)BI_JPEG或(huo)者(zhe)BI_PNG,則(ze)biWidth是(shi)(shi)解壓縮后JPEG或(huo)者(zhe)PNG圖像(xiang)的寬(kuan)度(du)。

·        biHeight,DIB的(de)高(以(yi)像素為單位)。

o   如果biHeight是正的(de),則DIB的(de)像(xiang)(xiang)素是按照從(cong)下往上(bottom-up,也就是像(xiang)(xiang)素數組的(de)第一行(xing)保存的(de)實際是DIB的(de)最后一行(xing)像(xiang)(xiang)素值),圖像(xiang)(xiang)源(yuan)點在左(zuo)下角。

o   如果(guo)biHeight是(shi)負的,則DIB的像素是(shi)按照從上往(wang)下(xia)保(bao)存的(up-bottom),而且像素的數據是(shi)不能被壓縮(suo)的其biCompression必須是(shi)BI_RGB或者BI_FIELDS

o   如(ru)果biCompression是BI_JPEG或者BI_PNG,則biHeight是解壓縮后JPEG或者PNG的高

·        biPlanes 目(mu)標設備的(de)平面(mian)數(shu),總(zong)是設為1.

·        biBitCount,每(mei)(mei)個(ge)像素(su)(su)所占用(yong)(yong)的位數。0,表示(shi)JPEG或者(zhe)PNG指定(ding)每(mei)(mei)個(ge)像素(su)(su)所占用(yong)(yong)的位數。還可以是1,4,8,16,24,32。

·      ;  biCompression,數據的壓縮(suo)方(fang)法(fa)(up-down的DIB不能被壓縮(suo)),可(ke)以是以下值:

o   BI_RGB / BI_FIELDS未被壓縮

o   BI_RLE4 / BI_RLE8 使用游程長(chang)度編碼 (RLE,run-length encode)

o   BI_JPEG / BI_PNG 指示該圖像(xiang)是(shi)JPEG或者PNG圖像(xiang)。

·      ;  biSizeImage 圖像的字節數,對(dui)于BI_RGB的DIB其(qi)值為(wei)0.

·        biXPelsPerMeter / biYPelsPerMeter 顯示該DIB的(de)目標(biao)設(she)備所需的(de)分(fen)辨(bian)率(單位是(shi)像(xiang)素每米)

·        biClrUsed DIB實際使(shi)用調色(se)板中的(de)顏(yan)色(se)個數,通(tong)常(chang)為0表(biao)示使(shi)用調色(se)板中的(de)全部顏(yan)色(se)。

·        biClrImportant 顯示DIB所必須(xu)的顏(yan)色(se)個數,通常為(wei)0表示全(quan)部顏(yan)色(se)都(dou)是(shi)必須(xu)的。

詳細的解釋參見 //msdn.microsoft.com/en-us/library/dd183376(v=vs.85).aspx

RGBQUAD

typedef struct tagRGBQUAD {
  BYTE rgbBlue;
  BYTE rgbGreen;
  BYTE rgbRed;
  BYTE rgbReserved;
} RGBQUAD;

注意,其存(cun)儲(chu)順序是BGR。

1.4 DIB的結(jie)構實例(li)

是一幅寬和高都是32的位圖(放大后,可以看到表示像素的一個個方塊),其有16種顏色。下面是該圖像的16進制數據

·        首(shou)先是(shi)文件的(de)頭信(xin)息 BITMAPFILEINFO 共有14個(ge)(ge)字(zi)節(0x00-0x0D),其起始的(de)兩個(ge)(ge)字(zi)節為0x4d42(大端存儲,高位在(zai)前)表示文件類型為BM,最后4個(ge)(ge)字(zi)節 0x0076是(shi)位圖的(de)像(xiang)(xiang)素信(xin)息相對于文件頭的(de)偏移量,也就是(shi)從0x0076為圖像(xiang)(xiang)的(de)像(xiang)(xiang)素信(xin)息。

·        下面是(shi)位圖的頭信(xin)息 BITMAPINFOHEADER共有40個字(zi)(zi)節(jie)(0x0E-0x35),起始的4個字(zi)(zi)節(jie)是(shi)0x0028就是(shi)該(gai)結構(gou)體(ti)的大小,緊接(jie)著的4個字(zi)(zi)節(jie)是(shi)圖像(xiang)的寬0x0020

·        跟著是圖像的(de)調(diao)色(se)板(ban),0x36 - 0x75。調(diao)色(se)板(ban)共有16種(zhong)顏色(se),也就是說(shuo)有調(diao)色(se)板(ban)中有16個RGBQUAD,其大小為16 *4.

·        最后是位(wei)圖的(de)數據 0x76-0x275

1.5 讀取

    CFile fp(dibName, CFile::modeRead | CFile::typeBinary);
    BITMAPFILEHEADER bmfileHeader;
    BITMAPINFOHEADER bmHeader;
    ULONGLONG headpos;
    int paletteSize = 0;
    int ret, cbHeaderSize;
    headpos = fp.GetPosition(); // 獲(huo)取(qu)文件(jian)指針的位置
    ret = fp.Read(&bmfileHeader, sizeof(BITMAPFILEHEADER)); // 讀取BMP文件頭
    if (bmfileHeader.bfType != 0x4d42) //判斷文件(jian)(jian)類型(xing)(xing)標頭是不(bu)是x4d42,表(biao)示該文件(jian)(jian)為BMP類型(xing)(xing)文件(jian)(jian)
    {
        AfxMessageBox(_T("文(wen)件(jian)不(bu)是bmp!"));
        return;
    }
    //讀取(qu)文件信(xin)息(xi)頭(tou)
    ret = fp.Read(&bmHeader, sizeof(BITMAPINFOHEADER));
    // 計算RGBQUAD的大(da)小
    switch (bmHeader.biBitCount)
    {
    case 1:
        paletteSize = 2;
        break;
    case 4:
        paletteSize = 16;
        break;
    case 8:
        paletteSize = 256;
        break;
    }
    // 為BITMAPINFO分配存儲(chu)空間
    cbHeaderSize = sizeof(BITMAPINFOHEADER)+paletteSize * sizeof(RGBQUAD);
    m_dibInfo = (BITMAPINFO*) new char[cbHeaderSize];
    m_dibInfo->bmiHeader = bmHeader;
    if (paletteSize) //是(shi)否有調色板
    {
        ret = fp.Read(&(m_dibInfo->bmiColors[0]), paletteSize * sizeof(RGBQUAD));
        if (ret != int(paletteSize * sizeof(RGBQUAD) ) )
        {
            delete[] m_dibInfo;
            m_dibInfo = NULL;
            return;
        }
    }
    //為(wei)像素數(shu)組分配存儲空間,大(da)小(xiao)由GetBodySize決定
    m_dibBits = (void*) new char[GetBodySize()];
    fp.Seek(headpos + bmfileHeader.bfOffBits, CFile::begin); // 將(jiang)文件指針移動(dong)到DIB像素數組
    ret = fp.Read(m_dibBits, GetBodySize());
    if (ret != int(GetBodySize()))
    {
        delete[] m_dibInfo;
        delete[] m_dibBits;
        m_dibInfo = NULL;
        m_dibBits = NULL;
    }
    fp.Close();  

知(zhi)道了DIB的(de)(de)文件結構后,讀取其(qi)(qi)到內(nei)存(cun)還是(shi)(shi)挺簡(jian)單(dan)的(de)(de),需要注意的(de)(de)是(shi)(shi)DIB的(de)(de)像(xiang)素數組(zu)的(de)(de)大小(xiao)。由于DIB的(de)(de)寬度需要時4的(de)(de)倍(bei)數,不是(shi)(shi)的(de)(de)話需要填充(chong)0將其(qi)(qi)湊成4的(de)(de)倍(bei)數,所以其(qi)(qi)像(xiang)素數組(zu)的(de)(de)大小(xiao)不能簡(jian)單(dan)的(de)(de)width * height * biBitCount / 8,其(qi)(qi)中biBitCount是(shi)(shi)每個像(xiang)素占用的(de)(de)位數。其(qi)(qi)具體的(de)(de)計(ji)算方法如下

1.    首先計算一行所占用的字節數bytesPerLine
bytesPerLine =((m_dibInfo->bmiHeader.biWidth * m_dibInfo->bmiHeader.biBitCount + 31) /32 ) * 4

2.    將bytesPerLine乘以圖像的高
bytesPerLine *m_dibInfo->bmiHeader.biHeight

1.6 總結

本文主(zhu)要對(dui)DIB的文件結(jie)構以及(ji)其(qi)對(dui)應的內存中(zhong)的結(jie)構體做了一個(ge)總結(jie),并對(dui)一個(ge)具(ju)體的DIB16進制數據(ju)結(jie)構進行分析(xi),最后(hou)實現了如何將一個(ge)DIB數據(ju)讀取到內存中(zhong)。

一直(zhi)對(dui)(dui)位(wei)圖(tu)結構不是很了(le)解,趁著在(zai)公(gong)司實習沒有具體的(de)工作安排,對(dui)(dui)DIB的(de)結構作了(le)個總結。至于如(ru)何(he)將處(chu)理后的(de)位(wei)圖(tu)數據寫(xie)回磁盤文(wen)件,在(zai)知道(dao)位(wei)圖(tu)結構的(de)情況下(xia),只需要填充相應的(de)結構字段(duan)就(jiu)行了(le),需要注意的(de)還(huan)是位(wei)圖(tu)的(de)寬需要是4的(de)倍數,不是的(de)話(hua)要用0補齊。

在線客(ke)服
客服電話
  • 0755-23712116
  • 13310869691