Python 3 Pillow图像的Sha256和identify-verbose不相等

Python 3 Sha256 of Pillow image and identify -verbose do not equal

美好的一天!

我可以使用 ImageMagick 获取某些文件的 sha256 哈希值:

$ identify -verbose z.png | rg signature
$ signature: 07f130a92bd1e7a2d3d0c6c8e143cddd3a767cdd365cd055317434ff8197c1a8

但是当我在 Python 3 上使用 Pillow 时:

from PIL import Image
im = Image.open('z.png')

import hashlib
sha=hashlib.sha256(im.tobytes()).hexdigest()
print(sha,'sha256')

>>> 4b705fbc8d6979fdc9a94335a8cf4b870c2424381fd983ec0d520a7383eba994 sha256

程序版本:

Version: ImageMagick 7.1.0-27 Q16-HDRI arm 2022-03-04 https://imagemagick.org
Python 3.9.10
Pillow 9.0.0

如何获得相同的结果? 为什么它们不同?

我不确定这个答案,并且有几天无法使用机器对其进行测试。但是,如果您查看 ImageMagick 安装的版本字符串,您会看到它是 Q16,这意味着 ImageMagick 将每个样本保存在一个 16 位无符号整数中,而 PIL 将为每个样本使用 8 位整数。

我认为解决方案可能是将 ImageMagick 的像素映射到 8 位,或者将 PIL 的像素映射到 16 位。

要将 ImageMagick 的像素向下映射,我想您需要这样的东西:

magick stream -map rgb -storage-type character YOURIMAGE - | sha256sum

或者也许:

magick YOURIMAGE -depth 8 rgb:- | sha256sum

反过来,将 PIL 的 8 位无符号扩展到 16 位,我想你会想要这样的东西:

Im = Image.open(YOURIMAGE).convert('RGB')
Na = np.array(im).astype(np.uint16))

那么你可以使用:

sha=hashlib.sha256(Na.tobytes()).hexdigest()

进一步考虑一下,如果您的 PNG 图像是 16 位 RGB(A),您可能会遇到根本问题,因为 PIL 可能根本不会加载它们。

此外,我不确定如果您的图像是 palette/indexed 图像会发生什么 - 我不知道 ImageMagick 是否仅对索引进行校验和,或者它是否在调色板中查找索引以制作 RGB图像,然后对结果进行校验和。