BMP文件旋转

//一、要求将bmp文件顺时针旋转90°,要求熟悉BMP的文件格式及熟悉文件操作
//解题思路如下:
//1.BMP文件的组成此处不赘述,关键针对24位真彩图
//文件头组成
class Header				//文件头
{
public:
	WORD bftype;	//位图文件的类型,必须为“BM”
	DWORD bfsize;	//位图文件大小,以字节为单位,整个文件,包括位图与文件头和信息头
	WORD bfReserved1;	//位图文件保留字,必须为0
	WORD bfReserved2;	//位图文件保留字,必须为0
	DWORD bfOffBits;	//位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
};

/其中WORD等为自定义数据类型以配合文档说
typedef unsigned char BYTE;	//BYTE为每个像素的RGB类,数值在0~255
typedef unsigned int DWORD;	//四个字节
typedef unsigned short WORD;	//两个字节
typedef long LONG;		//四个字节


信息头组成
class Info					//信息头
{
public:
	DWORD biSize;		//本类所用的字节数
	LONG biWidth;		//位图的宽度,以像素为单位
	LONG biHeight;		//位图的高度,以像素为单位
	WORD biPlanes;		//目标设备的平面数//不清,必须为1//什么
	WORD biBitCount;	//每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
	DWORD biCompression;	//位图压缩类型,必须是 0(不压缩),1(BI_RLE8压缩类型)或 2(BI_RLE4压缩类型)之一
	DWORD biSizeImage;		//位图的大小,以字节为单位
	LONG biXPelsPerMeter;	//位图水平分辨率,每米像素数
	LONG biYPelsPerMeter;	//位图垂直分辨率,每米像素数
	DWORD biClrUsed;		//位图实际使用的颜色表中的颜色数
	DWORD biClrImportant;	//位图显示过程中重要的颜色数
};

这说明bmp高H,宽W,每个坐标下(x,y)有一个像素,其中像素有3个字节,分别为RGB

读写文件
int main(int argc,char* argv[])
{
	char* src_name;
	char* dest_name;
	if(argc == 1)
	{
		cout<<"use \"src.bmp\" as default input file name,use \"dest.bmp\" as default output file name\n";
		src_name = new char[10];
		dest_name = new char[10];
		strcpy(src_name,"src.bmp");
		strcpy(dest_name,"dest.bmp");
	}
	else
	{
		src_name = argv[1];
		dest_name = argv[2];
	}
	Header fileHeader;
	Info infoHeader;
	ifstream infile(src_name,ios::in|ios::binary);
	if(!infile)
	{
		cout<<"读取文件失败"<(infile,outfile,fileHeader,infoHeader);
	else
		Trans(infile,outfile,fileHeader,infoHeader);
	return 0;
}


//首先将src.bmp的文件头和信息头读入到内存的fileHeader 和infoHeader位置
//然后再进行旋转操作函数
//旋转函数的编写
//首先要改变目标函数的文件头数据和信息头数据,这里主要是文件头的bfSize即位图文件的大小和信息头的biWidth \biHeight\ biSizeImage
//其次要进行旋转操作,即改变位图旋转90°后的数据存储
//所以要先读入位图数据
//考虑到
//Windows 规定图像文件中一个扫描行所占的字节数必须是 4 的倍数(即以字为单位),不足的以 0 填充,图像文件中一个扫描行所占的字节数计算方法: 
//DataSizePerLine= (biWidth* biBitCount+31)/8;// 一个扫描行所占的字节数 
//即对于原始文件,其每行的后面是有补零的,所以读取时应跳过这部分
//PS:为什么每行读取字节公式是这样计算的呢?这是因为Windows 规定图像文件中一个扫描行所占的字节数必须是 4 的倍数(即以字为单位),即每个扫描行/读取的位数必须为32的倍数,向上取整,不足补零,所以要加上32-1,则DataSizePerLine= (biWidth* biBitCount+31)/32*4;
//则要计算每个扫描行的补零的字节数
//一种写法:
int getDiff(Info & info)
{
	int DataSizePerline = (info.biWidth * info.biBitCount+31) / 8;	// 一个扫描行实际所占的字节数
	DataSizePerline -= DataSizePerline % 4;				//为什么要这行捏,DataSizePerline不是4的倍数吗
	return DataSizePerline - info.biWidth * info.biBitCount /8;		//
}

//另一种写法
int getDiff(Info & info)
{
	return 4 - ((info.biWidth * info.biBitCount)/8)%4;		//但是这种写法好像不能解决图片2
}


//接下来便是旋转函数
template < class T >
bool Trans(ifstream & infile,ofstream & outfile,Header & header,Info & info)
{
	Header new_header = header;
	Info new_info = info;
	new_info.biWidth = info.biHeight;
	new_info.biHeight = info.biWidth;


	int diff = getDiff(info);
	T* pic = new T[info.biHeight * info.biWidth];


	for(int i=0;i
#include
#include
#include


#pragma pack(1)


using namespace std;


typedef unsigned char BYTE;
typedef unsigned int DWORD;
typedef unsigned short WORD;
typedef long LONG;


class Header				//文件头
{
public:
	WORD bftype;	//位图文件的类型,必须为“BM”
	DWORD bfsize;	//位图文件大小,以字节为单位,整个文件,包括位图与文件头和信息头
	WORD bfReserved1;	//位图文件保留字,必须为0
	WORD bfReserved2;	//位图文件保留字,必须为0
	DWORD bfOffBits;	//位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
};
class Info					//信息头
{
public:
	DWORD biSize;		//本类所用的字节数
	LONG biWidth;		//位图的宽度,以像素为单位
	LONG biHeight;		//位图的高度,以像素为单位
	WORD biPlanes;		//目标设备的平面数//不清,必须为1//什么
	WORD biBitCount;	//每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
	DWORD biCompression;	//位图压缩类型,必须是 0(不压缩),1(BI_RLE8压缩类型)或 2(BI_RLE4压缩类型)之一
	DWORD biSizeImage;		//位图的大小,以字节为单位
	LONG biXPelsPerMeter;	//位图水平分辨率,每米像素数
	LONG biYPelsPerMeter;	//位图垂直分辨率,每米像素数
	DWORD biClrUsed;		//位图实际使用的颜色表中的颜色数
	DWORD biClrImportant;	//位图显示过程中重要的颜色数
};
class RGB24
{
public:
	RGB24()
	{
		GREEN = 0;
		RED = 0;
		BLUE = 0;
	}
	BYTE RED;	//红色的亮度(值范围在0~255)
	BYTE GREEN;	//绿色的亮度(值范围在0~255)
	BYTE BLUE;	//蓝色的亮度(值范围在0~255)
};
/*找到每行需要补0的字节数 */
int getDiff(Info & info)
{
	int DataSizePerline = (info.biWidth * info.biBitCount+31) / 8;	// 一个扫描行实际所占的字节数
	DataSizePerline -= DataSizePerline % 4;
	return DataSizePerline - info.biWidth * info.biBitCount / 8;		//返回
}
template < class T >
bool Trans(ifstream & infile,ofstream & outfile,Header & header,Info & info)
{
	Header new_header = header;
	Info new_info = info;
	new_info.biWidth = info.biHeight;
	new_info.biHeight = info.biWidth;


	int diff = getDiff(info);
	T* pic = new T[info.biHeight * info.biWidth];


	for(int i=0;i(infile,outfile,fileHeader,infoHeader);
	return 0;
}


 
  
 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(程序设计实习)