1.关于bmp的头
1.1 bmp头由两部分组成
包含14个字节的BITMAPFILEHEADER及40个字节的BITMAPINFOHEADER
1.2 以下两个表引自 《BMP 头文件格式》
http://blog.csdn.net/searchsun/article/details/4787472
BITMAPFILEHEADER:
bfType
|
说明文件的类型,该值必需是0x4D42,也就是字符'BM'。
|
bfSize
|
说明该位图文件的大小,用字节为单位
|
bfReserved1
|
保留,必须设置为0
|
bfReserved2
|
保留,必须设置为0
|
bfOffBits
|
说明从文件头开始到实际的图象数据之间的字节的偏移量。这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据。
|
BITMAPINFOHEADER:
biSize
|
说明BITMAPINFOHEADER结构所需要的字数。
|
biWidth
|
说明图象的宽度,以象素为单位。
|
biHeight
|
说明图象的高度,以象素为单位。注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。
|
biPlanes
|
为目标设备说明位面数,其值将总是被设为1。
|
biBitCount
|
说明比特数/象素,其值为1、4、8、16、24、或32。但是由于我们平时用到的图像绝大部分是24位和32位的,所以我们讨论这两类图像。
|
biCompression
|
说明图象数据压缩的类型,同样我们只讨论没有压缩的类型:BI_RGB。
|
biSizeImage
|
说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0。
|
biXPelsPerMeter
|
说明水平分辨率,用象素/米表示。
|
biYPelsPerMeter
|
说明垂直分辨率,用象素/米表示。
|
biClrUsed
|
说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
|
biClrImportant
|
说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
|
1.3 bmp的header分析
以下是从一张240 x 320 x 32用二进制分析出来的
-
0000000: 424d 36b0 0400 0000 0000 3600 0000 2800 BM6.......6...(.
-
0000010: 0000 f000 0000 4001 0000 0100 2000 0000 ......@..... ...
-
0000020: 0000 00b0 0400 0000 0000 0000 0000 0000 ................
-
0000030: 0000 0000 0000 ......
-
-
14个字节的BITMAPFILEHEADER:
-
bfType 2B--> 424d即文件的类型,该值必需是0x4D42,也就是字符'BM'
-
bfSize 4B--> 36b0 0400 --> 0x0004b036即文件的大小是307254字节=240*320*4+14+40
-
bfResv 2B--> 0000 -->必须设置为0
-
bfResv 2B--> 0000 -->必须设置为0
-
bfOffset 4B--> 3600 0000 -->0x36=54即从文件头开始到实际的图象数据之间的字节的偏移量是54=14+40
-
-
40个字节的BITMAPINFOHEADER:
-
biSize 4B-->2800 0000 -->0x28--> 40即BITMAPINFOHEADER结构所需要的字数是40
-
biWidth 4B-->f000 0000 -->0xf0即图像的宽度是0xf0=240象素
-
biHeight 4B-->4001 0000 -->0x0140即图像的高度是0x140=320象素
-
biPlanes 2B-->0100 -->为目标设备说明位面数,其值将总是被设为1。
-
biBitCount 2B-->2000 -->比特数/象素,即32bit一个象素
-
biCompres 4B-->0000 0000 -->0代表没有压缩
-
biSizeImage 4B-->00b0 0400 -->0x0004b000=307200-->图像中的数据大小,即去掉头之后的图像数据大小
-
biXPelsPerMeter 4B-->0000 0000 -->水平分辨率,用象素/米表示
-
biYPelsPerMeter 4B-->0000 0000 -->垂直分辨率,用象素/米表示
-
biClrUsed 4B-->0000 0000 -->说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
-
biClrImportant 4B-->0000 0000 -->说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
-
知道这些内容了就可以把一个raw的数据写成bmp格式的图像文件
注意: BMP存储的图像数据是--> 从左下角的像素开始 到最后的右上角像素
二.rgb的raw图像与bmp之间的相互转化
2.1
将rgb的raw图像转为bmp
原先只是以为加个bmp头就可以了,没想到里面还有小细节需要注意的:
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <math.h>
-
#pragma pack(1) //结构体要按字节对齐
-
typedef struct __BITMAPFILEHEADER__
-
{
-
u_int16_t bfType;
-
u_int32_t bfSize;
-
u_int16_t bfReserved1;
-
u_int16_t bfReserved2;
-
u_int32_t bfOffBits;
-
}BITMAPFILEHEADER;
-
-
typedef struct __BITMAPINFOHEADER
-
{
-
u_int32_t biSize;
-
u_int32_t biWidth;
-
u_int32_t biHeight;
-
u_int16_t biPlanes;
-
u_int16_t biBitCount;
-
u_int32_t biCompression;
-
u_int32_t biSizeImage;
-
u_int32_t biXPelsPerMeter;
-
u_int32_t biYPelsPerMeter;
-
u_int32_t biClrUsed;
-
u_int32_t biClrImportant;
-
}BITMAPINFOHEADER;
-
-
#define BYTE_PER_PIX 3
-
int create_bmp_header(BITMAPFILEHEADER* bmphead, BITMAPINFOHEADER* infohead, int w, int h)
-
{
-
bmphead->bfType = 0x4D42; //must be 0x4D42='BM'
-
bmphead->bfSize= w*h*BYTE_PER_PIX+14+40;
-
bmphead->bfReserved1= 0x00;
-
bmphead->bfReserved2= 0x00;
-
bmphead->bfOffBits = 14+40;
-
-
infohead->biSize = sizeof(BITMAPINFOHEADER);
-
infohead->biWidth = w;
-
infohead->biHeight = -h; //特别注意:引自参考文章"BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了"
-
infohead->biPlanes = 1;
-
infohead->biBitCount = BYTE_PER_PIX*8;
-
infohead->biCompression= 0;
-
infohead->biSizeImage= w*h*BYTE_PER_PIX;//640 * 480 * 3;
-
infohead->biXPelsPerMeter= 0x0;
-
infohead->biYPelsPerMeter= 0x0;
-
infohead->biClrUsed = 0;
-
infohead->biClrImportant = 0;
-
return 0;
-
}
-
-
int main ( int argc, char *argv[] )
-
{
-
char* pbuf=NULL;
-
char* pRGBbuf=NULL;
-
int w = 640;
-
int h = 480;
-
char raw_file[] = "./640_480.raw";
-
char bmp_file[] = "./out.bmp";
-
FILE * raw_fp = NULL;
-
FILE * bmp_fp = NULL;
-
int i;
-
char t_ch;
-
-
BITMAPFILEHEADER bmphead;
-
BITMAPINFOHEADER infohead;
-
-
pbuf = (char*)malloc(w*h*BYTE_PER_PIX*sizeof(char));
-
pRGBbuf = (char*)malloc(w*h*BYTE_PER_PIX*4*sizeof(char));
-
-
printf("sizeof(header)=%d\n",sizeof(bmphead));
-
printf("sizeof(info)=%d\n",sizeof(infohead));
-
//prepare for bmp write
-
if (NULL == (raw_fp = fopen(raw_file,"rb")))
-
{
-
printf("error: %s not found\n",raw_file);
-
return -1;
-
}
-
-
if (NULL == (bmp_fp = fopen(bmp_file,"wb")))
-
{
-
printf("error: %s not found\n",bmp_file);
-
return -1;
-
}
-
-
create_bmp_header(&bmphead, &infohead, w, h);
-
fwrite(&bmphead, 14, 1, bmp_fp);
-
fwrite(&infohead, 40, 1, bmp_fp);
-
-
fread(pbuf, w*h*BYTE_PER_PIX, 1, raw_fp);
-
for(i=0; i<w*h*BYTE_PER_PIX; i+=BYTE_PER_PIX) //特别注意,这儿的BGR转RGB
-
{
-
t_ch = pbuf[i];
-
pbuf[i] = pbuf[i+2];
-
pbuf[i+2] = t_ch;
-
}
-
fwrite(pbuf, w*h*BYTE_PER_PIX, 1, bmp_fp);
-
-
free(pbuf);
-
fclose(raw_fp);
-
fclose(bmp_fp);
-
printf("over\n");
-
return EXIT_SUCCESS;
-
}
2.3
将bmp转为raw图像
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <math.h>
-
#pragma pack(1)
-
typedef struct __BITMAPFILEHEADER__
-
{
-
u_int16_t bfType;
-
u_int32_t bfSize;
-
u_int16_t bfReserved1;
-
u_int16_t bfReserved2;
-
u_int32_t bfOffBits;
-
}BITMAPFILEHEADER;
-
-
typedef struct __BITMAPINFOHEADER
-
{
-
u_int32_t biSize;
-
u_int32_t biWidth;
-
u_int32_t biHeight;
-
u_int16_t biPlanes;
-
u_int16_t biBitCount;
-
u_int32_t biCompression;
-
u_int32_t biSizeImage;
-
u_int32_t biXPelsPerMeter;
-
u_int32_t biYPelsPerMeter;
-
u_int32_t biClrUsed;
-
u_int32_t biClrImportant;
-
}BITMAPINFOHEADER;
-
-
int translate_bmp2raw(FILE* raw_fp, FILE* bmp_fp)
-
{
-
int i, len;
-
int w, h, bpp; //bpp-->byte_per_pix
-
char* p_temp = NULL;
-
BITMAPFILEHEADER bmphead;
-
BITMAPINFOHEADER infohead;
-
-
if( (NULL==raw_fp) || (NULL==bmp_fp))
-
return -1;
-
len = sizeof(bmphead)+sizeof(infohead);
-
printf("len=%d\n",len);
-
p_temp = (char*)malloc(len*sizeof(char));
-
if(p_temp == NULL)
-
{
-
printf("malloc error\n");
-
return -1;
-
}
-
fread(p_temp, len, 1, bmp_fp);
-
memcpy(&bmphead, p_temp, sizeof(bmphead));
-
memcpy(&infohead, p_temp+sizeof(bmphead), sizeof(infohead));
-
if(bmphead.bfType != 0x4D42) //must be 0x4D42='BM'
-
{
-
printf("not a bmp file\n");
-
return -1;
-
}
-
if(infohead.biBitCount < 24)
-
{
-
printf("error: now bitCount=%d < 24bit\n", infohead.biBitCount);
-
return -1;
-
}
-
free(p_temp);
-
w = infohead.biWidth;
-
h = infohead.biHeight;
-
bpp = infohead.biBitCount/8;
-
printf("w=%d,h=%d,bitcount=%d\n", w, h, bpp);
-
p_temp = (char*)malloc(w*h*bpp);
-
if(p_temp == NULL)
-
{
-
printf("malloc w*h*bpp error\n");
-
return -1;
-
}
-
fread(p_temp, w*h*bpp, 1, bmp_fp);
-
fwrite(p_temp, w*h*bpp, 1, raw_fp);
-
free(p_temp);
-
return 0;
-
}
-
-
int main ( int argc, char *argv[] )
-
{
-
char* pbuf=NULL;
-
char bmp_file[] = "./240_320.bmp";
-
char raw_file[] = "./240_320.yuv";
-
FILE * raw_fp = NULL;
-
FILE * bmp_fp = NULL;
-
-
if (NULL == (bmp_fp = fopen(bmp_file,"rb")))
-
{
-
printf("error: %s not found\n",bmp_file);
-
return -1;
-
}
-
-
if (NULL == (raw_fp = fopen(raw_file,"wb")))
-
{
-
printf("error: %s not found\n",raw_file);
-
return -1;
-
}
-
-
translate_bmp2raw(raw_fp, bmp_fp);
-
-
fclose(raw_fp);
-
fclose(bmp_fp);
-
printf("over\n");
-
return EXIT_SUCCESS;
-
}
注意1:刚开始生成的bmp里面图像都是倒着的,参考下面的文章
《将rgb图像数据保存为BMP格式图片的方法》
http://blog.csdn.net/chyxwzn/article/details/8443883
才知道BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了
注意2:
刚开始生成的bmp里面图像BRG转一下RGB才能正常显示
所以需要加一个转换RB转换
阅读(4617) | 评论(0) | 转发(0) |