使用PIL模块处理64×64图像编解码失败,16×16图像正常
问题分析与修复方案
你的代码在处理64×64图像时失效,核心是几个关键bug,16×16图像因数据量小刚好没触发明显错误,下面逐个说明并给出修复后的代码:
主要问题点
编码时二进制未补全8位
decimalToBinary函数返回的二进制字符串长度不固定(比如数字5会变成101而不是00000101),导致整个二进制文本总长度不是「像素数×24」(每个RGB通道各占8位)。64×64图像有4096个像素,需要98304位二进制数据,编码时长度不足会让解码拆分RGB值错位,甚至出现空字符串引发转换错误。解码时像素索引计算错误
解码循环里用column*row作为pixellist的索引完全错误,正确索引要对应编码的遍历顺序:编码按「列→行」遍历,每个像素的索引应为column * height + row,用column*row会导致索引跳变、重复甚至越界(比如column=63、row=63时索引是3969,而实际最大索引是4095)。无效的像素过滤逻辑
解码时pixellist = [i for i in pixellist if i != ['','','',]]不仅语法错误(列表多了一个逗号),编码过程也不会生成空值像素列表,反而可能误删有效数据。
修复后的编码脚本
from PIL import Image input_image = Image.open("image.png") width, height = input_image.size binarylist = [] def decimalToBinary(n): # 补前导零到8位,确保每个通道占满8位 return bin(n).replace("0b", "").zfill(8) # 按列→行的顺序遍历像素,和解码逻辑对齐 for i in range(width): for j in range(height): r, g, b = input_image.getpixel((i, j)) binarylist.extend([decimalToBinary(r), decimalToBinary(g), decimalToBinary(b)]) with open('encimg.txt', 'w') as f: # 直接拼接所有二进制字符串写入,效率更高 f.write(''.join(binarylist))
修复后的解码脚本
from PIL import Image img = Image.open('image.png') pixel_map = img.load() width, height = img.size pixellist = [] def binaryToDecimal(n): return int(n, 2) with open('encimg.txt', 'r') as f: content = f.read() # 按每个像素24位拆分,确保遍历所有像素 total_pixels = width * height for i in range(total_pixels): # 计算当前像素的二进制起始位置 start = i * 24 red = content[start:start+8] green = content[start+8:start+16] blue = content[start+16:start+24] pixel = [binaryToDecimal(red), binaryToDecimal(green), binaryToDecimal(blue)] pixellist.append(pixel) # 按列→行的顺序写入像素,对应编码顺序 for column in range(width): for row in range(height): idx = column * height + row pixel_map[column, row] = tuple(pixellist[idx]) img.save('newimage.png', format='png')
额外优化说明
- 编码时用
''.join(binarylist)一次性写入文件,比循环写入效率高很多 - 解码时直接按总像素数计算拆分位置,避免依赖
len(content)/24的浮点计算误差 - 统一了文件名拼写(原编码脚本写的
images.png,解码是image.png,避免找不到文件)
内容的提问来源于stack exchange,提问作者BitDev
相关产品推荐
相关产品推荐

