xmp文件由文件头和数据体构成,文件头固定8个字节,前4个字节是宽度,后4个字节是高度,小端字节序。
首先打开文件第一步是解析文件头,拿到宽度width和高度height,计算一下理论图像数据大小:imgSize=width*height*3。
接下来读取剩余的内容,大小记为dataSize。
这时候观察imgSize和dataSize,会发现3种情况:
1.dataSize等于imgSize
这是最理想的情况,按照标准bmp的方式读取图像即可
2.dataSize略微大于imgSize
计算并观察(dataSize-imgSize)/height,会发现余数可能是1,2,3,记为padding
这个可以理解为图像每一行数据之后加了padding个字节的无效数据,因此需要在标准bmp方式读取的基础上,在每一行读取完成之后,手动跳过padding个字节
3.dataSize远远大于imgSize
说明这个文件实际上还夹带了一个隐藏图片,前面文件头里面读到的height是假的,但是width是真的,所以重新计算height=dataSize/3/width
接下来再按照标准bmp的方式读取图像,会发现上下两张图片叠在一起了
关键代码展示:
file.seek(8);
auto d = file.read(readSize);
img = QImage(width, height, QImage::Format_RGB888);
int index = 0;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int b = data[index + 0];
int g = data[index + 1];
int r = data[index + 2];
img.setPixel(x, height - 1 - y, qRgb(r, g, b));
index += 3;
}
index += padding;
}
首先打开文件第一步是解析文件头,拿到宽度width和高度height,计算一下理论图像数据大小:imgSize=width*height*3。
接下来读取剩余的内容,大小记为dataSize。
这时候观察imgSize和dataSize,会发现3种情况:
1.dataSize等于imgSize
这是最理想的情况,按照标准bmp的方式读取图像即可
2.dataSize略微大于imgSize
计算并观察(dataSize-imgSize)/height,会发现余数可能是1,2,3,记为padding
这个可以理解为图像每一行数据之后加了padding个字节的无效数据,因此需要在标准bmp方式读取的基础上,在每一行读取完成之后,手动跳过padding个字节
3.dataSize远远大于imgSize
说明这个文件实际上还夹带了一个隐藏图片,前面文件头里面读到的height是假的,但是width是真的,所以重新计算height=dataSize/3/width
接下来再按照标准bmp的方式读取图像,会发现上下两张图片叠在一起了
关键代码展示:
file.seek(8);
auto d = file.read(readSize);
img = QImage(width, height, QImage::Format_RGB888);
int index = 0;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int b = data[index + 0];
int g = data[index + 1];
int r = data[index + 2];
img.setPixel(x, height - 1 - y, qRgb(r, g, b));
index += 3;
}
index += padding;
}