1. 程式人生 > >BMP影象的結構及讀寫和灰度化

BMP影象的結構及讀寫和灰度化

1.文件目的

本文件主要給出24位真彩BMP影象的結構、讀寫和灰度化方法。

2.一般BMP影象的結構

一般的bmp檔案的結結構主要包括檔案頭,BMP資訊頭,調色盤,點陣圖資料內容

(1)BMP檔案頭(14位元組) ,檔案的第0位元組到第13位元組為BMP影象的檔案頭。BMP檔案頭資料結構含有BMP檔案的型別、檔案大小和點陣圖起始位置等資訊。 

  其結構定義如下: 

  typedef struct tagBITMAPFILEHEADER 

  { 

  WORD bfType; // 點陣圖檔案的型別,必須為BM(0-1位元組) 

  DWORD bfSize; // 整個點陣圖檔案的大小,以位元組為單位(2-5位元組) 

  WORD bfReserved1; // 點陣圖檔案保留字,必須為0(6-7位元組) 

  WORD bfReserved2; // 點陣圖檔案保留字,必須為0(8-9位元組) 

  DWORD bfOffBits; // 點陣圖資料的起始位置,以相對於點陣圖(10-13位元組) 

  // 檔案頭的偏移量表示,以位元組為單位 

  } BITMAPFILEHEADER;

(2) BMP資訊頭

點陣圖資訊頭(40位元組),檔案的第14個位元組到第53個位元組為BMP影象的資訊頭,點陣圖資訊頭資料用於說明點陣圖的尺寸等資訊。 

  typedef struct tagBITMAPINFOHEADER{ 

  DWORD biSize; // 本結構所佔用位元組數(14-17位元組) 

  LONG biWidth; // 點陣圖的寬度,以畫素為單位(18-21位元組) 

  LONG biHeight; // 點陣圖的高度,以畫素為單位(22-25位元組) 

  WORD biPlanes; // 目標裝置的級別,必須為1(26-27位元組) 

  WORD biBitCount;// 每個畫素所需的位數,必須是1(雙色), 4(16色),8(256色)或24(真彩色)之一(28-29位元組)

  DWORD biCompression; // 點陣圖壓縮型別,必須是 0(不壓縮), 1(BI_RLE8壓縮型別)或2(BI_RLE4壓縮型別)之一(30-33位元組)

  DWORD biSizeImage; // 點陣圖資料部分的大小,以位元組為單位(34-37位元組) 

  LONG biXPelsPerMeter; // 點陣圖水平解析度,每米畫素數(38-41位元組) 

  LONG biYPelsPerMeter; // 點陣圖垂直解析度,每米畫素數(42-45位元組) 

  DWORD biClrUsed;// 點陣圖實際使用的顏色表中的顏色數(46-49位元組) 

  DWORD biClrImportant;// 點陣圖顯示過程中重要的顏色數(50-53位元組) 

  } BITMAPINFOHEADER;

(3) 調色盤

調色盤用於說明點陣圖中的顏色,它有若干個表項,每一個表項是一個RGBQUAD型別的結構,定義一種顏色。RGBQUAD結構的定義如下: 

  typedef struct tagRGBQUAD { 

  BYTE rgbBlue;    // 藍色的亮度(值範圍為0-255) 

  BYTE rgbGreen;   // 綠色的亮度(值範圍為0-255) 

  BYTE rgbRed;     // 紅色的亮度(值範圍為0-255) 

  BYTE rgbReserved;// 保留,必須為0 

  } RGBQUAD;

調色盤中RGBQUAD結構資料的個數有biBitCount來確定: 

當biBitCount=1,4,8時,分別有2,16,256個表項; 

當biBitCount=24時,該BMP影象就是24Bit真彩圖,沒有調色盤項。

  (4):點陣圖資料內容 

點陣圖資料記錄了點陣圖的每一個畫素值,記錄順序是在掃描行內是從左到右,掃描行之間是從下到上。點陣圖的一個畫素值所佔的位元組數由biBitCount來確定:

當biBitCount=1時,8個畫素佔1個位元組; 

  當biBitCount=4時,2個畫素佔1個位元組; 

  當biBitCount=8時,1個畫素佔1個位元組; 

當biBitCount=24時,1個畫素佔3個位元組;

Windows規定一個掃描行所佔的位元組數必須是4的倍數(即以long為單位),不足的以0填充

例如:

24Bit真彩圖每一行佔的實際位元組數:

