问题遇到的现象和发生背景
在使用C++学习图像处理时,遇到的一个小问题。
现象:复制后的文件数据出现"错位",原因是多了两个字节
背景:使用Visual studio 2022 处理BMP位图
完整代码
#include <iostream>
#include <fstream>
using namespace std;
typedef struct //位图文件头格式
{
short int bfType; // 位图文件的类型,必须设置为BM _**正是该部分数据出现问题**_
int bfSize; // 位图文件的大小,以字节为单位
short int bfReserved1;// 位图文件保留字,必须设置为0
short int bfReserved2;// 位图文件保留字,必须设置为0
short int bfOffBits; // 位图数据相对于位图文件头的偏移量表示,即位图点阵偏移量
}HEAD; //实际上,使用sizeof(HEAD)==16 因为 sizeof以4字节为单位 _**我不清楚是不是这种问题**_
typedef struct //位图文件头信息
{
int biSize; //结构体字节的总数
int biWidth; // 位图的宽度,以像素为单位
int biHeight; // 位图的高度,以像素为单位
short int biPlanes; // 目标设备的位平面数,必须为1
short int biBitCount; // 每个像素的位数,必须是1(单色)、4(16色)、8(256色)或24(真彩色)
int biCompression; // 位图的压缩类型,必须是0(不压缩)、1(BI-RLE8压缩类型)或2(BI-RLE4压缩类型)
int biSizeImage; // 位图的大小,以字节为单位
int biXPeIsPerMeter; // 位图的目标设备水平分辨率,以每米像素数为单位(水平像素数)
int biYPeIsPerMeter; // 位图的目标设备垂直分辨率,以每米像素数为单位(垂直像素数)
int biClrUsed; // 位图实际使用的颜色表中的颜色变址数,即使用的颜色数
int biClrImpotant; // 位图显示过程中被认为重要颜色的变址数,即所使用的重要颜色数,为0时表示所有颜色都很重要
}INFO; //sizeof(INFO)==40正好为4倍数 **_是否因为此处结构体字节数正好是4的倍数才正常?_**
typedef struct //定义RGBQUAD类型结构体,储存一种颜色信息颜色
{
unsigned char rgbBlue; //蓝色所占比重
unsigned char rgbGreen; //绿色所占比重
unsigned char rgbRed; //红色所占比重
unsigned char rgbReserved; //保留字节
}RGBQUAD; // sizeof(RGBQUAD)==4
int main()
{
HEAD strHead;
INFO strInfo;
RGBQUAD straPla[256]{};
unsigned char strPixel[262144];
char szFilena_1[30] = { "C:\\LENA.BMP" }, szFilena_2[30] = { "C:\\LENA2.BMP"}; //记录要处理的源文件与处理后的目的文件名
ifstream infile;
ofstream outfile;
infile.open(szFilena_1,ios::binary);
outfile.open(szFilena_2, ios::binary);
int nCounti;//用以实现循环中对颜色板数据的读取与写入
//读出原文件头 14字节
infile.read((char*)&strHead.bfType, 2);
infile.read((char*)&strHead.bfSize, 4);
infile.read((char*)&strHead.bfReserved1, 2);
infile.read((char*)&strHead.bfReserved2, 2);
infile.read((char*)&strHead.bfOffBits, 4);
//读出原文件信息头 40字节
infile.read((char*)&strInfo.biSize, 4);
infile.read((char*)&strInfo.biWidth, 4);
infile.read((char*)&strInfo.biHeight, 4);
infile.read((char*)&strInfo.biPlanes, 2);
infile.read((char*)&strInfo.biBitCount, 2);
infile.read((char*)&strInfo.biCompression, 4);
infile.read((char*)&strInfo.biSizeImage, 4);
infile.read((char*)&strInfo.biXPeIsPerMeter, 4);
infile.read((char*)&strInfo.biYPeIsPerMeter, 4);
infile.read((char*)&strInfo.biClrUsed, 4);
infile.read((char*)&strInfo.biClrImpotant, 4);
//读出原文件颜色板 //颜色板也没有错位
for (nCounti = 0; nCounti < 256; nCounti++)
{
infile.read((char*)&straPla[nCounti], 4);
}
//读取位图数据 //位图数据也没有出现错位
for (nCounti = 0; nCounti < 262144; nCounti++)
{
infile.read((char*)&strPixel[nCounti], 1);
}
//写入文件头
outfile.write((char*)&strHead, 14);
//写入文件信息头
outfile.write((char*)&strInfo, 40);
//写入颜色板
for (nCounti = 0; nCounti < 256; nCounti++)
{
outfile.write((char*)&straPla[nCounti], 4);
}
//写入位图数据
for (nCounti = 0; nCounti < 262144; nCounti++)
{
outfile.write((char*)&strPixel[nCounti], 1);
}
//控制台输出文件信息
cout << "bfType:" << strHead.bfType << endl;
cout << "bfSize:" << strHead.bfSize << endl;
cout << "bfReserved1:" << strHead.bfReserved1 << endl;
cout << "bfReserved2:" << strHead.bfReserved2 << endl;
cout << "bfOffBits:" << strHead.bfOffBits << endl;
cout << "biSize :" << strInfo.biSize << endl;
cout << "biWidth :" << strInfo.biWidth << endl;
cout << "biHeight :" << strInfo.biHeight << endl;
cout << "biPlanes :" << strInfo.biPlanes << endl;
cout << "biBitCount :" << strInfo.biBitCount << endl;
cout << "biCompression:" << strInfo.biCompression << endl;
cout << "biSizeImage :" << strInfo.biSizeImage << endl;
cout << "biXPeIsPerMeter :" << strInfo.biXPeIsPerMeter << endl;
cout << "biYPeIsPerMeter:" << strInfo.biYPeIsPerMeter << endl;
cout << "biClrUsed :" << strInfo.biClrUsed << endl;
cout << "biClrImpotant :" << strInfo.biClrImpotant << endl;
return 0;
}
运行结果
无报错,控制台输出:
原BMP位图 LENA.BMP以16进制打开:
创建的BMP位图LENA2.BMP以16进制打开:
尝试过的方法
将写入文件头结构体 Head部分改为:
//写入文件头
outfile.write((char*)&strHead.bfType, 2);
outfile.write((char*)&strHead.bfSize, 4);
outfile.write((char*)&strHead.bfReserved1, 2);
outfile.write((char*)&strHead.bfReserved2, 2);
outfile.write((char*)&strHead.bfOffBits, 4);
所创建的BMP位图 LENA2.BMP能正常打开而且与原文件一模一样(本笨蛋只能想到这个.)
希望的解决方案:
就是想知道这种问题出在哪。凡是字节数为4的倍数都没有多字节的问题.
以及范式的编程方法.