0. BMP格式重點介紹
0.1 BMP採用的是小端(Little Endian)存儲方式
這種存儲方式中“RGB24”格式的像素的分量存儲的先後順序爲B、G、R。由於RGB24格式存儲的順序是R、G、B,所以需要將“R”和“B”順序作一個調換再進行存儲。
0.2 BMP圖像的高度與RGB相反
0.3 BMP文件結構
BMP文件是由BITMAPFILEHEADER、BITMAPINFOHEADER、RGB像素數據共3個部分構成,它的結構如下圖所示。
//BITMAPFILEHEADER
//BITMAPINFOHEADER
//RGB像素數據
//其中前兩部分的結構如下所示。在寫入BMP文件頭的時候給其中的每個字段賦上合適的值就可以了。
typedef struct tagBITMAPFILEHEADER{
unsigned short int bfType; //位圖文件的類型,必須爲BM
unsigned long bfSize; //文件大小,以字節爲單位
unsigned short int bfReserverd1; //位圖文件保留字,必須爲0
unsigned short int bfReserverd2; //位圖文件保留字,必須爲0
unsigned long bfbfOffBits; //位圖文件頭到數據的偏移量,以字節爲單位
}BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{
long biSize; //該結構大小,字節爲單位
long biWidth; //圖形寬度以象素爲單位
long biHeight; //圖形高度以象素爲單位
short int biPlanes; //目標設備的級別,必須爲1
short int biBitcount; //顏色深度,每個象素所需要的位數
short int biCompression; //位圖的壓縮類型
long biSizeImage; //位圖的大小,以字節爲單位
long biXPelsPermeter; //位圖水平分辨率,每米像素數
long biYPelsPermeter; //位圖垂直分辨率,每米像素數
long biClrUsed; //位圖實際使用的顏色表中的顏色數
long biClrImportant; //位圖顯示過程中重要的顏色數
}BITMAPINFOHEADER;
1. 代碼如下
extern "C"
{
#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#endif
}
extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
}
/**
* Convert RGB24 file to BMP file
* @param rgb24path Location of input RGB file.
* @param width Width of input RGB file.
* @param height Height of input RGB file.
* @param url_out Location of Output BMP file.
*/
int simplest_rgb24_to_bmp(const char* rgb24path, int width, int height,
const char* bmppath) {
typedef struct { //tagBITMAPFILEHEADER關鍵結構
long imageSize; //文件大小,已字節爲單位
long blank;
long startPosition;
}BmpHead;
typedef struct {
long Length;
long width;
long height;
unsigned short colorPlane;
unsigned short bitColor;
long zipFormat;
long realSize;
long xPels;
long yPels;
long colorUse;
long colorImportant;
}InfoHead;
int i = 0, j = 0;
BmpHead m_BMPHeader = { 0 };
InfoHead m_BMPInfoHeader = { 0 };
char bfType[2] = { 'B','M' };
int header_size = sizeof(bfType) + sizeof(BmpHead) + sizeof(InfoHead);
unsigned char* rgb24_buffer = NULL;
FILE* fp_rgb24 = NULL, * fp_bmp = NULL;
if ((fp_rgb24 = fopen(rgb24path, "rb")) == NULL) { //輸入文件
printf("Error: Cannot open input RGB24 file.\n");
return -1;
}
if ((fp_bmp = fopen(bmppath, "wb")) == NULL) { //bmppath爲生成文件
printf("Error: Cannot open output BMP file.\n");
return -1;
}
rgb24_buffer = (unsigned char*)malloc(width * height * 3);
//申請內存空間,大小由BMP圖像類型決定
fread(rgb24_buffer, 1, width * height * 3, fp_rgb24);
//一個字節一個字節的把fp_rgb24裏面的數據存到rgb24_buffer裏面
m_BMPHeader.imageSize = 3 * width * height + header_size;
//文件大小,總的存儲RGB數據的加上文件頭
m_BMPHeader.startPosition = header_size;//位圖文件頭到數據的偏移量,以字節爲單位
m_BMPInfoHeader.Length = sizeof(InfoHead); //改結構的大小
m_BMPInfoHeader.width = width;//BMP圖像寬度以爲RGB像素的寬度
//BMP storage pixel data in opposite direction of Y-axis (from bottom to top).
m_BMPInfoHeader.height = -height;//BMP圖像高度和原RGB是相反的
m_BMPInfoHeader.colorPlane = 1; //目標設備的級別,必須爲1
m_BMPInfoHeader.bitColor = 24;//顏色深度,每個像素所需要的位數
m_BMPInfoHeader.realSize = 3 * width * height;//位圖的大小
fwrite(bfType, 1, sizeof(bfType), fp_bmp);//把bfType對應的BM寫入fp_bmp中
fwrite(&m_BMPHeader, 1, sizeof(m_BMPHeader), fp_bmp);
//繼續上面的文件指針,m_BMPHeader寫入fp_bmp中
fwrite(&m_BMPInfoHeader, 1, sizeof(m_BMPInfoHeader), fp_bmp);
//繼續上面的文件指針,m_BMPInfoHeader寫入fp_bmp中
//BMP save R1|G1|B1,R2|G2|B2 as B1|G1|R1,B2|G2|R2
//It saves pixel data in Little Endian
//So we change 'R' and 'B'
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
char temp = rgb24_buffer[(j * width + i) * 3 + 2];
rgb24_buffer[(j * width + i) * 3 + 2] = rgb24_buffer[(j * width + i) * 3 + 0];
rgb24_buffer[(j * width + i) * 3 + 0] = temp;
//將RGB數據中每個像素的“R”和“B”的位置互換。
}
}
fwrite(rgb24_buffer, 3 * width * height, 1, fp_bmp);
//繼續上面的文件指針,把交換過的RGB數據存到fp_bmp
fclose(fp_rgb24);//關閉流
fclose(fp_bmp);//關閉流
free(rgb24_buffer);//釋放內存
printf("Finish generate %s!\n", bmppath);
return 0;
}
int main()
{
simplest_rgb24_to_bmp("lena_256x256_rgb24.rgb", 256, 256, "output_lena.bmp");
return 0;
}
2. 效果
下圖爲輸入: RGB24格式的圖像lena_256x256_rgb24.rgb
下圖是封裝爲BMP格式後的圖像output_lena.bmp,封裝後的圖像使用普通的看圖軟件就可以查看。
用Windows照片查看器打開,效果如下:
參考鏈接:https://blog.csdn.net/leixiaohua1020/article/details/50534150