c++实现24 位位图的灰度化处理

/*********************************************************

对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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值