nBytesPerLine =[(bi.biWidth*3+3)/4*4   // bi.biWidth為影象寬度

灰度圖每一行佔的實際位元組數:

nBytesPerLine = ((bi.biWidth+3)/4)*4

3. 24位真彩BMP影象的結構及灰度圖的結構

     (1)24位真彩BMP影象的結構主要由檔案頭,BMP資訊頭, BMP資料內容,沒有調色盤。

     (2)灰度圖的結構主要包括檔案頭,BMP資訊頭,調色盤,BMP資料內容四部分。灰度圖的調色盤共有256項RGBQUAD結構,存放0到255的灰度值,每一項rgbRed、rgbGreen、rgbBlue分量值相等。調色盤空間的申請的具體設定如下:

 RGBQUAD *ipRGB2 = (RGBQUAD *)malloc(256*sizeof(RGBQUAD));//調色盤的大小為1024位元組

      for ( i = 0; i < 256; i++ )

      ipRGB2[i].rgbRed = ipRGB2[i].rgbGreen = ipRGB2[i].rgbBlue = i;

4.BMP影象的讀寫

    BMP影象的讀:

(1)首先定義BMP檔案頭和資訊頭變數

BITMAPFILEHEADER bf; //BMP檔案頭結構體

BITMAPINFOHEADER bi; //BMP資訊頭結構體

(2)建立檔案輸入流fp

 fp=fopen(fileName,"rb");   //fileName為BMP影象檔名

(3)讀取資訊頭、檔案頭

fread(&bf,sizeof(BITMAPFILEHEADER),1,fp); 

fread(&bi,sizeof(BITMAPINFOHEADER),1,fp);

經過這兩條程式把BMP影象的資訊頭、檔案頭賦給bf和bi變數,可以根據bf和bi得到影象的各種屬性。

(4) 讀取BMP調色盤

fread(ipRGB2,sizeof(RGBQUAD),256,fp);  

(5)讀取BMP點陣圖資料

定義一個二維陣列Imgdata來存取BMP點陣圖資料

unsignedchar * * Imgdata;    

Imgdata=newunsignedchar*[bi.biHeight]; //宣告一個指標陣列

for ( i=0;i<bi.biHeight;i++)    

        Imgdata[i]=newunsignedchar[(bi.biWidth*3+3)/4*4]; //每個陣列元素也是一個指標陣列

for ( i=0;i<bi.biHeight;i++ )    

for(j=0;j<(bi.biWidth*3+3)/4*4;j++)    

            fread(&Imgdata[i][j],1,1,fp);//每次只讀取一個位元組,存入陣列

BMP影象的寫:

(1)建立一個輸出流fp

 fp=fopen("mybmp.bmp","wb");    

(2)寫BMP影象的資訊頭、檔案頭

fwrite(&bf2,sizeof(BITMAPFILEHEADER),1,fp);  

fwrite(&bi2,sizeof(BITMAPINFOHEADER),1,fp);

(3)寫BMP調色盤

fwrite(ipRGB2,sizeof(RGBQUAD),256,fp);  

(4)寫BMP影象的點陣圖資料部分

for (i=(bi.biHeight)-1 ;i>=0;i--)    

 for (j=0 ;j<(bi.biWidth*3+3)/4*4;j++)       

fwrite(&Imgdata[i][j],1,1,fp);    

5. 24位真彩BMP影象的灰度化

      把24位真彩BMP影象轉變成256階灰度圖的具體步驟如下:

(1) 修改資訊頭

       資訊頭共有11部分,灰度化時需要修改兩部分

bi2.biBitCount=8;

bi2.biSizeImage=( (bi.biWidth+3)/4 ) * 4*bi.biHeight

(2)修改檔案頭

       檔案頭共有5部分,灰度化時需要修改兩部分

bf2.bfOffBits = sizeof(bf2)+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);

bf2.bfSize = bf2.bfOffBits + bi2.biSizeImage;

(3)建立調色盤

RGBQUAD *ipRGB2 = (RGBQUAD *)malloc(256*sizeof(RGBQUAD));

for ( i = 0; i < 256; i++ )

ipRGB2[i].rgbRed = ipRGB2[i].rgbGreen = ipRGB2[i].rgbBlue = i;

  (4)修改點陣圖資料部分

         這部分主要是由原真彩圖的rgbRed、rgbGreen、rgbBlue分量值得到灰度影象的灰度值Y,可以用下面公式得到:

            Y=0.299*rgbRed+0.587* rgbGreen+0.114*rgbBlue;

具體修改程式碼如下:

int nBytesPerLine2 = ( (bi.biWidth+3)/4 ) * 4;

nLineStart2 = nBytesPerLine2 * i;

for ( int j = 0; j<nBytesPerLine2;j++ )

ImgData2[nLineStart2+j]= int( (float)Imgdata[i][3 * j] * 0.114 + \

(float)Imgdata[i][3 * j + 1] * 0.587 + \

(float)Imgdata[i][3 * j + 2] * 0.299 );//用一個一維陣列順序儲存灰度值

(5)按順序寫入BMP影象的各個部分

fwrite(&bf2,sizeof(BITMAPFILEHEADER),1,fp);  

