免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3531 | 回复: 6

[C] 怎样读取BMP文件后将图信息保存为二维数组进行处理 [复制链接]

论坛徽章:
0
发表于 2019-04-17 09:19 |显示全部楼层
我的编译环境是dev C++,目前写好了读取BMP头文件部分,已经可以读取出图片的属性信息了,代码如下:


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #pragma pack(1)

  4. /* 定义WORD为两个字节的类型 */
  5. typedef unsigned short WORD;
  6. /* 定义DWORD为四个字节的类型 */
  7. typedef unsigned int DWORD;

  8. /* 位图文件头主要是对位图文件的一些描述 位图信息头主要是对位图图像方面信息的描述 */
  9. /*************************** 位图标准信息(54字节) ******************************************/
  10. /* 位图文件头 (位图头的字节数 = 位图文件字节数 - 位图图像数据字节数)*/
  11. typedef struct BMP_FILE_HEADER
  12. {
  13.         WORD bType;      // 文件标识符
  14.         DWORD bSize;     // 文件的大小
  15.         WORD bReserved1; // 保留值,必须设置为0  
  16.         WORD bReserved2; // 保留值,必须设置为0
  17.         DWORD bOffset;   // 文件头的最后到图像数据位开始的偏移量
  18. } BMPFILEHEADER;     // 14 字节

  19. /* 位图信息头 */
  20. typedef struct BMP_INFO
  21. {
  22.         DWORD bInfoSize;            // 信息头的大小   
  23.         DWORD bWidth;               // 图像的宽度     
  24.         DWORD bHeight;              // 图像的高度     
  25.         WORD bPlanes;               // 图像的位面数   
  26.         WORD bBitCount;             // 每个像素的位数
  27.         DWORD bCompression;         // 压缩类型
  28.         DWORD bmpImageSize;         // 图像的大小,以字节为单位
  29.         DWORD bXPelsPerMeter;       // 水平分辨率
  30.         DWORD bYPelsPerMeter;       // 垂直分辨率
  31.         DWORD bClrUsed;             // 使用的色彩数
  32.         DWORD bClrImportant;        // 重要的颜色数
  33. } BMPINF0;                      // 40 字节

  34. /* 彩色表:调色板 */
  35. typedef struct RGB_QUAD
  36. {
  37.         WORD rgbBlue;     // 蓝色强度
  38.         WORD rgbGreen;    // 绿色强度
  39.         WORD rgbRed;      // 红色强度
  40.         WORD rgbReversed; // 保留值
  41. } RGBQUAD;






  42. int main()
  43. {
  44.         int i = sizeof(BMPFILEHEADER);
  45.         int j = sizeof(long);
  46.         FILE *fp;                     // 定义一个文件指针
  47.         BMPFILEHEADER bmpFileHeader;  // 定义一个 BMP 文件头的结构体
  48.         BMPINF0 bmpInfo;               // 定义一个 BMP 文件信息结构体
  49.     MAPINFO mapinfo;              // 定义一个 图片信息结构体
  50.   
  51.         // "rb" 只读打开一个二进制文件,只允许读数据。'b'指的是让这个库函数以二进制形式打开此文件。
  52.         // 读取失败会返回空指针,读取成功后,fp 会指向一块具有 bmp 属性的内存,我们可以对这块内存开始操作
  53.         if((fp = fopen("ABC.bmp", "rb")) == NULL) // fp = 0x00426aa0
  54.         {
  55.                 printf("Cann't open the file!\n");
  56.                 return 0;
  57.         }

  58.         // 让 fp 指向 bmp 文件的开始
  59.         // 第 2 个参数是偏移量 第三个参数是文件起始地址 所以此函数执行成功后文件指针会指向文件的开始
  60.         fseek(fp, 0, SEEK_SET);                            // fp = 0x00426aa0

  61.         // 读取文件信息
  62.         fread(&bmpFileHeader, sizeof(BMPFILEHEADER), 1, fp);
  63.        

  64.         fread(&bmpInfo, sizeof(bmpInfo), 1, fp);



  65.         // 输出BMP文件的位图文件头的所有信息
  66.         printf("位图文件头主要是对位图文件的一些描述:BMPFileHeader\n\n");
  67.         printf("文件标识符 = 0X%X\n", bmpFileHeader.bType);
  68.         printf("BMP 文件大小 = %d 字节\n", bmpFileHeader.bSize);
  69.         printf("保留值1 = %d \n", bmpFileHeader.bReserved1);
  70.         printf("保留值2 = %d \n", bmpFileHeader.bReserved2);
  71.         printf("文件头的最后到图像数据位开始的偏移量 = %d 字节\n", bmpFileHeader.bOffset);

  72.         // 输出BMP文件的位图信息头的所有信息
  73.         printf("\n\n位图信息头主要是对位图图像方面信息的描述:BMPInfo\n\n");
  74.         printf("信息头的大小 = %d 字节\n", bmpInfo.bInfoSize);
  75.         printf("位图的高度 = %d \n", bmpInfo.bHeight);
  76.         printf("位图的宽度 = %d \n", bmpInfo.bWidth);
  77.         printf("图像的位面数(位面数是调色板的数量,默认为1个调色板) = %d \n", bmpInfo.bPlanes);
  78.         printf("每个像素的位数 = %d 位\n", bmpInfo.bBitCount);
  79.         printf("压缩类型 = %d \n", bmpInfo.bCompression);
  80.         printf("图像的大小 = %d 字节\n", bmpInfo.bmpImageSize);
  81.         printf("水平分辨率 = %d \n", bmpInfo.bXPelsPerMeter);
  82.         printf("垂直分辨率 = %d \n", bmpInfo.bYPelsPerMeter);
  83.         printf("使用的色彩数 = %d \n", bmpInfo.bClrUsed);
  84.         printf("重要的色彩数 = %d \n", bmpInfo.bClrImportant);



  85.        
  86.         fclose(fp);
  87.         while(1);
  88.         return 0;

  89. }
