1

在应用程序启动时,我构建了一个图标缓存(24x24 32bbp 预乘 argb 位图)。这个缓存包含大约一千个项目。出于内存和性能原因,我不想在此缓存中多次存储相同的图像。我认为最好的方法是在每个位图进入缓存时从它创建某种类型的 crc,并将新位图与这个 crcs 列表进行比较。

从仅加载在内存中的位图创建 crc 的好(和快速)方法是什么?

还是我完全走错了路,有没有更好的方法来构建位图缓存?

4

2 回答 2

2

虽然我会回应 Hans 所说的话,但我相信你可以做到这一点,但 CRC 是一种不好使用的算法。

您可以改为创建生成位图字节的 MD5 散列。根据我的计算,您的图像大小必须至少为 2Kb。要生成散列,您可以在整个位图上计算它,或者您可以偷偷摸摸地在每个第n个字节上执行它 - 这在散列方面会更快,但可能会增加内存使用量,因为您必须提取那些字节到一个新的数组。

如果您要跳过每第 n 个字节,我会使用 4 或 2 - 使用 4 意味着您从每个连续像素中读取一个分量,使用两个意味着您从每个连续像素中读取两个分量。

但是,MD5非常快,您可能会发现(我会在单元测试中对此进行基准测试)仅对整个位图进行散列会更快。

唯一的事情是,我看不出如何在事先不知道它的哈希值的情况下提前检查是否应该生成给定的位图,而知道它的哈希值的唯一方法就是生成它。在这种情况下,您不妨将新图像保存出来。图像缓存数组中的额外元素不会破坏宇宙。

为了真正节省空间和启动时间,您真正需要做的是在生成图像之前知道它是否与另一个图像相同。鉴于这些图像是动态生成的,当生成两个相同的图像时,它们是由具有相同参数的相同方法调用生成的吗?

如果是这样,您可以改为查看为生成图像的方法的一个或多个哈希码(使用object.GetHashCode())标记每个生成MethodInfo的图像(您可以通过调用在方法本身内部获取它MethodBase.GetCurrentMethod(),以及每个参数的每个哈希码)方法的哈希码非常可靠,因为它使用运行时的方法句柄(每个方法都是唯一的)——唯一可能发生的哈希码压缩出现在句柄为 64 位的 64 位机器上,但是哈希码是 32。但是,实际上这种冲突很少发生,因为您必须在应用程序中拥有大量代码才能使两个单独的方法句柄的前 32 位相同。

当然,除非这些参数类型具有良好的散列码函数,否则各个参数的散列码的可靠性要低得多。

这个解决方案绝不是完美的(最坏的情况下你仍然会得到一些重复),但我认为它会加快速度。不过,就像我说的那样,它依赖于您的重复图像总是由相同的调用生成。

于 2010-07-14T09:43:12.620 回答
1

CRC 与任何散列函数具有相同的缺陷:相同的 CRC 值并不能证明图像是相同的。您的程序会随机但很少显示错误的图像。

你需要别的东西。就像您从中检索位图的文件名一样。

于 2010-07-13T18:53:45.223 回答