#!/usr/bin/env -S uv run --script # /// script # requires-python = ">=3.12" # dependencies = [ # "imagehash" # ] # /// import imagehash import numpy from PIL import Image def from64bit_hash(value: int) -> imagehash.ImageHash: """ Converts a 64-bit unsigned long integer into an ImageHash object. The integer is transformed into a 8x8 binary numpy array, which is the standard representation for many perceptual hashes. :param value: The 64-bit integer hash value. Must be between 0 and 2**64 - 1. :return: An ImageHash object representing the integer. """ if not (0 <= value < 2**64): raise ValueError("Value must be a 64-bit unsigned integer (between 0 and 2**64 - 1).") # 1. Convert the integer to its 64-bit binary string representation. # numpy.binary_repr is perfect for this, as it handles padding. # Example: 1 -> '000...001' binary_string = numpy.binary_repr(value, width=64) # 2. Convert the binary string into a numpy array of booleans. # '1' becomes True, '0' becomes False. binary_array = numpy.array([char == '1' for char in binary_string], dtype=bool) # 3. Reshape the 64-element flat array into a 8x8 matrix. matrix = binary_array.reshape((8, 8), order='F') # 4. Create and return the ImageHash instance. return imagehash.ImageHash(matrix) def to64bit_hash(value: imagehash.ImageHash) -> int: buffer = numpy.packbits(value.hash.flatten(order='F')) return numpy.frombuffer(buffer, dtype='>u8').item() if __name__ == '__main__': ph = imagehash.phash(Image.open('peppers.png')) x = to64bit_hash(ph) #round trip test print(ph == from64bit_hash(x))