用C++读取、修改和保存位图
该示例用C++读取、修改位图,通过它我们可以了解位图的文件结构,对图像处理的理解很有帮助。下面是全部的源码:
#include <stdio.h>
#include <fstream.h>
#include <windows.h>
/***********************变量的定义***********************************/
unsigned char* pBmpBuf; //读入图像数据的指针
int bmpWidth; //图像的宽度
int bmpHeight; //图像的高度
RGBQUAD* pColorTable; //颜色表指针
int biBitCount; //图像类型,像素位数
/****************************************************************************
读取图像的位图数据、宽度、高度、颜色表及像素位数,并存放在全局变量中
*****************************************************************************/
bool readBmp(char* bmpName)
{
FILE* fp = fopen(bmpName,"rb"); //以二进制读的方式打开指定的图像文件
if(fp == 0) return 0;
//跳过位图文件头
fseek(fp,sizeof(BITMAPFILEHEADER),0);
//定义位图信息头结构变量,读取位图信息头进内存,存放在变量infoHead中
BITMAPINFOHEADER infoHead;
fread(&infoHead,sizeof(BITMAPINFOHEADER),1,fp);
bmpWidth = infoHead.biWidth;
bmpHeight = infoHead.biHeight;
biBitCount = infoHead.biBitCount;
//定义变量,计算图像每行像素所占的字节数(必须为4的倍数)
int lineByte=(bmpWidth * biBitCount/8 + 3)/4 * 4;
//灰度图像有颜色表,且颜色表为256
if(biBitCount == 8)
{
//申请颜色表所需要的空间,读颜色表进内存
pColorTable = new RGBQUAD[256];
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
//申请位图数据所需要的空间,读位图数据进内存
pBmpBuf = new unsigned char[lineByte * bmpHeight];
fread(pBmpBuf,1,lineByte * bmpHeight,fp);
fclose(fp);
return 1;
}
/***************************************************************************************************
将指定数据写到文件中
***************************************************************************************************/
bool saveBmp(char* bmpName, unsigned char* imgBuf, int width, int height,
int biBitCount, RGBQUAD* pColorTable)
{
//如果位图数据指针为0,则没有数据输入
if (!imgBuf)
return 0;
//颜色表大小,以字节为单位:灰度图像为1024;彩色图像为0
int colorTablesize = 0;
if(biBitCount == 8)
colorTablesize = 1024;
//待存储图像数据每行字节数为4的倍数
int lineByte = (width * biBitCount/8 + 3)/4 * 4;
//以二进制写的方式打开文件
FILE* fp = fopen(bmpName,"wb");
if(fp == 0) return 0;
//申请位图文件头结构变量,填写文件头信息
BITMAPFILEHEADER fileHead;
fileHead.bfType = 0x4D42; // bmp 类型
//bfSize是图像文件4个部分之和
fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ colorTablesize + lineByte * height;
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;
//bfOffBits是图像文件前3个部分所需空间之和
fileHead.bfOffBits = 54 + colorTablesize;
//写文件头进文件
fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);
//申请位图信息头结构变量,填写信息头信息
BITMAPINFOHEADER infoHead;
infoHead.biBitCount = biBitCount;
infoHead.biClrImportant = 0;
infoHead.biClrUsed = 0;
infoHead.biCompression = 0;
infoHead.biHeight = height;
infoHead.biPlanes = 1;
infoHead.biSize = 40;
infoHead.biSizeImage = lineByte * height;
infoHead.biWidth = width;
infoHead.biXPelsPerMeter = 0;
infoHead.biYPelsPerMeter = 0;
//写位图信息头进内存
fwrite(&infoHead,sizeof(BITMAPINFOHEADER),1,fp);
//如果灰度图像,有颜色表,写入文件
if(biBitCount == 8)
fwrite(pColorTable,sizeof(RGBQUAD),256,fp);
//写位图数据进文件
fwrite(imgBuf,height * lineByte,1,fp);
fclose(fp);
return 1;
}
/*********************************************************************************************************************
位图处理过程
********************************************************************************************************************/
void pixHandle(char* bmpName)
{
//读入指定BMP文件进内存
readBmp(bmpName);
//输出图像的信息
cout<<"width="<<bmpWidth<<"/nheight="<<bmpHeight<<"/nBitCount="<<biBitCount<<endl;
//每行字节数
int lineByte = (bmpWidth * biBitCount/8 + 3)/4 * 4;
//循环变量定义
int m=0,n=0,pixCount=0;
//输出改变像素的文本文件
ofstream outfile("图像像素.txt",ios::in | ios::trunc );
if(biBitCount == 8) //灰度图像
{
//把图像的右上方的1/4变为黑色
for(int i=bmpHeight/2;i<bmpHeight;i++)
{
for(int j=lineByte/2;j<lineByte;j++)
{
m=*(pBmpBuf + i*lineByte + j) = 0;
outfile<<m<<" ";
pixCount++;
if(pixCount%8 == 0)
outfile<<endl;
}
}
}
if(!outfile)
cout<<"Open error!"<<endl;
else if(biBitCount == 24) //彩色图像
{
for(int i=bmpHeight/2;i<bmpHeight;i++)
{
for(int j=bmpWidth/2;j<bmpWidth;j++)
{
for(int k=0;k<3;k++)
{
m=*(pBmpBuf + i*lineByte + j*3 + k) =0; //每像素RGB三个分量分别置为0
outfile<<m<<" ";
pixCount++;
if(pixCount%8 == 0)
outfile<<endl;
}
n++;
}
}
cout<<"总的像素个数为:"<<n<<endl;
}
//将图像数据存盘
char* writePath = "testcpy.bmp";
//图片处理后再存储
saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);
delete[] pBmpBuf;
if(biBitCount == 8)
delete[] pColorTable;
}
void main()
{
pixHandle("test.bmp");
}
上述代码可直接运行,已经过测试。
参考:http://zhidao.baidu.com/question/122567656.html?si=1