首页 > 解决方案 > 将 float32 转换为位等效的 int32

问题描述

Python 中的 Pillow 模块坚持打开我拥有的 32 位/像素 TIFF 文件,就好像像素是 float32 类型一样,而我相信正确的解释是 unsigned int32。如果我继续将数据加载到 float32 类型的 640x512 数组中,如何在保留底层二进制表示的同时将其重新键入为 uint32?

在 Fortran 和 C 中,很容易让不同类型的指针或数据结构指向同一个物理内存块,以便可以根据我想要的任何类型轻松解释原始内存内容。Python中是否有等效的程序?

示例如下(请注意,我没有关于压缩等的信息;有问题的文件是由商业软件程序从专有文件格式中提取的):

from PIL import Image

infile = "20181016_071207_367_R.tif"        
im = Image.open(infile)

data = np.array(im.getdata())
print(data)

[ -9.99117374 -10.36103535 -9.80696869 ... -18.41988373 -18.35027885 -18.69905663]

标签: pythonimagetypesbinarytype-conversion

解决方案


假设您im.mode最初等于F,您可以强制 Pillow 在不同的模式下重新加载相同的数据(确实是一个非常不寻常的愿望),以一种有点骇人听闻的方式:

imnew = im.convert(mode='I')
imnew.frombytes(im.tobytes())

更一般地(在 PIL 的上下文之外),每当您遇到需要在 Python 中处理原始内存表示时,您通常应该依赖于numpy或 Python 的内置memoryview类与struct模块。

这是一个将 numpy 数组重新解释为的float32示例int32

a = np.array([1.0, 2.0, 3.0], dtype='float32')
a_as_int32 = a.view('int32')

以下是使用 执行相同操作的示例memoryview

# Create a memory buffer
b = bytearray(4*3)

# Write three floats
struct.pack_into('fff', b, 0, *[1.0, 2.0, 3.0])

# View the same memory as three ints
mem_as_ints = memoryview(b).cast('I')

推荐阅读