C++—— 读入一张bmp图片,提取其图像数据,存入矩阵/txt文件

本文章完成的是读入bmp图片、将数据存入矩阵/TXT文件、保存图片的功能。

在开始之前,我们需要了解bmp位图的存储方式:

BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
(1)bmp文件头(bmp file header):提供文件的格式、大小等信息
(2)位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
(3)调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表

(4)位图数据(bitmap data):图像数据,像素按照从下到上、从左到右的顺序每行占用的空间必须是4的整数倍


read_save.h


   
   
  1. #include<fstream>
  2. #include<windows.h>
  3. #include<iostream>
  4. using namespace std;
  5. unsigned char *pBmpBuf; //读入图像数据的指针
  6. int bmpWidth; //图像的宽
  7. int bmpHeight; //图像的高
  8. RGBQUAD *pColorTable; //颜色表指针
  9. int biBitCount; //图像类型,每像素位数
  10. //显示位图文件头信息
  11. void showBmpHead(BITMAPFILEHEADER pBmpHead){
  12. cout << "\n位图文件头:" << endl;
  13. cout << "文件大小:" << pBmpHead.bfSize << endl;
  14. cout << "保留字_1:" << pBmpHead.bfReserved1 << endl;
  15. cout << "保留字_2:" << pBmpHead.bfReserved2 << endl;
  16. cout << "实际位图数据的偏移字节数:" << pBmpHead.bfOffBits << endl << endl;
  17. }
  18. //显示位图信息头信息
  19. void showBmpInforHead(BITMAPINFOHEADER pBmpInforHead){
  20. cout << "\n位图信息头:" << endl;
  21. cout << "结构体的长度:" << pBmpInforHead.biSize << endl;
  22. cout << "位图宽:" << pBmpInforHead.biWidth << endl;
  23. cout << "位图高:" << pBmpInforHead.biHeight << endl;
  24. cout << "biPlanes平面数:" << pBmpInforHead.biPlanes << endl;
  25. cout << "biBitCount采用颜色位数:" << pBmpInforHead.biBitCount << endl;
  26. cout << "压缩方式:" << pBmpInforHead.biCompression << endl;
  27. cout << "biSizeImage实际位图数据占用的字节数:" << pBmpInforHead.biSizeImage << endl;
  28. cout << "X方向分辨率:" << pBmpInforHead.biXPelsPerMeter << endl;
  29. cout << "Y方向分辨率:" << pBmpInforHead.biYPelsPerMeter << endl;
  30. cout << "使用的颜色数:" << pBmpInforHead.biClrUsed << endl;
  31. cout << "重要颜色数:" << pBmpInforHead.biClrImportant << endl;
  32. }
  33. //-----------------------------------------------------------------------------------------
  34. //给定一个图像位图数据、宽、高、颜色表指针及每像素所占的位数等信息,将其写到指定文件中
  35. bool readBmp(char *bmpName)
  36. {
  37. FILE *fp = fopen(bmpName, "rb"); //二进制读方式打开指定的图像文件
  38. if (fp == 0)
  39. return 0;
  40. //跳过位图文件头结构BITMAPFILEHEADER
  41. fseek(fp, sizeof(BITMAPFILEHEADER), 0);
  42. /*
  43. BITMAPFILEHEADER filehead;
  44. fread(&filehead, 1, sizeof(BITMAPFILEHEADER), fp);
  45. showBmpHead(filehead);//显示文件头
  46. */
  47. //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
  48. BITMAPINFOHEADER infohead;
  49. fread(&infohead, sizeof(BITMAPINFOHEADER), 1, fp); //获取图像宽、高、每像素所占位数等信息
  50. bmpWidth = infohead.biWidth;
  51. bmpHeight = infohead.biHeight;
  52. biBitCount = infohead.biBitCount; //定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
  53. showBmpInforHead(infohead); //显示信息头
  54. int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4; //灰度图像有颜色表,且颜色表表项为256
  55. if (biBitCount == 8)
  56. {
  57. //申请颜色表所需要的空间,读颜色表进内存
  58. pColorTable = new RGBQUAD[ 256];
  59. fread(pColorTable, sizeof(RGBQUAD), 256, fp);
  60. }
  61. //申请位图数据所需要的空间,读位图数据进内存
  62. pBmpBuf = new unsigned char[lineByte * bmpHeight];
  63. fread(pBmpBuf, 1, lineByte * bmpHeight, fp);
  64. fclose(fp); //关闭文件
  65. return 1; //读取文件成功
  66. }
  67. //保存图片
  68. bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable)
  69. {
  70. //如果位图数据指针为0,则没有数据传入,函数返回
  71. if (!imgBuf)
  72. return 0;
  73. //颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0
  74. int colorTablesize = 0;
  75. if (biBitCount == 8)
  76. colorTablesize = 1024;
  77. //待存储图像数据每行字节数为4的倍数
  78. int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
  79. //以二进制写的方式打开文件
  80. FILE *fp = fopen(bmpName, "wb");
  81. if (fp == 0)
  82. return 0;
  83. //------------------------------------------------------------------------------------------------------------------
  84. //申请位图文件头结构变量,填写文件头信息
  85. BITMAPFILEHEADER fileHead;
  86. fileHead.bfType = 0x4D42; //bmp类型
  87. //bfSize是图像文件4个组成部分之和
  88. fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*height;
  89. fileHead.bfReserved1 = 0;
  90. fileHead.bfReserved2 = 0;
  91. //bfOffBits是图像文件前3个部分所需空间之和
  92. fileHead.bfOffBits = 54 + colorTablesize;
  93. //--------------------------------------------------------------------------------------------------------------------
  94. //写文件头进文件
  95. fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
  96. //申请位图信息头结构变量,填写信息头信息
  97. BITMAPINFOHEADER infohead;
  98. infohead.biBitCount = biBitCount;
  99. infohead.biClrImportant = 0;
  100. infohead.biClrUsed = 0;
  101. infohead.biCompression = 0;
  102. infohead.biHeight = height;
  103. infohead.biPlanes = 1;
  104. infohead.biSize = 40;
  105. infohead.biSizeImage = lineByte*height;
  106. infohead.biWidth = width;
  107. infohead.biXPelsPerMeter = 0;
  108. infohead.biYPelsPerMeter = 0;
  109. //写位图信息头进内存
  110. fwrite(&infohead, sizeof(BITMAPINFOHEADER), 1, fp);
  111. //----------------------------------------------------------------------------------------------------------------------
  112. //如果灰度图像,有颜色表,写入文件
  113. if (biBitCount == 8)
  114. fwrite(pColorTable, sizeof(RGBQUAD), 256, fp);
  115. //写位图数据进文件
  116. fwrite(imgBuf, height*lineByte, 1, fp);
  117. //关闭文件
  118. fclose(fp);
  119. return 1;
  120. }

