参考:
http://stackoverflow.com/questions/5751749/how-can-i-read-bmp-pixel-values-into-an-array
http://msdn.microsoft.com/en-us/library/dd183374%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/dd183376%28v=VS.85%29.aspx
本文代码和测试图片下载
【测试图片】
宽50像素,高100像素,每个像素的颜色:Red=30, Green=50, Blue=80,在Windows mspaint.exe中保存为 24-bit Bitmap (.bmp)文件
【代码】
#ifndef _BMP_HEADER_DEF_H_ #define _BMP_HEADER_DEF_H_ typedef int LONG; typedef unsigned short WORD; typedef unsigned int DWORD; typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER, *PBITMAPFILEHEADER; typedef 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, *PBITMAPINFOHEADER; #endif
#ifndef _BMP_READER_H_ #define _BMP_READER_H_ #include "bmp_header_def.h" class CBmpReader { public: CBmpReader(); ~CBmpReader(); public: int Load(const char * bmp_file); void Unload(); unsigned int GetWidth() const; unsigned int GetHeight() const; PBITMAPFILEHEADER GetFileHeader() const; PBITMAPINFOHEADER GetInfoHeader() const; char * GetRawData() const; unsigned int GetRedAt(int row, int col) const; unsigned int GetGreenAt(int row, int col) const; unsigned int GetBlueAt(int row, int col) const; private: PBITMAPFILEHEADER m_pFileHeader; PBITMAPINFOHEADER m_pInfoHeader; char * m_buffer; char * m_pRawData; unsigned int m_nWidth; unsigned int m_nHeight; unsigned int m_nLineBytes; }; #endif
#pragma pack(1) #include "bmp_reader.h" #include <stdio.h> CBmpReader::CBmpReader() { m_pFileHeader = NULL; m_pInfoHeader = NULL; m_buffer = NULL; m_pRawData = NULL; m_nWidth = 0; m_nHeight = 0; m_nLineBytes = 0; } CBmpReader::~CBmpReader() { Unload(); } #define FOUR_BYTES_ALIGN(width_in_bit) ((((width_in_bit)+31)>>5)<<2) int CBmpReader::Load(const char * bmp_file) { FILE * pf = fopen(bmp_file, "rb"); if (NULL == pf) { return 0; } fseek(pf, 0, SEEK_END); long length = ftell(pf); rewind(pf); m_buffer = new char[length]; fread(m_buffer, length, 1, pf); m_pFileHeader = (PBITMAPFILEHEADER)(m_buffer); m_pInfoHeader = (PBITMAPINFOHEADER)(m_buffer + sizeof(BITMAPFILEHEADER)); m_pRawData = m_buffer + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); m_nWidth = m_pInfoHeader->biWidth; m_nHeight = m_pInfoHeader->biHeight; m_nLineBytes = FOUR_BYTES_ALIGN(m_nWidth * 24); fclose(pf); return 0; } void CBmpReader::Unload() { if (m_buffer) { m_pFileHeader = NULL; m_pInfoHeader = NULL; delete [] m_buffer; m_buffer = NULL; m_pRawData = NULL; m_nWidth = 0; m_nHeight = 0; m_nLineBytes = 0; } } unsigned int CBmpReader::GetWidth() const { return m_nWidth; } unsigned int CBmpReader::GetHeight() const { return m_nHeight; } PBITMAPFILEHEADER CBmpReader::GetFileHeader() const { return m_pFileHeader; } PBITMAPINFOHEADER CBmpReader::GetInfoHeader() const { return m_pInfoHeader; } char * CBmpReader::GetRawData() const { return m_pRawData; } #define GET_COLOR_AT(row, col, offset) \ if (NULL == m_pRawData) { \ return 0; \ } \ if ((row) > m_nHeight - 1 || (col) > m_nWidth - 1) { \ return 0; \ } \ return m_pRawData[m_nLineBytes * (row) + 3 * (col) + (offset)]; unsigned int CBmpReader::GetRedAt(int row, int col) const { GET_COLOR_AT(row, col, 2); } unsigned int CBmpReader::GetGreenAt(int row, int col) const { GET_COLOR_AT(row, col, 1); } unsigned int CBmpReader::GetBlueAt(int row, int col) const { GET_COLOR_AT(row, col, 0); }
#include <iostream> #include "bmp_reader.h" using namespace std; #define OUTPUT_TITLE(title) \ cout << "[" << #title << "]" << endl; #define OUTPUT_ITEM_CONTENT(item, name) \ cout << "\t" << #name << ": " << item->name << endl; void OutputBitMapFileHeader(PBITMAPFILEHEADER pFileHeader) { OUTPUT_TITLE("Bitmap File Header"); if (NULL == pFileHeader) { return; } OUTPUT_ITEM_CONTENT(pFileHeader, bfType); OUTPUT_ITEM_CONTENT(pFileHeader, bfSize); OUTPUT_ITEM_CONTENT(pFileHeader, bfReserved1); OUTPUT_ITEM_CONTENT(pFileHeader, bfReserved2); OUTPUT_ITEM_CONTENT(pFileHeader, bfOffBits); } void OutputBitMapInfoHeader(PBITMAPINFOHEADER pInfoHeader) { OUTPUT_TITLE("Bitmap Info Header"); if (NULL == pInfoHeader) { return; } OUTPUT_ITEM_CONTENT(pInfoHeader, biSize); OUTPUT_ITEM_CONTENT(pInfoHeader, biWidth); OUTPUT_ITEM_CONTENT(pInfoHeader, biHeight); OUTPUT_ITEM_CONTENT(pInfoHeader, biPlanes); OUTPUT_ITEM_CONTENT(pInfoHeader, biBitCount); OUTPUT_ITEM_CONTENT(pInfoHeader, biCompression); OUTPUT_ITEM_CONTENT(pInfoHeader, biSizeImage); OUTPUT_ITEM_CONTENT(pInfoHeader, biXPelsPerMeter); OUTPUT_ITEM_CONTENT(pInfoHeader, biYPelsPerMeter); OUTPUT_ITEM_CONTENT(pInfoHeader, biClrUsed); OUTPUT_ITEM_CONTENT(pInfoHeader, biClrImportant); } void OutputColorAt(const CBmpReader &reader, int row, int col) { cout << "BGR @ [" << row << ", " << col << "]: " << reader.GetBlueAt(row, col) << ", " << reader.GetGreenAt(row, col) << ", " << reader.GetRedAt(row, col) << endl; } int main(int argc, char * argv[]) { CBmpReader reader; reader.Load("./data.bmp"); int width = reader.GetWidth(); int height = reader.GetHeight(); cout << "width: " << width << " height: " << height << endl; PBITMAPFILEHEADER pFileHeader = reader.GetFileHeader(); OutputBitMapFileHeader(pFileHeader); PBITMAPINFOHEADER pInfoHeader = reader.GetInfoHeader(); OutputBitMapInfoHeader(pInfoHeader); OutputColorAt(reader, 0, 0); OutputColorAt(reader, 0, 1); OutputColorAt(reader, 0, 2); OutputColorAt(reader, 1, 0); OutputColorAt(reader, 1, 1); OutputColorAt(reader, 1, 2); OutputColorAt(reader, 0, width - 1); OutputColorAt(reader, height - 1, 0); OutputColorAt(reader, height - 1, width - 1); return 0; }
all: g++ -g bmp_reader.cpp main.cpp -o t clean: rm *.o t -f
width: 50 height: 100 ["Bitmap File Header"] bfType: 19778 bfSize: 0 bfReserved1: 0 bfReserved2: 54 bfOffBits: 2621440 ["Bitmap Info Header"] biSize: 40 biWidth: 50 biHeight: 100 biPlanes: 1 biBitCount: 24 biCompression: 0 biSizeImage: 15200 biXPelsPerMeter: 0 biYPelsPerMeter: 0 biClrUsed: 0 biClrImportant: 0 BGR @ [0, 0]: 80, 50, 30 BGR @ [0, 1]: 80, 50, 30 BGR @ [0, 2]: 80, 50, 30 BGR @ [1, 0]: 80, 50, 30 BGR @ [1, 1]: 80, 50, 30 BGR @ [1, 2]: 80, 50, 30 BGR @ [0, 49]: 80, 50, 30 BGR @ [99, 0]: 80, 50, 30 BGR @ [99, 49]: 80, 50, 30