当在Release中作为QImage加载时,相同的图像具有不同的像素数据

Har*_*rry 3 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 << 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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

几点说明:

  • 当使用时将图像的格式更改为例如QImage :: Format_ARGB32时,这不再可再现 convertToFormat
  • pixelIndex用于比较每个像素时,这不再可再现
  • 总是失败的索引相同
  • 在不同的计算机上运行时失败的索引会发生更改.

我目前的猜测是,当以这种格式加载图像时,Qt会做一些优化.我无法解释为什么这不会导致两个相同图像的相同数据.

如果您想重现问题,这是我的输入图像:

样本图片

pad*_*ddy 5

我想我可以看到这里发生了什么.

您的图像是8位灰度,宽度为127像素.发生差异的所有索引都是128的倍数(减1, 128字节行中的最后一列).由于您已获得原始图像位,因此图像中的行数据最有可能对齐(通常为2或4个字节).

Qt可能没有在这些填充字节中写入任何内容,因为它们不被视为图像的一部分.所以你真的看到了未定义的行为,因为你的程序无法保证可重复的结果(从未初始化的内存位置加载数据).

要正确比较图像数据,您需要跳过任何填充字节.这意味着你需要知道填充量.鉴于Qt库的丰富性,我确信会有一些方法来访问或推断该信息.

[编辑]我很快查找了QImage的参考,实际上我可以看到扫描线是32位对齐的.实现比较的最简单方法是调用QImage::bytesPerLine()以确定每个扫描线要比较的字节数,然后通过单独获取每个扫描线QImage::scanLine(int)