You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Pillow调用putpixel修改图片像素仅首个像素生效问题

Pillow putpixel仅首个像素修改生效问题修复

问题根因

你的代码存在4个逻辑错误共同导致该现象:

  • 二进制串生成时未补全8位前导零,导致二进制总长度远小于预期,提前触发终止逻辑
  • 处理到文本最后一位时直接return,未将当前已修改的像素写入图片
  • 像素遍历顺序为列优先,和getdata()返回的行优先顺序不一致,导致打印结果和预期对不上
  • 若原图为索引色PNG,直接修改像素值不会生效(该场景概率较高)

修复步骤

  1. 补全二进制串的8位填充
    将原代码的二进制转换逻辑:
text = ''.join(format(x,'b') for x in bytes(text,"ascii"))

修改为:

# 每个ASCII字符固定转换为8位二进制,不足补前导零
text = ''.join(format(x, '08b') for x in bytes(text, "ascii"))
  1. 修正终止逻辑,避免提前返回
    将k循环内的提前return逻辑移到像素写入操作之后,处理完所有文本位后再返回,避免未保存当前像素的修改就退出。

  2. 调整像素遍历顺序为行优先
    将原有的外层x内层y的循环,调整为外层y内层x,和getdata()的顺序保持一致,避免打印结果和预期顺序错位。

  3. 统一图片像素格式
    打开图片后先转为RGBA模式,避免索引色模式下修改像素不生效。

修复后完整代码

from PIL import Image

def encode(text,image):
    pixels = image.load()
    # 补全8位二进制
    text = ''.join(format(x,'08b') for x in bytes(text,"ascii"))
    print(text)
    iteration = 0

    # 调整为行优先遍历,和getdata顺序一致
    for j in range(image.size[1]):
        for i in range(image.size[0]):
            
            tmp = list(pixels[i,j])
            
            for k in range(len(tmp)):
                if iteration >= len(text):
                    break
                
                elif text[iteration]=="0":
                    if tmp[k]%2!=0:
                        if tmp[k]==255:
                            tmp[k]-=1
                        else:
                            tmp[k]+=1
                            
                elif text[iteration]=="1":
                    if tmp[k]%2==0:
                        tmp[k]+=1
                        
                iteration +=1

            # 直接修改load出来的像素对象即可,不需要额外调用putpixel
            pixels[i,j] = tuple(tmp)
            print(f"pixel : {pixels[i,j]}")
            
            # 所有位处理完后返回,避免提前退出
            if iteration >= len(text):
                return image
    return image
    

if __name__ == "__main__":
    img = Image.open("C:/Users/Toavina/Pictures/Crypto/icon.PNG")
    # 转为RGBA模式,避免索引色原图导致修改失效
    img = img.convert("RGBA")
    img = encode("test_data",img)

    # 打印修改后的像素
    for pixel in img.getdata():
        print(pixel)

内容的提问来源于stack exchange,提问作者Toavina Tokiniaina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 04:45:03