程设作业:文件操作作业 解题报告&弱弱的代码

来源:互联网 发布:软件著作权和商标 编辑:程序博客网 时间:2024/06/11 14:06

解题报告:

做这道题要仔细阅读老师提供的文档,熟悉了24位位图的数据规模后再读入。

数据读入:对于图像数据分行读入,设置一个后移块,用于跳过每一行的补0位。

数据交换:a(width - i - 1,j) = b(j,i)

这里为了迎合题意,在main函数里加入两个参数int argc和char * argv[],这样可以直接从命令提示符cmd.exe中用如下图方式使用转换程序:

另外,代码里用到的template模板的思想来自thoar大牛的代码

大家可以去他的博客看到更多的代码:

http://blog.csdn.net/xranthoar

注意:老师提供的文档前面那篇文章可能有点问题,在图像描述信息块的最后一部分数据应该是002E-0035!

接下来贴代码:

因为手头没有32位位图,我不知道能不能旋转32位位图…

#include <iostream>#include <fstream>#pragma pack(1)using namespace std;const int CON_SIZE = 31;  //公式中的大小。DataSizePerLine= (biWidth* biBitCount+31)/8;为一个扫描行所占的字节数const int BYTE_SIZE = 8;  //一个字节=8位。typedef char BYTE;  //1字节typedef short DBYTE;  //2字节typedef int WORD;  //4字节typedef long LONG;  //4字节class FileHead  //文件头信息块{public:DBYTE bfType;  //文件标识,为字母ASCII码“BM”WORD bfSize;  //文件大小WORD bfReserved;  //保留,每字节以“00”填写WORD bfOffBits;  //记录图像数据区的起始位置。各字节的信息依次含义为:文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)};class InfoHead  //图像描述信息块{public:WORD biSize;  //图像描述信息块的大小,常为28HLONG biWidth;  //图像宽度LONG biHight;  //图像高度DBYTE biPlane;  //图像的plane总数(恒为1)DBYTE biBitCount;  //记录像素的位数,很重要的数值,图像的颜色数由该值决定WORD biCompression;  //数据压缩方式(数值位0:不压缩;1:8位压缩;2:4位压缩)WORD biSizeImage;  //图像区数据的大小LONG biXPelsPerMeter;  //水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写LONG biYPelsPerMeter;  //垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写WORD biClrUsed;  //此图像所用的颜色数WORD biCleImportance;  //颜色重要性,若为0,则表示颜色一样重要//这里要注意!老师提供的文档前面那篇文章这里有错误,他说“002E-0031:此图像所用的颜色数,如值为0,表示所有颜色一样重要。”//但实际上:这里应该是两个长为4字节的数据!(即biClrUsed和biCleImportance)};class RGBQuad_24 //24位位图图像数据{public:RGBQuad_24() : rgbBlue(0), rgbGreen(0), rgbRed(0) { };  //补0用BYTE rgbBlue;  //蓝BYTE rgbGreen;  //绿BYTE rgbRed;  //红};class RGBQuad_32 //32位位图图像数据{public:RGBQuad_32() : rgbBlue(0), rgbGreen(0), rgbRed(0), rgbAlpha(0) { };  //补0用BYTE rgbBlue;  //蓝BYTE rgbGreen;  //绿BYTE rgbRed;  //红BYTE rgbAlpha; //透明度};FileHead Head;InfoHead Info;template <typename RGBQuad>bool Deal(ifstream &fin, ofstream &fout){RGBQuad *Quad;int LineSize = (Info.biWidth * Info.biBitCount + CON_SIZE) / BYTE_SIZE;LineSize -= LineSize % 4;  //计算每一行的真实长度,在下面输入的时候用于过滤补0的数据int DifPtr = LineSize - Info.biWidth * sizeof(RGBQuad);  //用于跳过补0数据int Scale = Info.biHight * Info.biWidth;  //真实有用的数据规模Quad = new RGBQuad [Scale];  //生成图片数据包for(int i = 0; i != Info.biHight; ++i){fin.read((char*) (Quad + i * Info.biWidth), Info.biWidth * sizeof(RGBQuad));  //读入有效数据fin.seekg(DifPtr, ios::cur);  //跳过补0位}FileHead DestHead = Head;InfoHead DestInfo = Info;DestInfo.biHight = Info.biWidth;DestInfo.biWidth = Info.biHight;int DestLineSize = (DestInfo.biWidth * DestInfo.biBitCount + CON_SIZE) / BYTE_SIZE;DestLineSize -= DestLineSize % 4;DifPtr = DestLineSize - DestInfo.biWidth * sizeof(RGBQuad); Scale = DestInfo.biWidth * DestInfo.biHight;DestHead.bfSize = DestInfo.biHight * DestLineSize + sizeof(FileHead) + sizeof(InfoHead);DestInfo.biSizeImage = DestHead.bfSize - sizeof(FileHead) + sizeof(InfoHead);RGBQuad *DestQuad = new RGBQuad [Scale];for(int i = 0; i != DestInfo.biHight; ++i){for(int j = 0; j != DestInfo.biWidth; ++j){DestQuad[(DestInfo.biHight - i - 1) * DestInfo.biWidth + j] = Quad[j * Info.biWidth + i];}}  //交换数据fout.write((char *) &DestHead, sizeof(FileHead));fout.write((char *) &DestInfo, sizeof(InfoHead));char *Temp = new char[DifPtr + 1];memset(Temp, 0, DifPtr + 1);for(int i = 0; i != DestInfo.biHight; ++i){fout.write((char*) (DestQuad + DestInfo.biWidth * i), DestInfo.biWidth * sizeof(RGBQuad));fout.write((char*) Temp, DifPtr);}cout << "处理完成!" << endl;cout << "处理前文件大小 = " << Head.bfSize << endl;cout << "处理后文件大小 = " << DestHead.bfSize << endl;return true;}int main(int argc, char * argv[])  //传入控制台参数,在cmd里可以直接用rotatebmp src.bmp dest.bmp{if(argc == 1){argv[1] = "src.bmp";argv[2] = "dest.bmp";  //默认的图片文件名,缺省用}ifstream fin(argv[1], ios::in | ios::binary);ofstream fout(argv[2], ios::out | ios::binary);if(!fin){cout << "找不到 " << argv[1] << " !" << endl;return -1;}if(!fout){cout << "无法打开 " << argv[2] << " !" << endl;return -1;}fin.read((char *) &Head, sizeof(FileHead));fin.read((char *) &Info, sizeof(InfoHead));  //2进制读入两个文件信息头if(Info.biBitCount == 24){Deal<RGBQuad_24>(fin, fout);}if(Info.biBitCount == 32){Deal<RGBQuad_32>(fin, fout);}return 0;}




这里提供几张24位bmp给诸位试试。





原创粉丝点击