2个回答
展开全部
,所以只做了处理24位位图和32位位图的功能,1、4、8、16位位图从原理上来说是一样的,不过情况稍微复杂一点。你自己解决吧。
//注意,运行时必须要在控制台(cmd窗口)运行,如果直接在编译器那里编译时,是看不到希望的结果的。有问题的话这两天可以百度找我,再过几天就回家了,得明年才回来。
#include<windows.h>
#include<iostream>
#include<fstream>
#include <iomanip>
using namespace std;
/*
位图文件分四个部分:
1.文件头
2.文件信息头
3.调色板
4.实际位图数据
//位图文件文件头,2*3+4*2=14字节
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;//文件类型,必须为0x424D,由于WORD类型存放数据是先低字节、再高字节,所以实际上在判断时要用0x4d42(见代码,或者可直接用10进制的数19778),即"BM",'B'=0x42,'M'='0x4d'
DWORD bfSize;//文件大小
WORD bfReserved1;//保留字,必须设置为0,可不考虑,下同
WORD bfReserved2;
DWORD bfOffBits;//文件头到实际位图数据的偏移字节数,即前三部分长度之和
}BITMAPFILEHEADER;
//文件信息头,2*2+4*9=40字节
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;//此结构长度,为40
LONG biWidth;//图像宽度,单位为像素
LONG biHeight;//图像高度,单位为像素
WORD biPlanes;//必须为1
WORD biBitCount;//颜色位数,常用有:1(黑白2色图)、4(16色图)、8(256色图)、24(真彩色图)。新bmp格式还支持32位(增强型真彩色图)
DWORD biCompression;//指定位图是否压缩,有效值:BI_RGB、BI_RLE8、BI_RLE4、BI_BITFIELDS,均为Windows定义好的常量
DWORD biSizeImage;//实际位图数据占用的字节数
LONG biXPelsPerMeter;//目标设备水平分辨率,单位:像素/米
LONG biYPelsPerMeter;//目标设备垂直分辨率,单位:像素/米
DWORD biClrUsed;//图像实际用的到颜色数,如果为0,则实际用到的颜色数为:2的biBitCount次方
DWORD biClrImportant;//重要的颜色数,为0时表示所有颜色都重要
}BITMAPINFOHEADER;
//位图调色板(真彩色不需要),是一个数组,共biClrUsed个元素,若该值为0,则共有2的biBitCount次方个元素。每个元素是一个颜色表结构:
//颜色表结构
typedef struct tagRGBQUAD
{
BYTE rgbBlue; //蓝色分量
BYTE rgbGreen; //绿色分量
BYTE rgbRed; //红色分量
BYTE rgbReserved;//保留值
}RGBQUAD;
*/
class CBmp
{
public:
//读图像文件信息
bool ReadInfo(char FilePath[]);
//写图像灰度信息到文本文件
bool WriteToTxt(char FilePath[]);
CBmp();
virtual ~CBmp();
private:
BITMAPFILEHEADER m_sBMFH; //位图文件头
BITMAPINFOHEADER m_sBMIH; //位图信息头
RGBQUAD * m_pPalette; //调色板
BYTE * m_pBData; //位图数据
};
CBmp::CBmp()
{
m_pPalette = NULL;
m_pBData = NULL;
}
CBmp::~CBmp()
{
if(m_pPalette!=NULL)
{
delete [] m_pPalette;
m_pPalette = NULL;
}
if(m_pBData!=NULL)
{
delete [] m_pBData;
m_pBData = NULL;
}
}
//读图像文件
bool CBmp::ReadInfo(char FilePath[])
{
int nSize; //用来记录调色板的大小
ifstream fin;
fin.open(FilePath,ios::binary);
if(!fin)
{
cerr<<"Open file error!"<<endl;
return false;
}
//读取文件头
fin.read((char *)(&m_sBMFH),sizeof(BITMAPFILEHEADER));
// 判断是否BMP格式
if(m_sBMFH.bfType!=0x4d42)
{
cout<<"该文件不是BMP格式的文件!"<<endl;
return false;
}
//读取文件信息头
fin.read((char *)(&m_sBMIH),sizeof(BITMAPINFOHEADER));
//计算调色板的大小
nSize = m_sBMFH.bfOffBits - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER);
if(nSize!=0)
{
//读取调色板
m_pPalette = new RGBQUAD [nSize/4];
fin.read((char *)(m_pPalette),nSize);
}
//读取图像数据
m_pBData = new BYTE [m_sBMIH.biSizeImage];
fin.read((char *)(m_pBData),m_sBMIH.biSizeImage);
return true;
}
//写图像灰度信息到文本文件
bool CBmp::WriteToTxt(char FilePath[])
{
// 选用的灰度转换公式不同,所得的结果基本上是一致的,但是会稍有差别。
// Gray = (R*38 + G*75 + B*15) >> 7; //高精度转灰度公式
// Gray = R*0.299 + G*0.587 + B*0.114 //使用浮点计算,速度较慢
int k = 0,i,j;
int r,g,b;
int Gray;
BYTE *pt;
ofstream fout;
int t=0;
j = strlen(FilePath);
char *TxtFilePath = new char [j+1]; //记录灰度值的文本文件路径
TxtFilePath[j-3] = 't';
TxtFilePath[j-2] = 'x';
TxtFilePath[j-1] = 't';
TxtFilePath[j] = '\0';
for(i=j-4;i>=0;i--)
TxtFilePath[i] = FilePath[i] ;
switch(m_sBMIH.biBitCount)
{
case 1: //1、4、8位的位图有调色板,要先读取调色板,根据索引找到真实的图像RGB值,再转换。
cout<<"黑白2色(1位)位图的处理暂未实现!"<<endl;
break;
case 4:
cout<<"16色(4位)位图的处理暂未实现!"<<endl;
break;
case 8:
cout<<"256色(8位)位图的处理暂未实现"<<endl;
break;
case 16: //16位位图无调色板,一般为前5位记录R值,中6位记录G值,后5位记录B值
cout<<"16位位图的处理暂未实现"<<endl;
break;
case 24:
if(m_sBMIH.biWidth*3%4!=0)t=4-m_sBMIH.biWidth*3%4; //位图数据要求每行字节数必须是4的倍数,不足补齐t
fout.open(TxtFilePath,ios::out);
for(i=m_sBMIH.biHeight-1;i>=0;i--)
{
fout<<"第"<<m_sBMIH.biHeight-i<<"行像素点的灰度值:\n";
for(j=0;j<m_sBMIH.biWidth;j++)
{
pt = m_pBData+i*(m_sBMIH.biWidth*3+t)+3*j ;
r = (int)(*pt);
g = (int)(*(pt+1));
b = (int)(*(pt+2));
// Gray = (r*0.299+g*0.587+b*0.114);
Gray = (r*38 + g*75 + b*15) >> 7;
fout<<setiosflags(ios::left)<<setw(4)<<Gray;
}
fout<<endl;
}
fout.close();
break;
case 32:
//每行字节数必是4的倍数,所以不用补齐
fout.open(TxtFilePath,ios::out);
for(i=m_sBMIH.biHeight-1;i>=0;i--)
{
fout<<"第"<<m_sBMIH.biHeight-i<<"行像素点的灰度值:\n";
for(j=0;j<m_sBMIH.biWidth;j++)
{
pt = m_pBData+i*(m_sBMIH.biWidth*4+t)+4*j ;
r = (int)(*pt);
g = (int)(*(pt+1));
b = (int)(*(pt+2));
// Gray = (r*0.299+g*0.587+b*0.114);
Gray = (r*38 + g*75 + b*15) >> 7;
fout<<setiosflags(ios::left)<<setw(4)<<Gray;
}
fout<<endl;
}
fout.close();
break;
default:
return false;
}
cout<<"灰度值记录在文件"<<TxtFilePath<<"中"<<endl;
delete [] TxtFilePath;
return true;
}
int main(int argc,char *argv[])
{
if(argc !=2 )
{
cout<<"输入参数错误,正确形式:\nyourprogram filePath"<<endl;
return 0;
}
CBmp Bitmap;
if( Bitmap.ReadInfo(argv[1]) )
Bitmap.WriteToTxt(argv[1]);
else
{
cout<<"读取文件出错"<<endl;
return 0;
}
return 1;
}
//注意,运行时必须要在控制台(cmd窗口)运行,如果直接在编译器那里编译时,是看不到希望的结果的。有问题的话这两天可以百度找我,再过几天就回家了,得明年才回来。
#include<windows.h>
#include<iostream>
#include<fstream>
#include <iomanip>
using namespace std;
/*
位图文件分四个部分:
1.文件头
2.文件信息头
3.调色板
4.实际位图数据
//位图文件文件头,2*3+4*2=14字节
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;//文件类型,必须为0x424D,由于WORD类型存放数据是先低字节、再高字节,所以实际上在判断时要用0x4d42(见代码,或者可直接用10进制的数19778),即"BM",'B'=0x42,'M'='0x4d'
DWORD bfSize;//文件大小
WORD bfReserved1;//保留字,必须设置为0,可不考虑,下同
WORD bfReserved2;
DWORD bfOffBits;//文件头到实际位图数据的偏移字节数,即前三部分长度之和
}BITMAPFILEHEADER;
//文件信息头,2*2+4*9=40字节
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;//此结构长度,为40
LONG biWidth;//图像宽度,单位为像素
LONG biHeight;//图像高度,单位为像素
WORD biPlanes;//必须为1
WORD biBitCount;//颜色位数,常用有:1(黑白2色图)、4(16色图)、8(256色图)、24(真彩色图)。新bmp格式还支持32位(增强型真彩色图)
DWORD biCompression;//指定位图是否压缩,有效值:BI_RGB、BI_RLE8、BI_RLE4、BI_BITFIELDS,均为Windows定义好的常量
DWORD biSizeImage;//实际位图数据占用的字节数
LONG biXPelsPerMeter;//目标设备水平分辨率,单位:像素/米
LONG biYPelsPerMeter;//目标设备垂直分辨率,单位:像素/米
DWORD biClrUsed;//图像实际用的到颜色数,如果为0,则实际用到的颜色数为:2的biBitCount次方
DWORD biClrImportant;//重要的颜色数,为0时表示所有颜色都重要
}BITMAPINFOHEADER;
//位图调色板(真彩色不需要),是一个数组,共biClrUsed个元素,若该值为0,则共有2的biBitCount次方个元素。每个元素是一个颜色表结构:
//颜色表结构
typedef struct tagRGBQUAD
{
BYTE rgbBlue; //蓝色分量
BYTE rgbGreen; //绿色分量
BYTE rgbRed; //红色分量
BYTE rgbReserved;//保留值
}RGBQUAD;
*/
class CBmp
{
public:
//读图像文件信息
bool ReadInfo(char FilePath[]);
//写图像灰度信息到文本文件
bool WriteToTxt(char FilePath[]);
CBmp();
virtual ~CBmp();
private:
BITMAPFILEHEADER m_sBMFH; //位图文件头
BITMAPINFOHEADER m_sBMIH; //位图信息头
RGBQUAD * m_pPalette; //调色板
BYTE * m_pBData; //位图数据
};
CBmp::CBmp()
{
m_pPalette = NULL;
m_pBData = NULL;
}
CBmp::~CBmp()
{
if(m_pPalette!=NULL)
{
delete [] m_pPalette;
m_pPalette = NULL;
}
if(m_pBData!=NULL)
{
delete [] m_pBData;
m_pBData = NULL;
}
}
//读图像文件
bool CBmp::ReadInfo(char FilePath[])
{
int nSize; //用来记录调色板的大小
ifstream fin;
fin.open(FilePath,ios::binary);
if(!fin)
{
cerr<<"Open file error!"<<endl;
return false;
}
//读取文件头
fin.read((char *)(&m_sBMFH),sizeof(BITMAPFILEHEADER));
// 判断是否BMP格式
if(m_sBMFH.bfType!=0x4d42)
{
cout<<"该文件不是BMP格式的文件!"<<endl;
return false;
}
//读取文件信息头
fin.read((char *)(&m_sBMIH),sizeof(BITMAPINFOHEADER));
//计算调色板的大小
nSize = m_sBMFH.bfOffBits - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER);
if(nSize!=0)
{
//读取调色板
m_pPalette = new RGBQUAD [nSize/4];
fin.read((char *)(m_pPalette),nSize);
}
//读取图像数据
m_pBData = new BYTE [m_sBMIH.biSizeImage];
fin.read((char *)(m_pBData),m_sBMIH.biSizeImage);
return true;
}
//写图像灰度信息到文本文件
bool CBmp::WriteToTxt(char FilePath[])
{
// 选用的灰度转换公式不同,所得的结果基本上是一致的,但是会稍有差别。
// Gray = (R*38 + G*75 + B*15) >> 7; //高精度转灰度公式
// Gray = R*0.299 + G*0.587 + B*0.114 //使用浮点计算,速度较慢
int k = 0,i,j;
int r,g,b;
int Gray;
BYTE *pt;
ofstream fout;
int t=0;
j = strlen(FilePath);
char *TxtFilePath = new char [j+1]; //记录灰度值的文本文件路径
TxtFilePath[j-3] = 't';
TxtFilePath[j-2] = 'x';
TxtFilePath[j-1] = 't';
TxtFilePath[j] = '\0';
for(i=j-4;i>=0;i--)
TxtFilePath[i] = FilePath[i] ;
switch(m_sBMIH.biBitCount)
{
case 1: //1、4、8位的位图有调色板,要先读取调色板,根据索引找到真实的图像RGB值,再转换。
cout<<"黑白2色(1位)位图的处理暂未实现!"<<endl;
break;
case 4:
cout<<"16色(4位)位图的处理暂未实现!"<<endl;
break;
case 8:
cout<<"256色(8位)位图的处理暂未实现"<<endl;
break;
case 16: //16位位图无调色板,一般为前5位记录R值,中6位记录G值,后5位记录B值
cout<<"16位位图的处理暂未实现"<<endl;
break;
case 24:
if(m_sBMIH.biWidth*3%4!=0)t=4-m_sBMIH.biWidth*3%4; //位图数据要求每行字节数必须是4的倍数,不足补齐t
fout.open(TxtFilePath,ios::out);
for(i=m_sBMIH.biHeight-1;i>=0;i--)
{
fout<<"第"<<m_sBMIH.biHeight-i<<"行像素点的灰度值:\n";
for(j=0;j<m_sBMIH.biWidth;j++)
{
pt = m_pBData+i*(m_sBMIH.biWidth*3+t)+3*j ;
r = (int)(*pt);
g = (int)(*(pt+1));
b = (int)(*(pt+2));
// Gray = (r*0.299+g*0.587+b*0.114);
Gray = (r*38 + g*75 + b*15) >> 7;
fout<<setiosflags(ios::left)<<setw(4)<<Gray;
}
fout<<endl;
}
fout.close();
break;
case 32:
//每行字节数必是4的倍数,所以不用补齐
fout.open(TxtFilePath,ios::out);
for(i=m_sBMIH.biHeight-1;i>=0;i--)
{
fout<<"第"<<m_sBMIH.biHeight-i<<"行像素点的灰度值:\n";
for(j=0;j<m_sBMIH.biWidth;j++)
{
pt = m_pBData+i*(m_sBMIH.biWidth*4+t)+4*j ;
r = (int)(*pt);
g = (int)(*(pt+1));
b = (int)(*(pt+2));
// Gray = (r*0.299+g*0.587+b*0.114);
Gray = (r*38 + g*75 + b*15) >> 7;
fout<<setiosflags(ios::left)<<setw(4)<<Gray;
}
fout<<endl;
}
fout.close();
break;
default:
return false;
}
cout<<"灰度值记录在文件"<<TxtFilePath<<"中"<<endl;
delete [] TxtFilePath;
return true;
}
int main(int argc,char *argv[])
{
if(argc !=2 )
{
cout<<"输入参数错误,正确形式:\nyourprogram filePath"<<endl;
return 0;
}
CBmp Bitmap;
if( Bitmap.ReadInfo(argv[1]) )
Bitmap.WriteToTxt(argv[1]);
else
{
cout<<"读取文件出错"<<endl;
return 0;
}
return 1;
}
展开全部
给你个网址,里面有个现成的库,很简单,C的,我最近也是使用的他
参考资料: http://www.yakergong.com/blog/archives/159
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询