/*********************************************************
对24位的位图进行灰度处理,将其转为8位的灰度图像,需要对文
件的信息头进行修改并添加调色板信息进行写入,图像大小转换
初始的1/3大小,尺寸不变
**********************************************************/
#include "StdAfx.h"
#include<iostream>
#include<Windows.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
using namespace std;
char *p,*p1; //像素指针
char fileName[300]; //定义打开图像名字
FILE *fp; //定义文件指针
char *buf; //定义文件读取缓冲区
FILE *fpw; //定义保存文件指针
BITMAPFILEHEADER bf; //图像文件头
BITMAPINFOHEADER bi; //图像文件头信息
DWORD w,h; //定义读取图像的长和宽
DWORD bitSize; //定义图像的大小
HWND wnd; //窗口句柄
HDC dc; //绘图设备环境句柄
HWND wnd1; //窗口句柄
HDC dc1; //绘图设备环境句柄
int r,g,b,pix,r1,g1,b1,pix1,count;
int color;
int main ()
{
/********************将指定数据读取到内存中*********************/
cout<<"请输入要打开文件的名字:";
cin>>fileName;
if((fp=fopen(fileName,"rb"))==NULL)
{
cout<<"文件未找到!";
exit(0);
}
fread(&bf,sizeof(BITMAPFILEHEADER),1,fp);//读取BMP文件头文件
fread(&bi,sizeof(BITMAPINFOHEADER),1,fp);//读取BMP文件头文件信息
/*********************检查开头字节是否为BM*********************/
if(bf.bfType!=MAKEWORD('B','M'))
{
cout<<"不是bmp图像";
}
/*******************从头文件中获取图像的基本信息*********************/
w=bi.biWidth; //获取图像的宽
cout<<"宽度"<<w<<endl;
h=bi.biHeight; //获取图像的高
cout<<"高度"<<h<<endl;
bitSize=bi.biSizeImage; //获取图像的size
count=bi.biBitCount; //获取图像的像素使用的二进制位数
cout<<"图像的位数"<<count<<endl;
/**********************检查开头字节是否为24位图*********************/
if (count!=24){
cout<<"文件不是bmp文件"<<endl;
system("pause");
return -1;
}
int nWidthBytes=(w*3+3)/4*4 ; //计算每行的字节数
cout<<"每行的字节数"<<nWidthBytes<<endl;
buf=(char*)malloc(h*w*count); //为图片文件分配缓冲区大小
fseek(fp,long(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)),0);//定位到像素起始位置
fread(buf,1,h*w*count,fp); //开始读取数据
/**********************在窗口中显示图像*********************/
wnd=GetForegroundWindow(); //获取窗口句柄
dc=GetDC(wnd); //获取绘图设备
int x=100; //定位窗口显示的开始坐标
int y=100;
p=buf; //图像像素地址的开始位置
for(int j=0;j<h;j++)
{
for(int i=0;i<w;i++)
{
b=*p++;
g=*p++;
r=*p++;
pix=RGB(r,g,b); //指定要用来绘制该点的颜色
SetPixel(dc,x+i,y+h-j,pix); //在屏幕中绘制此像素
}
}
/**********************构造新图像的文件信息头*********************/
BITMAPFILEHEADER newheader={0};
newheader.bfType=MAKEWORD('B','M');
newheader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;
newheader.bfSize=newheader.bfOffBits+h*nWidthBytes/3;//头文件加位图实际大小
/**********************构造灰度图的位图信息头*********************/
BITMAPINFOHEADER targetinfoheader={0};
targetinfoheader.biBitCount=8;
targetinfoheader.biSize=sizeof(BITMAPINFOHEADER);
targetinfoheader.biHeight=h;
targetinfoheader.biWidth=w;
targetinfoheader.biPlanes=1;
targetinfoheader.biCompression=BI_RGB;
targetinfoheader.biSizeImage=nWidthBytes*h/3;
targetinfoheader.biXPelsPerMeter=0;
targetinfoheader.biYPelsPerMeter=0;
targetinfoheader.biClrImportant=0;
targetinfoheader.biClrUsed=0;
/*****************构造灰度图的调色板信息需要256个*****************/
RGBQUAD rgbquad[256];
int i;
for(i=0;i<256;i++)
{
rgbquad[i].rgbBlue=i;
rgbquad[i].rgbGreen=i;
rgbquad[i].rgbRed=i;
rgbquad[i].rgbReserved=0;
}
/*****************在窗口中显示出灰度图像*****************/
p=buf; //重新定位到像素起始位置
wnd1=GetForegroundWindow(); //获取窗口句柄
dc1=GetDC(wnd1); //获取绘图设备
char * newImageData=new char[w*h]; //将处理后的像素值存储到一维数组中
int x1=200;
int y1=200;
int n=0;
for(int j=0;j<h;j++)
{
for(int i=0;i<w;i++)
{
b1=*p++;
g1=*p++;
r1=*p++;
color = (int)(r1 * 0.299 + g1 * 0.587 + b1 * 0.114);//指定要用来绘制该点的灰度化颜色 Gray = 0.30 * R + 0.59 * G + 0.11 *B
newImageData[w*j+i]=color;
pix1=RGB(color,color,color);
SetPixel(dc1,x1+i,y1+h-j,pix1); //在屏幕中绘制此像素
n++;
}
}
cout<<"像素个数"<<n<<endl;
/*****************将灰度图像的信息写入到文件中*****************/
fpw=fopen("test3灰度.bmp","wb"); //打开存储的文件
fwrite(&newheader,sizeof(newheader),1,fpw); //写入文件头
fwrite(&targetinfoheader,sizeof(BITMAPINFOHEADER),1,fpw);//写入位图信息头
fwrite(&rgbquad,sizeof(RGBQUAD),256,fpw); //写入调色板信息
p1=newImageData; //得到存储灰度像素信息的一维数组地址
for (int i=0;i<w*h;i++)
{
fwrite(p1++,1,1,fpw);
}
fclose(fpw);
fclose(fp);
system("pause");
return 0;
}
c++实现24 位位图的灰度化处理
最新推荐文章于 2022-03-05 21:36:24 发布