C++ 在版本中加载为QImage时,相同的图像具有不同的像素数据
仅当在释放模式下运行时,比较以QImage::format_Indexed8格式加载的两个相同图像时,其像素数据不同 以下代码显示在Release中运行时的差异,但在Debug中运行时的差异:C++ 在版本中加载为QImage时,相同的图像具有不同的像素数据,c++,qt,qimage,C++,Qt,Qimage,仅当在释放模式下运行时,比较以QImage::format_Indexed8格式加载的两个相同图像时,其像素数据不同 以下代码显示在Release中运行时的差异,但在Debug中运行时的差异: int main() { QImage _img1("C:\\tmp\\diff\\identicals\\file1.png"); QImage _img2("C:\\tmp\\diff\\identicals\\file2.png"); std::cout << QStrin
int main()
{
QImage _img1("C:\\tmp\\diff\\identicals\\file1.png");
QImage _img2("C:\\tmp\\diff\\identicals\\file2.png");
std::cout << QString("Format 1: %1").arg(_img1.format()).toStdString().c_str() << std::endl;
std::cout << QString("Format 2: %2").arg(_img2.format()).toStdString().c_str() << std::endl;
const unsigned char * _bits1 = _img1.bits();
const unsigned char * _bits2 = _img2.bits();
std::cout << QString("Byte count 1: %1 | Byte count 2: %2").arg(_img1.byteCount()).
arg(_img2.byteCount()).toStdString().c_str() << std::endl;
for (int _i = 0; _i < _img1.byteCount(); _i++)
{
if (_bits1[_i] != _bits2[_i])
{
std::cout << "--DIFFERENCE--" << std::endl;
std::cout << QString("i --> %1").arg(_i).toStdString().c_str() << std::endl;
std::cout << QString("Bit1: %1 | Bit2: %2").arg(_bits1[_i]).arg(_bits2[_i]).toStdString().c_str() << std::endl << std::endl;
}
}
std::cout << "BREAK" << std::endl;
}
请注意:
- 使用
convertToFormat
- 当使用
比较每个像素时,这不再是可复制的pixelIndex
- 失败的总是同样的指数
- 在不同的机器上运行时,失败的索引会发生变化
我想我能看到这里发生了什么 您的图像为8位灰度,宽度为127像素。出现差异的所有索引都是128的倍数(减1,即128字节行中的最后一列)。由于已获得原始图像位,因此图像中的行数据很可能是对齐的(通常为2或4字节) Qt可能不会将任何内容写入这些填充字节,因为它们不被视为图像的一部分。因此,您确实看到了未定义的行为,因为您的程序无法保证可重复的结果(从未初始化的内存位置加载数据) 要正确比较图像数据,需要跳过任何填充字节。这意味着您需要知道填充量。考虑到Qt库的丰富性,我相信会有一些方法来访问或推断这些信息
[编辑]我很快查找了QImage的参考,事实上我可以看到扫描线是32位对齐的。实现比较的最简单方法是调用
QImage::bytesPerLine()
来确定每个扫描线要比较的字节数,然后通过QImage::scanline(int)
单独获取每个扫描线图像比较的实现是不正确的。为什么不使用QImage::operator==
?您也可以参考its来了解应该如何做,但这有点毫无意义,因为Qt已经为您提供了这段代码——除非您真正的问题是如何正确地迭代图像中的所有像素,因为这就是错误所在。您的代码具有未定义的行为,因为它可以根据QImage
和C++
语义读取可能从未写入的位置。格式2的打印需要使用%1
,btwu,bytesPerLine
似乎不适合填充,返回8,这意味着比较每条扫描线也会失败。但是,我非常肯定您是正确的,因为像素数据的大小(以字节为单位)正好是图像高度
大于图像宽度x图像高度
。似乎每行有一个字节的填充。然而,奇怪的是,在同一个索引上,比较总是失败的。如果它是由未初始化的内存引起的,我希望它会更随机一些……在我们的E2E测试框架中,该代码用于计算比较两幅图像时的峰值信噪比。因为在我们的架构中没有两个图像完全相同,所以我们允许PSNR阈值。我的问题的解决方案之一是使用像素索引
,我就是这么做的。我的问题的目的是更好地了解Qt在这里做什么@paddy在这方面帮了很多忙,但我仍然无法理解为什么总是相同的索引不同(例如,不是图像的每个128位,而是其中的一个子集)。
Format 1: 3
Format 2: 3
Byte count 1: 23424 | Byte count 2: 23424
--DIFFERENCE--
i --> 1535
Bit1: 0 | Bit2: 217
--DIFFERENCE--
i --> 1663
Bit1: 0 | Bit2: 35
--DIFFERENCE--
i --> 1791
Bit1: 0 | Bit2: 94
--DIFFERENCE--
i --> 1919
Bit1: 0 | Bit2: 166
--DIFFERENCE--
i --> 2047
Bit1: 0 | Bit2: 143
--DIFFERENCE--
i --> 2175
Bit1: 0 | Bit2: 104
--DIFFERENCE--
i --> 2303
Bit1: 0 | Bit2: 240
--DIFFERENCE--
i --> 2431
Bit1: 0 | Bit2: 190
--DIFFERENCE--
i --> 2559
Bit1: 0 | Bit2: 129
--DIFFERENCE--
i --> 2687
Bit1: 0 | Bit2: 11
--DIFFERENCE--
i --> 2815
Bit1: 0 | Bit2: 30
--DIFFERENCE--
i --> 2943
Bit1: 0 | Bit2: 163
--DIFFERENCE--
i --> 3071
Bit1: 0 | Bit2: 206
--DIFFERENCE--
i --> 3199
Bit1: 0 | Bit2: 232
--DIFFERENCE--
i --> 3327
Bit1: 0 | Bit2: 124
--DIFFERENCE--
i --> 3455
Bit1: 0 | Bit2: 225
--DIFFERENCE--
i --> 12287
Bit1: 0 | Bit2: 240
--DIFFERENCE--
i --> 12415
Bit1: 0 | Bit2: 224
--DIFFERENCE--
i --> 12543
Bit1: 0 | Bit2: 240