1. 程式人生 > >C++—— 讀入一張bmp圖片,提取其影象資料,存入矩陣/txt檔案

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. }