Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2151681
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2016-06-22 18:58:16

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

说明比特数/象素,其值为1481624、或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用二进制分析出来的
  1. 0000000: 424d 36b0 0400 0000 0000 3600 0000 2800 BM6.......6...(.
  2. 0000010: 0000 f000 0000 4001 0000 0100 2000 0000 ......@..... ...
  3. 0000020: 0000 00b0 0400 0000 0000 0000 0000 0000 ................
  4. 0000030: 0000 0000 0000                          ......

  5. 14个字节的BITMAPFILEHEADER
  6. bfType   2B--> 424d即文件的类型,该值必需是0x4D42,也就是字符'BM'
  7. bfSize   4B--> 36b0 0400 --> 0x0004b036即文件的大小是307254字节=240*320*4+14+40
  8. bfResv   2B--> 0000 -->必须设置为0
  9. bfResv   2B--> 0000 -->必须设置为0
  10. bfOffset 4B--> 3600 0000 -->0x36=54即从文件头开始到实际的图象数据之间的字节的偏移量是54=14+40

  11. 40个字节的BITMAPINFOHEADER:
  12. biSize          4B-->2800 0000 -->0x28--> 40即BITMAPINFOHEADER结构所需要的字数是40
  13. biWidth         4B-->f000 0000 -->0xf0即图像的宽度是0xf0=240象素
  14. biHeight        4B-->4001 0000 -->0x0140即图像的高度是0x140=320象素
  15. biPlanes        2B-->0100      -->为目标设备说明位面数,其值将总是被设为1。
  16. biBitCount      2B-->2000      -->比特数/象素,即32bit一个象素
  17. biCompres       4B-->0000 0000 -->0代表没有压缩
  18. biSizeImage     4B-->00b0 0400 -->0x0004b000=307200-->图像中的数据大小,即去掉头之后的图像数据大小
  19. biXPelsPerMeter 4B-->0000 0000 -->水平分辨率,用象素/米表示
  20. biYPelsPerMeter 4B-->0000 0000 -->垂直分辨率,用象素/米表示
  21. biClrUsed       4B-->0000 0000 -->说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
  22. biClrImportant  4B-->0000 0000 -->说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。

知道这些内容了就可以把一个raw的数据写成bmp格式的图像文件
注意: BMP存储的图像数据是--> 从左下角的像素开始 到最后的右上角像素
二.rgb的raw图像与bmp之间的相互转化
2.1 将rgb的raw图像转为bmp
原先只是以为加个bmp头就可以了,没想到里面还有小细节需要注意的:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #pragma pack(1)                           //结构体要按字节对齐
  5. typedef struct __BITMAPFILEHEADER__
  6. {
  7.     u_int16_t bfType;
  8.     u_int32_t bfSize;
  9.     u_int16_t bfReserved1;
  10.     u_int16_t bfReserved2;
  11.     u_int32_t bfOffBits;
  12. }BITMAPFILEHEADER;

  13. typedef struct __BITMAPINFOHEADER
  14. {
  15.     u_int32_t biSize;
  16.     u_int32_t biWidth;
  17.     u_int32_t biHeight;
  18.     u_int16_t biPlanes;
  19.     u_int16_t biBitCount;
  20.     u_int32_t biCompression;
  21.     u_int32_t biSizeImage;
  22.     u_int32_t biXPelsPerMeter;
  23.     u_int32_t biYPelsPerMeter;
  24.     u_int32_t biClrUsed;
  25.     u_int32_t biClrImportant;
  26. }BITMAPINFOHEADER;

  27. #define BYTE_PER_PIX 3
  28. int create_bmp_header(BITMAPFILEHEADER* bmphead, BITMAPINFOHEADER* infohead, int w, int h)
  29. {
  30.     bmphead->bfType = 0x4D42; //must be 0x4D42='BM'
  31.     bmphead->bfSize= w*h*BYTE_PER_PIX+14+40;
  32.     bmphead->bfReserved1= 0x00;
  33.     bmphead->bfReserved2= 0x00;
  34.     bmphead->bfOffBits = 14+40;

  35.     infohead->biSize = sizeof(BITMAPINFOHEADER);
  36.     infohead->biWidth = w;
  37.     infohead->biHeight = -h;    //特别注意:引自参考文章"BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了"
  38.     infohead->biPlanes = 1;
  39.     infohead->biBitCount = BYTE_PER_PIX*8;
  40.     infohead->biCompression= 0;
  41.     infohead->biSizeImage= w*h*BYTE_PER_PIX;//640 * 480 * 3;
  42.     infohead->biXPelsPerMeter= 0x0;
  43.     infohead->biYPelsPerMeter= 0x0;
  44.     infohead->biClrUsed = 0;
  45.     infohead->biClrImportant = 0;
  46.     return 0;
  47. }

  48. int main ( int argc, char *argv[] )
  49. {
  50.     char* pbuf=NULL;
  51.     char* pRGBbuf=NULL;
  52.     int w = 640;
  53.     int h = 480;
  54.     char raw_file[] = "./640_480.raw";
  55.     char bmp_file[] = "./out.bmp";
  56.     FILE * raw_fp = NULL;
  57.     FILE * bmp_fp = NULL;
  58.     int i;
  59.     char t_ch;

  60.     BITMAPFILEHEADER bmphead;
  61.     BITMAPINFOHEADER infohead;
  62.     
  63.     pbuf = (char*)malloc(w*h*BYTE_PER_PIX*sizeof(char));
  64.     pRGBbuf = (char*)malloc(w*h*BYTE_PER_PIX*4*sizeof(char));

  65.     printf("sizeof(header)=%d\n",sizeof(bmphead));
  66.     printf("sizeof(info)=%d\n",sizeof(infohead));
  67.     //prepare for bmp write
  68.     if (NULL == (raw_fp = fopen(raw_file,"rb")))
  69.     {
  70.         printf("error: %s not found\n",raw_file);
  71.         return -1;
  72.     }

  73.     if (NULL == (bmp_fp = fopen(bmp_file,"wb")))
  74.     {
  75.         printf("error: %s not found\n",bmp_file);
  76.         return -1;
  77.     }

  78.     create_bmp_header(&bmphead, &infohead, w, h);
  79.     fwrite(&bmphead, 14, 1, bmp_fp);
  80.     fwrite(&infohead, 40, 1, bmp_fp);
  81.     
  82.     fread(pbuf, w*h*BYTE_PER_PIX, 1, raw_fp);
  83.     for(i=0; i<w*h*BYTE_PER_PIX; i+=BYTE_PER_PIX)  //特别注意,这儿的BGR转RGB
  84.     {
  85.         t_ch = pbuf[i];
  86.         pbuf[i] = pbuf[i+2];
  87.         pbuf[i+2] = t_ch;
  88.     }
  89.     fwrite(pbuf, w*h*BYTE_PER_PIX, 1, bmp_fp);

  90.     free(pbuf);
  91.     fclose(raw_fp);
  92.     fclose(bmp_fp);
  93.     printf("over\n");
  94.     return EXIT_SUCCESS;
  95. }

2.3 将bmp转为raw图像
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #pragma pack(1)
  6. typedef struct __BITMAPFILEHEADER__
  7. {
  8.     u_int16_t bfType;
  9.     u_int32_t bfSize;
  10.     u_int16_t bfReserved1;
  11.     u_int16_t bfReserved2;
  12.     u_int32_t bfOffBits;
  13. }BITMAPFILEHEADER;

  14. typedef struct __BITMAPINFOHEADER
  15. {
  16.     u_int32_t biSize;
  17.     u_int32_t biWidth;
  18.     u_int32_t biHeight;
  19.     u_int16_t biPlanes;
  20.     u_int16_t biBitCount;
  21.     u_int32_t biCompression;
  22.     u_int32_t biSizeImage;
  23.     u_int32_t biXPelsPerMeter;
  24.     u_int32_t biYPelsPerMeter;
  25.     u_int32_t biClrUsed;
  26.     u_int32_t biClrImportant;
  27. }BITMAPINFOHEADER;

  28. int translate_bmp2raw(FILE* raw_fp, FILE* bmp_fp)
  29. {
  30.     int i, len;
  31.     int w, h, bpp; //bpp-->byte_per_pix
  32.     char* p_temp = NULL;
  33.     BITMAPFILEHEADER bmphead;
  34.     BITMAPINFOHEADER infohead;

  35.     if( (NULL==raw_fp) || (NULL==bmp_fp))
  36.         return -1;
  37.     len = sizeof(bmphead)+sizeof(infohead);
  38.     printf("len=%d\n",len);
  39.     p_temp = (char*)malloc(len*sizeof(char));
  40.     if(p_temp == NULL)
  41.     {
  42.         printf("malloc error\n");
  43.         return -1;
  44.     }
  45.     fread(p_temp, len, 1, bmp_fp);
  46.     memcpy(&bmphead, p_temp, sizeof(bmphead));
  47.     memcpy(&infohead, p_temp+sizeof(bmphead), sizeof(infohead));
  48.     if(bmphead.bfType != 0x4D42) //must be 0x4D42='BM'
  49.     {
  50.         printf("not a bmp file\n");
  51.         return -1;
  52.     }
  53.     if(infohead.biBitCount < 24)
  54.     {
  55.         printf("error: now bitCount=%d < 24bit\n", infohead.biBitCount);
  56.         return -1;
  57.     }
  58.     free(p_temp);
  59.     w = infohead.biWidth;
  60.     h = infohead.biHeight;
  61.     bpp = infohead.biBitCount/8;
  62.     printf("w=%d,h=%d,bitcount=%d\n", w, h, bpp);
  63.     p_temp = (char*)malloc(w*h*bpp);
  64.     if(p_temp == NULL)
  65.     {
  66.         printf("malloc w*h*bpp error\n");
  67.         return -1;
  68.     }
  69.     fread(p_temp, w*h*bpp, 1, bmp_fp);
  70.     fwrite(p_temp, w*h*bpp, 1, raw_fp);
  71.     free(p_temp);
  72.     return 0;
  73. }

  74. int main ( int argc, char *argv[] )
  75. {
  76.     char* pbuf=NULL;
  77.     char bmp_file[] = "./240_320.bmp";
  78.     char raw_file[] = "./240_320.yuv";
  79.     FILE * raw_fp = NULL;
  80.     FILE * bmp_fp = NULL;

  81.     if (NULL == (bmp_fp = fopen(bmp_file,"rb")))
  82.     {
  83.         printf("error: %s not found\n",bmp_file);
  84.         return -1;
  85.     }

  86.     if (NULL == (raw_fp = fopen(raw_file,"wb")))
  87.     {
  88.         printf("error: %s not found\n",raw_file);
  89.         return -1;
  90.     }
  91.     
  92.     translate_bmp2raw(raw_fp, bmp_fp);

  93.     fclose(raw_fp);
  94.     fclose(bmp_fp);
  95.     printf("over\n");
  96.     return EXIT_SUCCESS;
  97. }

注意1:刚开始生成的bmp里面图像都是倒着的,参考下面的文章
《将rgb图像数据保存为BMP格式图片的方法》
http://blog.csdn.net/chyxwzn/article/details/8443883
才知道BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了  
注意2:刚开始生成的bmp里面图像BRG转一下RGB才能正常显示
所以需要加一个转换RB转换

阅读(4617) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~