复制代码
基本可以运行,但是我不清楚应该怎样设定一个二维数组来读取图片的信息并处理

这个二维数组的要求应该是这样:大小为图片的长*宽,每一位数据的大小应该为每个像素的位数,

之前我尝试了fread(&mapinfo, bmpInfo.bHeight*bmpInfo.bWidth, 1, fp);来继续读取图片信息,但是直接报错了
Process exited with return value 3221225477

求助!


论坛徽章:
0
发表于 2019-04-17 10:43 |显示全部楼层
和位图的位深有关,假设你是24位的,就是每个像素点3字节,需要的空间就是长X宽X3。
另外,长度要4字节的整数倍对齐,VC里面有个宏定义:
#define   WIDTHBYTES(i)  ((i+31)/32*4)
这样,每一行的长度应该是: WIDTHBYTES(bi.biWidth*bi.biBitCount)

论坛徽章:
0
发表于 2019-04-17 10:44 |显示全部楼层
你看一下开源项目的实现,比如freeimage

论坛徽章:
0
发表于 2019-04-17 10:55 |显示全部楼层
回复 2# sxcong

您好,这个大致了解了#define   WIDTHBYTES(i)  ((i+31)/32*4) 的意义,请问我应该怎么设置这个数组并读取数据呢?
我现在尝试像头文件一样定义一个
  1. <div>typedef struct MAP_INFO</div><div>{</div><div><span style="white-space:pre">        </span>int map[bmpInfo.bHeight][bmpInfo.bWidth];</div><div><span style="white-space:pre">        </span></div><div>} MAPINFO;</div>
复制代码


  1. <div>  MAPINFO mapinfo;              // 定义一个 图片信息结构体 </div><div>  fread(&mapinfo, sizeof(mapinfo), 1, fp);    //读取图片信息</div>
复制代码

可以编译,但是运行结果为:
  1. Process exited with return value 3221225725
复制代码
目前看来好像是是设置存储大小出了问题,您看这个方向还有办法解决吗

论坛徽章:
0
发表于 2019-04-17 13:33 |显示全部楼层
你没看我的回复吗?你空间申请的不对,假设是24位,你要申请的点数x3, 32图就是x4。
而且,你的fread(&mapinfo, bmpInfo.bHeight*bmpInfo.bWidth, 1, fp);是要把数据放到 mapinof里,这明显不对,应该再申请一个内存空间。比如:
int totalSize = WIDTHBYTES(bi.biWidth*bi.biBitCount) *bmpHeight;
BYTE *pBmpBuf = new BYTE[totalSize];

论坛徽章:
0
发表于 2019-04-21 21:09 |显示全部楼层
您好,大致写了一下,
  1. void readBmp(const char* bmpName) {

  2.     FILE *fp=fopen(bmpName,"rb");

  3.     if(fp==0) {

  4.         printf("cannot open file");

  5.         return 0;

  6.     }

  7.     fseek(fp,sizeof(BITMAPFILEHEADER),0);

  8.     BITMAPINFOHEADER head;

  9.     fread(&head,sizeof(BITMAPINFOHEADER),1,fp);

  10.     bmpWidth = head.biWidth;

  11.     bmpHeight = head.biHeight;

  12.     biBitCount = head.biBitCount;

  13.     biClrUsed = head.biClrUsed;

  14.     int lineByte = (bmpWidth *biBitCount/8+3)/4*4;//计算图像每行像素所占的字节数

  15.     pColorTable = new RGBQUAD[256];
  16.    
  17.     fread(pColorTable,sizeof(RGBQUAD),256,fp);//★

  18.     pBmpBuf = new unsigned char [lineByte *bmpHeight+1];

  19.     fread(pBmpBuf,1,lineByte *bmpHeight,fp);

  20.     fclose(fp);

  21.     return 1;

  22. }
复制代码


论坛徽章:
0
发表于 2019-04-21 21:09 |显示全部楼层
您好,大致写了一下,
  1. void readBmp(const char* bmpName) {

  2.     FILE *fp=fopen(bmpName,"rb");

  3.     if(fp==0) {

  4.         printf("cannot open file");

  5.         return 0;

  6.     }

  7.     fseek(fp,sizeof(BITMAPFILEHEADER),0);

  8.     BITMAPINFOHEADER head;

  9.     fread(&head,sizeof(BITMAPINFOHEADER),1,fp);

  10.     bmpWidth = head.biWidth;

  11.     bmpHeight = head.biHeight;

  12.     biBitCount = head.biBitCount;

  13.     biClrUsed = head.biClrUsed;

  14.     int lineByte = (bmpWidth *biBitCount/8+3)/4*4;//计算图像每行像素所占的字节数

  15.     pColorTable = new RGBQUAD[256];
  16.    
  17.     fread(pColorTable,sizeof(RGBQUAD),256,fp);//★

  18.     pBmpBuf = new unsigned char [lineByte *bmpHeight+1];

  19.     fread(pBmpBuf,1,lineByte *bmpHeight,fp);

  20.     fclose(fp);

  21.     return 1;

  22. }
复制代码


您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

SACC2019中国系统架构师大会

【数字转型 架构演进】SACC2019中国系统架构师大会
2019年10月31日~11月2日第11届中国系统架构师大会(SACC2019)将在北京隆重召开。四大主线并行的演讲模式,1个主会场、20个技术专场、超千人参与的会议规模,100+来自互联网、金融、制造业、电商等领域的嘉宾阵容,将为广大参会者提供一场最具价值的技术交流盛会。




----------------------------------------

大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP