经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
C语言实现BMP图像处理(彩色图转灰度图)
来源:jb51  时间:2021/10/25 19:07:42  对本文有异议

我们知道真彩图不带调色板,每个象素用 3 个字节,表示 R、G、B 三个分量。所以处理很简单,根据 R、G、B 的值求出 Y 值后,将 R、G、B 值都赋值成 Y,写入新图即可。 在YUV 的颜色表示方法中,Y 分量的物理含义就是亮度,它含了灰度图(grayscale)的所有信息,只用 Y 分量就完全能够表示出一幅灰度图来。YUV 和RGB 之间有着如下的对应关系:

再来看看带调色板的彩色图,我们知道位图中的数据只是对应调色板中的一个索引值,我们只需要将调色板中的彩色变成灰度,形成新调色板,而位图数据不用动,就可以了。

以上解释来自于:《数字图像处理编程入门》,代码参考:C语言实现24位彩色图像二值化

  1. #include<stdio.h>
  2. #include<windows.h>
  3. int main(int argc, char* argv[])
  4. {
  5. int bmpHeight;
  6. int bmpWidth;
  7. unsigned char *pBmpBuf;
  8. RGBQUAD *pColorTable;
  9. int biBitCount;
  10. //读取bmp文件
  11. FILE *fp = fopen("./02.bmp", "rb");
  12. if (fp == 0)
  13. return 0;
  14. fseek(fp, sizeof(BITMAPFILEHEADER), 0);
  15. BITMAPINFOHEADER head;
  16. fread(&head, 40, 1, fp);
  17. bmpHeight = head.biHeight;
  18. bmpWidth = head.biWidth;
  19. biBitCount = head.biBitCount;
  20. fseek(fp, sizeof(RGBQUAD), 1);
  21. int LineByte = (bmpWidth*biBitCount / 8 + 3) / 4 * 4;//保证每一行字节数都为4的整数倍
  22. pBmpBuf = new unsigned char[LineByte*bmpHeight];
  23. fread(pBmpBuf, LineByte*bmpHeight, 1, fp);
  24. fclose(fp);
  25. //将24位真彩图灰度化并保存
  26. FILE *fp1 = fopen("gray.bmp", "wb");
  27. if (fp1 == 0)
  28. return 0;
  29. int LineByte1 = (bmpWidth * 8 / 8 + 3) / 4 * 4;
  30. //修改文件头,其中有两项需要修改,分别为bfSize和bfOffBits
  31. BITMAPFILEHEADER bfhead;
  32. bfhead.bfType = 0x4D42;
  33. bfhead.bfSize = 14 + 40 + 256 * sizeof(RGBQUAD)+LineByte1*bmpHeight;//修改文件大小
  34. bfhead.bfReserved1 = 0;
  35. bfhead.bfReserved2 = 0;
  36. bfhead.bfOffBits = 14 + 40 + 256 * sizeof(RGBQUAD);//修改偏移字节数
  37. fwrite(&bfhead, 14, 1, fp1); //将修改后的文件头存入fp1;
  38. //修改信息头,其中有两项需要修改,1个位biBitCount:真彩图为24 ,应改成8;另一个是biSizeImage:由于每像素所占位数的变化,所以位图数据的大小发生变化
  39. BITMAPINFOHEADER head1;
  40. head1.biBitCount = 8; //将每像素的位数改为8
  41. head1.biClrImportant = 0;
  42. head1.biCompression = 0;
  43. head1.biClrUsed = 0;
  44. head1.biHeight = bmpHeight;
  45. head1.biWidth = bmpWidth;
  46. head1.biPlanes = 1;
  47. head1.biSize = 40;
  48. head1.biSizeImage = LineByte1*bmpHeight;//修改位图数据的大小
  49. head1.biXPelsPerMeter = 0;
  50. head1.biYPelsPerMeter = 0;
  51. fwrite(&head1, 40, 1, fp1); //将修改后的信息头存入fp1;
  52. pColorTable = new RGBQUAD[256];
  53. for (int i = 0; i < 256; i++){
  54. pColorTable[i].rgbRed = i;
  55. pColorTable[i].rgbGreen = i;
  56. pColorTable[i].rgbBlue = i; //是颜色表里的B、G、R分量都相等,且等于索引值
  57. }
  58. fwrite(pColorTable, sizeof(RGBQUAD), 256, fp1); //将颜色表写入fp1;
  59. //写位图数据
  60. unsigned char *pBmpBuf1;
  61. pBmpBuf1 = new unsigned char[LineByte1*bmpHeight];
  62. for (int i = 0; i < bmpHeight; i++){
  63. for (int j = 0; j<bmpWidth; j++){
  64. unsigned char *pb1, *pb2;
  65. pb1 = pBmpBuf + i*LineByte + j * 3;
  66. int y = *(pb1)*0.299 + *(pb1 + 1)*0.587 + *(pb1 + 2)*0.114; //将每一个像素都按公式y=B*0.299+G*0.587+R*0.114进行转化
  67. pb2 = pBmpBuf1 + i*LineByte1 + j;
  68. *pb2 = y;
  69. }
  70. }
  71. fwrite(pBmpBuf1, LineByte1*bmpHeight, 1, fp1);
  72. fclose(fp1);
  73. system("pause");
  74. return 0;
  75. }

实验结果分析:

实验结果分析:真彩色图不带调色板,而灰度图的调色板为256级。所以在修改调色板时需要将RGB三个分量修改为256级,根据YUV颜色空间中Y分量计算。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号