1

QImage 的 CacheKey 方法实际上返回的不是图像的普通哈希。有谁知道,高32位是什么意思?在比较两张图片时我真的可以忽略它们吗?(只比较低 32 位?)


仅用于说明,此代码多次读取同一图像(但将它们存储在不同的 QImage 对象中):

printf("%llx\n",QImage("image.png").cacheKey());
printf("%llx\n",QImage("image.png").cacheKey());
printf("%llx\n",QImage("image.png").cacheKey());

返回这个?

144300000002
144400000002
144500000002

或这个?(似乎高 32 位取决于当前内存位置)

140800000002
140900000002
140a00000002
4

3 回答 3

3

不,您不能使用 的任何部分cacheKey来比较图像内容,它的存在只是为了确保图像自上次cacheKey获取值以来没有更改。它标识缓冲区并在调用任何非常量函数时更改QImage

但是正如cacheKey属性的名称所暗示的那样,您可以将其用作QCache<qint64, QByteArray>存储图像实际哈希值的键,QCryptographicHash只有在图像发生更改时才会重新计算(= 仅当它尚未在缓存)。

QImage不像QPixmap读取图像那样使用缓存,因此读取 3 次相同的图像文件将分配 3 个不同的缓冲区,每次使用不同的cacheKey. 为避免每次都计算哈希值,您应该查看QPixmap::load函数的源代码。

于 2013-08-23T21:24:52.523 回答
2

高 32 位不依赖于任何东西,而是依赖于前一个图像的 32 位。它是一个序列号,随着每个新的 QImage 递增。

于 2013-08-23T15:20:09.863 回答
1

查看QImage的来源:

qint64 QImage::cacheKey() const
{
    if (!d)
        return 0;
    else
        return (((qint64) d->ser_no) << 32) | ((qint64) d->detach_no);
}

看起来高 32 位是用 QImageData 初始化的 d->ser_no:

QBasicAtomicInt qimage_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1);

QImageData::QImageData()
    : ref(0), width(0), height(0), depth(0), nbytes(0), data(0),
#ifdef QT3_SUPPORT
      jumptable(0),
#endif
      format(QImage::Format_ARGB32), bytes_per_line(0),
      ser_no(qimage_serial_number.fetchAndAddRelaxed(1)),
      detach_no(0),
      dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
      dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
      offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false),
      is_cached(false), paintEngine(0)
{
}

看起来 QBasicAtomicInt 是一个原子引用计数器(见这里)。所以看起来每个新图像在缓存键值中都有不同的高 32 位,除非你复制它而不是重新创建它。

于 2013-08-23T15:27:12.273 回答