欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言实现BMP图像处理(彩色图转灰度图)

程序员文章站 2022-03-04 15:01:36
我们知道真彩图不带调色板,每个象素用 3 个字节,表示 r、g、b 三个分量。所以处理很简单,根据 r、g、b 的值求出 y 值后,将 r、g、b 值都赋值成 y,写入新图即可。 在yuv 的颜色表示...

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

C语言实现BMP图像处理(彩色图转灰度图)

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

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

#include<stdio.h>
#include<windows.h>
 
int main(int argc, char* argv[])
{
 int bmpheight;
 int bmpwidth;
 unsigned char *pbmpbuf;
 rgbquad *pcolortable;
 int bibitcount;
 
 //读取bmp文件
 file *fp = fopen("./02.bmp", "rb");
 if (fp == 0)
  return 0;
 fseek(fp, sizeof(bitmapfileheader), 0);
 
 bitmapinfoheader head;
 fread(&head, 40, 1, fp);
 bmpheight = head.biheight;
 bmpwidth = head.biwidth;
 bibitcount = head.bibitcount;
 
 fseek(fp, sizeof(rgbquad), 1);
 
 int linebyte = (bmpwidth*bibitcount / 8 + 3) / 4 * 4;//保证每一行字节数都为4的整数倍
 pbmpbuf = new unsigned char[linebyte*bmpheight];
 fread(pbmpbuf, linebyte*bmpheight, 1, fp);
 fclose(fp);
 
 //将24位真彩图灰度化并保存
 file *fp1 = fopen("gray.bmp", "wb");
 if (fp1 == 0)
  return 0;
 int linebyte1 = (bmpwidth * 8 / 8 + 3) / 4 * 4;
 
 //修改文件头,其中有两项需要修改,分别为bfsize和bfoffbits
 bitmapfileheader bfhead;
 bfhead.bftype = 0x4d42;
 bfhead.bfsize = 14 + 40 + 256 * sizeof(rgbquad)+linebyte1*bmpheight;//修改文件大小
 bfhead.bfreserved1 = 0;
 bfhead.bfreserved2 = 0;
 bfhead.bfoffbits = 14 + 40 + 256 * sizeof(rgbquad);//修改偏移字节数
 fwrite(&bfhead, 14, 1, fp1);    //将修改后的文件头存入fp1;
 
 //修改信息头,其中有两项需要修改,1个位bibitcount:真彩图为24 ,应改成8;另一个是bisizeimage:由于每像素所占位数的变化,所以位图数据的大小发生变化
 bitmapinfoheader head1;
 head1.bibitcount = 8;    //将每像素的位数改为8
 head1.biclrimportant = 0;
 head1.bicompression = 0;
 head1.biclrused = 0;
 head1.biheight = bmpheight;
 head1.biwidth = bmpwidth;
 head1.biplanes = 1;
 head1.bisize = 40;
 head1.bisizeimage = linebyte1*bmpheight;//修改位图数据的大小
 head1.bixpelspermeter = 0;
 head1.biypelspermeter = 0;
 fwrite(&head1, 40, 1, fp1);  //将修改后的信息头存入fp1;
 
 pcolortable = new rgbquad[256];
 for (int i = 0; i < 256; i++){
  pcolortable[i].rgbred = i;
  pcolortable[i].rgbgreen = i;
  pcolortable[i].rgbblue = i; //是颜色表里的b、g、r分量都相等,且等于索引值
 }
 fwrite(pcolortable, sizeof(rgbquad), 256, fp1); //将颜色表写入fp1;
 
 //写位图数据
 unsigned char *pbmpbuf1;
 pbmpbuf1 = new unsigned char[linebyte1*bmpheight];
 for (int i = 0; i < bmpheight; i++){
  for (int j = 0; j<bmpwidth; j++){
   unsigned char *pb1, *pb2;
   pb1 = pbmpbuf + i*linebyte + j * 3;
   int y = *(pb1)*0.299 + *(pb1 + 1)*0.587 + *(pb1 + 2)*0.114;   //将每一个像素都按公式y=b*0.299+g*0.587+r*0.114进行转化
   pb2 = pbmpbuf1 + i*linebyte1 + j;
   *pb2 = y;
  }
 }
 fwrite(pbmpbuf1, linebyte1*bmpheight, 1, fp1);
 
 fclose(fp1);
 
 system("pause");
 return 0;
}

实验结果分析:

C语言实现BMP图像处理(彩色图转灰度图)

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

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