fwrite(&bi2,sizeof(BITMAPINFOHEADER),1,fp);

fwrite(ipRGB2,sizeof(RGBQUAD),256,fp);

fwrite(ImgData2,nImageSize2,1,fp);

附:BMP的讀取和灰度化程式程式碼:

#include<windows.h>

#include<stdio.h>

#include<stdlib.h>

#include<ctype.h>

#include<string.h>

#include<malloc.h>

int main()    

{   

    BITMAPFILEHEADER bf; //BMP檔案頭結構體

    BITMAPINFOHEADER bi; //BMP資訊頭結構體

    FILE* fp;           //指向檔案的指標

    RGBQUAD *ipRGB; //

    DWORD LineByte,ImgSize;       

unsignedchar * * Imgdata;    

int i,j;    

char fileName[256];    

//開啟檔案

    printf("please enter filename:");    

    scanf("%s",fileName);    

    fp=fopen(fileName,"rb");    

if(fp == NULL){   

        printf("Open file error!");   

        exit(0);   

    }   

//讀取資訊頭、檔案頭

    fread(&bf,sizeof(BITMAPFILEHEADER),1,fp); //把指標fp所指向的檔案的頭資訊寫入bf(地址)

    fread(&bi,sizeof(BITMAPINFOHEADER),1,fp);    

    LineByte=bi.biSizeImage / bi.biHeight; //計算點陣圖的實際寬度並確保它為的倍數

    ImgSize=(DWORD)LineByte*bi.biHeight;               

     Imgdata=newunsignedchar*[bi.biHeight]; //宣告一個指標陣列

if(bi.biBitCount==24){    

for ( i=0;i<bi.biHeight;i++)    

        Imgdata[i]=newunsignedchar[(bi.biWidth*3+3)/4*4]; //每個陣列元素也是一個指標陣列

for ( i=0;i<bi.biHeight;i++ )    

for(j=0;j<(bi.biWidth*3+3)/4*4;j++)    

            fread(&Imgdata[i][j],1,1,fp);//每次只讀取一個位元組,存入陣列

fclose(fp);    

//寫入另一個檔案

fp=fopen("mybmp.bmp","wb");    

//以下定義中帶“2”的都是新影象資訊。

BITMAPFILEHEADER bf2;

BITMAPINFOHEADER bi2;

int nBytesPerLine2 = ( (bi.biWidth+3)/4 ) * 4;       

int nImageSize2 = nBytesPerLine2 * bi.biHeight; 

  memcpy( &bi2, &bi, sizeof(BITMAPINFOHEADER) );

  bi2.biBitCount=8;

  bi2.biSizeImage=nImageSize2;

bf2.bfType = 0x4d42;

bf2.bfReserved1 = bf2.bfReserved2 = 0;

bf2.bfOffBits = sizeof(bf2)+sizeof

相關推薦

BMP影象結構

1.文件目的 本文件主要給出24位真彩BMP影象的結構、讀寫和灰度化方法。 2.一般BMP影象的結構 一般的bmp檔案的結結構主要包括檔案頭,BMP資訊頭,調色盤,點陣圖資料內容 (1)BMP檔案頭(14位元組) ,檔案的第0位元組到第13位元組為BMP影象的檔案

實驗二 影象檔案的轉換(BMP轉YUV)

實驗二 影象檔案的讀寫和轉換(BMP轉YUV) 一、實驗基本原理 1.BMP點陣圖檔案格式 BMP(全稱Bitmap)是Windows作業系統中的標準影象檔案格式,可以分成兩類:裝置相關點陣圖(DDB)和裝置無關點陣圖(DIB),採用位對映儲存格式,除了影象深度可選(1

Python3 檔案流OS函式

讀和寫檔案open() 將會返回一個 file 物件,基本語法格式如下: open(filename, mode)filename:包含了你要訪問的檔名稱的字串值。mode:決定了開啟檔案的模式:只讀,寫入,追加等。所有可取值見如下的完全列表。這個引數是非強制的,預設檔案訪問

使用matlab對影象進行二值處理

用matlab對影象進行二值化處理 >>m = imread('d:\image\logo.jpg'); >> imshow(n); >> n = graythre

OpenCVForUnity二值

隨著csdn部落格系統升級,嘗試使用md寫文章,感覺還不錯。繼續使用OpenCVForUnity處理圖片,今次的效果是灰度化和二值化,當所有功能實現後,可能會做出一個unity版的美圖秀秀。 首先我們來確定一下兩者的概念。 二值化,就是將影象上的畫素點的灰

【數字影象】C++8位24位BMP點陣圖的平滑、銳、二值處理,以及24位真彩圖的

BMP標頭檔案: #ifndef BMP_H//前處理器 #define BMP_H typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef

在OpenCV環境下影象二維傅立葉換,幅值計算,頻譜平移將數值歸一到0到255區間的四個函式

影象處理開發資料、影象處理開發需求、影象處理接私活掙零花錢,可以搜尋公眾號"qxsf321",並關注! 影象處理開發資料、影象處理開發需求、影象處理接私活掙零花錢,可以搜尋公眾號"qxsf321",並關注! 影象處理開發資料、影象處理開發需求、影象處理接私活掙零花錢,可以搜尋

Spring實現動態資料來源,支援動態新增、刪除設定權重分離

當專案慢慢變大,訪問量也慢慢變大的時候,就難免的要使用多個數據源和設定讀寫分離了。 在開題之前先說明下,因為專案多是使用Spring,因此以下說到某些操作可能會依賴於Spring。 在我經歷過的專案中,見過比較多的讀寫分離處理方式,主要分為兩步: 1、對於開發人員,要

R語言使用RMySQL連接Mysql數據庫

技術分享 fcm list adl 創建數據庫 package install sql安裝 packages 簡單說下安裝過程,一般不會有問題,重點是RMySQL的使用方式。 系統環境說明 Redhat系統:Linux 460-42.6.32-431.29.2.el6.

mysql 主從實戰分離

logs 啟動 毫秒 class -- systemctl position 讀寫 mas 1. MYSQL主從原理    1) 至少需要2臺數據庫服務器,一主一從,Master開啟bin-log功能用於記錄主庫增加、刪除、修改、更新SQL語句。   2) 異步復

mysql主從分離

主從與讀寫分離 主從同步1 主配置把237配置為主數據庫服務器 授權用戶從42數據庫服務器連接自己的時候有拷貝數據的權限grant replication slave on *.* to [email protected]"172.40.7.42" identified

搬家行業開發小程序系統(App.Config詳解操作)

設置 反饋 流程 選擇 文件的 搬家 功能 操作 服務項目 應用程序配置文件是標準的 XML 文件,XML 標記和屬性是區分大小寫的。它是可以按需要更改的,開發人員可以使用配置文件來更改設置,而不必重編譯應用程序。配置文件的根節點是configuration。我們經常訪問的

mycat基本概念分離一

heartbeat sha linux系統中 mys ren ack ima text 雙master mycat基本概念及讀寫分離一

Python基礎筆記系列十一:標準輸入輸出、文件指針等操作

mode strong sublime pre 字符串類型 類型 print語句 open 同時   本系列教程供個人學習筆記使用,如果您要瀏覽可能需要其它編程語言基礎(如C語言),why?因為我寫得爛啊,只有我自己看得懂!! 標準輸入輸出一、輸入  在sublime中這

HBase 數據模型操作

稀疏 tor 標識 刪除 定位 兩個 超過 idt 表示 一、HBase數據模型  HBase是一個類似於BigTable的分布式數據庫,它是一個稀疏的長期存儲的(存在HDFS上)、多維度的、排序的映射表。這張表的索引是行關鍵字、列關鍵字和時間戳。HBase的數據都是字符串

mysql的復制集群,分離

replica 成功 http 一個 主機名 技術 端口號 變化 res 為什麽要設置mysql集群? 為了減輕,mysql服務器的IO壓力,設置多個其他mysql服務器幫他分擔讀寫操作 1.mysql復制集群的類型 主從架

mysql主從復制分離(附安裝包)

download inux libaio script 關閉防火墻 安裝包 useradd tor 數據 實驗目的:在實際生產環境中,如果對數據庫的讀和寫都在同一個數據庫服務器中操作,無論在安全性、高可用性,還是高並發等各個方面都是完全不能滿足實際需求的,因此,一般需要通過

MySQL中的事務鎖實現並發訪問控制

hang dea 執行c 定時 ack 幫助 持久 表操作 查看 一、並發控制中鎖的概念   鎖是並發控制中最核心的概念之一,在MySQL中的鎖分兩大類,一種是讀鎖,一種是寫鎖,讀鎖也可以稱為共享鎖(shared lock),寫鎖也通常稱為排它鎖(exclusive loc

C++結構操作

    今天再寫一個練手的程式的時候,忘記了C++關於結構體的檔案讀寫操作,於是在網上找了好多,但是都是有些問題的,經過一番探索終於解決了在檔案中讀寫結構體的問題,下面就是我的解決方法。     首先程式裡要用到ifstream的eof()函式,以及open

(ING)OpenCV基礎_矩陣/影象/視訊的

目錄 1. OpenCV簡介與學習建議 2. GUI指令 3. OpenCV基本資料結構 4. 數字影象處理 5. 矩陣處理 6. 視訊處理 1. OpenCV簡介與學習建議 1.1 OpenCV簡介 (1)特點 (2)功能 (3)包含模組 1.2 學習資源