read.cpp


   
   
  1. #include<cstdlib>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<iomanip>
  5. #include"readbmp.h"
  6. #include"savebmp.h"
  7. using namespace std;
  8. //unsigned int out_r[2000][2000];
  9. //unsigned int out_g[2000][2000];
  10. //unsigned int out_b[2000][2000];
  11. unsigned int **out_r;
  12. unsigned int **out_g;
  13. unsigned int **out_b;
  14. void doIt()
  15. {
  16. char readPath[] = "D:\\C++_file\\image_deal_C++\\read_BMP\\lunpan.bmp";
  17. readBmp(readPath);
  18. // 输出整体图像信息
  19. cout << "\nwidth=" << bmpWidth << "\nheight=" << bmpHeight << "\nbiBitCount=" << biBitCount << endl;
  20. // 图像的字节数
  21. int linebyte1 = (bmpWidth*biBitCount / 8 + 3) / 4 * 4;
  22. int n = 0, m = 0, count_xiang_su = 0;
  23. out_r = new unsigned int *[bmpHeight]; //开辟指针数组
  24. for ( int i = 0; i<bmpHeight; i++)
  25. out_r[i] = new unsigned int[bmpWidth];
  26. out_g = new unsigned int *[bmpHeight]; //开辟指针数组
  27. for ( int i = 0; i<bmpHeight; i++)
  28. out_g[i] = new unsigned int[bmpWidth];
  29. out_b = new unsigned int *[bmpHeight]; //开辟指针数组
  30. for ( int i = 0; i<bmpHeight; i++)
  31. out_b[i] = new unsigned int[bmpWidth];
  32. //初始化原始像素的数组。
  33. if (biBitCount == 8)
  34. {
  35. for ( int i = 0; i<bmpHeight / 2; i++)
  36. {
  37. for ( int j = 0; j<bmpWidth / 2; i++)
  38. *(pBmpBuf + i*linebyte1 + j) = 0;
  39. }
  40. }
  41. if (biBitCount == 24)
  42. {
  43. for ( int i = 0; i<bmpHeight; i++)
  44. {
  45. for ( int j = 0; j<bmpWidth; j++)
  46. {
  47. for ( int k = 0; k< 3; k++) //每像素RGB三个分量分别置0才变成黑色
  48. {
  49. m = *(pBmpBuf + i*linebyte1 + j * 3 + k);
  50. count_xiang_su++;
  51. }
  52. n++;
  53. }
  54. }
  55. cout << "总的像素个素为:" << n << endl;
  56. cout << "----------------------------------------------------" << endl;
  57. }
  58. if (biBitCount == 24)
  59. {
  60. for ( int i = 0; i<bmpHeight; i++)
  61. {
  62. for ( int j = 0; j<bmpWidth; j++)
  63. {
  64. out_r[bmpHeight - 1 - i][j] = pBmpBuf[j * 3 + 2 + bmpWidth*i * 3];
  65. out_g[bmpHeight - 1 - i][j] = pBmpBuf[j * 3 + 1 + bmpWidth *i * 3];
  66. out_b[bmpHeight - 1 - i][j] = pBmpBuf[j * 3 + bmpWidth *i * 3];
  67. }
  68. }
  69. // for (int i = 0; i<bmpHeight; i++)
  70. // {
  71. // for (int j = 0; j<bmpWidth; j++)
  72. // {
  73. // cout<<out_r[i][j]<<endl;
  74. // cout << out_g[i][j] << endl;
  75. // cout << out_b[i][j] << endl;
  76. // }
  77. // }
  78. }
  79. //---------------------------------------------------------------------------------------
  80. /*//将像素数据存入TXT文件。
  81. ofstream outfile;
  82. outfile.open("rrbmp.txt", ios::in | ios::trunc);
  83. if(!outfile) cout << "error" << endl;
  84. for (int i = 0; i<bmpHeight; i++)
  85. {
  86. for (int j = 0; j<bmpWidth; j++)
  87. {
  88. outfile << out_r[i][j] << " ";
  89. //cout << out_g[i][j] << endl;
  90. //cout << out_b[i][j] << endl;
  91. }
  92. outfile << "\n";
  93. }
  94. outfile.close();
  95. */
  96. // jiang tuxiang shuju cunpan .
  97. char writePath[] = "D:\\C++_file\\image_deal_C++\\read_BMP\\1.bmp";
  98. saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);
  99. //清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间
  100. delete[]pBmpBuf;
  101. if (biBitCount == 8)
  102. delete[]pColorTable;
  103. }
  104. //
  105. int main()
  106. {
  107. doIt();
  108. system( "pause");
  109. return 0;
  110. }

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值