我正在尝试使用 Python 和图像/gif 文件及其 .bin 或 .dat 表示形式。例如,我想获取一个 PNG 文件,将其转换为它的 .bin 或 .dat 文件(它的二进制版本),然后做一些操作来处理图像,例如将它从灰度转换为黑白,或者拍摄黑白图像并将所有 0 和 1 反转,使黑色部分变为白色,白色部分变为黑色,然后将其转换回实际图像/gif。例如,对这张 PNG 图像进行黑白翻转:
这有点像实践教育练习,以更好地理解图像和二进制之间的关系。
我想使用 Python 标准库函数来执行此操作,类似于 C 中可用的函数。我不想使用 numpy 或 opencv 等外部库。
我似乎找不到任何可以直接解释这一点的资源。我该怎么做?
这是我到目前为止尝试过的:
import base64
with open("984269812_1.png", "rb") as f:
png_encoded = base64.b64encode(f.read())
encoded_b2 = "".join([format(n, '08b') for n in png_encoded])
print(encoded_b2)
flippedBinary = ''.join('1' if x == '0' else '0' for x in encoded_b2)
print(flippedBinary)
# first split into 8-bit chunks
bit_strings = [flippedBinary[i:i + 8] for i in range(0, len(flippedBinary), 8)]
# then convert to integers
byte_list = [int(b, 2) for b in bit_strings]
with open('byte.dat', 'wb') as f:
f.write(bytearray(byte_list)) # convert to bytearray before writing
这只是反转前一个图像的位并生成一个 .dat 文件。我无法将其转换回 PNG 图像,我不确定我是否在正确的轨道上。
假设您有彩色或灰度 PNG/GIF/JPEG 图像,您可以在终端中使用 ImageMagick 将其转换为灰度 1 字节/像素 BIN 文件,如下所示:
magick IMAGE.JPG -colorspace gray -depth 8 GRAY:IMAGE.BIN
如果您的输入图像为 60x40,则您的 BIN 文件将为 2,400 字节或 1 字节/像素。如果您的图像是黑色的,则所有字节都将为零。如果它是白色的,它们都是 255.
现在做你的 Python 事情,记得打开
"rb"
标志用于二进制读取 "IMAGE.BIN"
和 "wb"
标志用于将处理后的数据二进制写入 "PROCESSED.BIN"
在我的脑海中,未经测试,反转图像的 Python 看起来像:
with open("IMAGE.BIN", "rb") as in, open("PROCESSED.BIN", "wb") as out:
while True:
# Read 1 pixel
b = in.read(1)
if b is null:
break
# Write inverted pixel
out.write(255-b)
将处理后的数据转换回最终的 PNG/GIF/JPEG 结果:
magick -depth 8 -size 60x40 GRAY:PROCESSED.BIN result.png
注意从原始二进制文件转换时(与 PNG/JPEG 不同,它在图像宽度和高度的开头没有元数据),您需要告诉 ImageMagick 尺寸。
如果你想尝试使用标题和元数据解码/编码正确的图像,我建议你先尝试 PGM 格式,因为它很容易。 Adobe Photoshop、QuickLook/Preview、GIMP、
feh
等可以读写。所以你会从 PNG/JPEG 到 PGM 与:
magick IMAGE.PNG -colorspace gray -depth 8 IMAGE.PGM
现在做你的 Python 处理,记得处理标题,然后返回 PNG/JPEG:
magick PROCESSED.PGM result.png
请注意,您不再需要告诉 ImageMagick 宽度和高度,因为它们在 PGM 标题中。
一旦理解了 8 位 PGM,就可以转向 16 位 PGM。然后你可以去PPM格式来支持颜色。
请注意,如果您安装了旧版本 6 ImageMagick,您需要在我的回答中从
magick
更改为 convert
- 或者,最好升级到 v7.
请注意,我在此答案中使用的所有 ImageMagick 命令同样可以使用
ffmpeg
表示,如果这更接近您的心。