【问题标题】:python - Steganography - UnicodeDecode Errorpython - 隐写术 - UnicodeDecodeError
【发布时间】:2017-11-05 21:05:02
【问题描述】:

我正在编写一个 Python 脚本来隐藏图像中的数据。它基本上隐藏了.PNG中每个像素的RGB映射中红色的最后两位中的位。该脚本适用于小写字母,但会产生带有句号的错误。它会产生这个错误:

Traceback(最近一次调用最后一次):文件 “E:\Python\Steganography\main.py”,第 65 行,在 print(unhide('coded-img.png')) 文件“E:\Python\Steganography\main.py”,第 60 行,取消隐藏 message = bin2str(binary) 文件“E:\Python\Steganography\main.py”,第 16 行,在 bin2str 中 return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode() UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 6:无效的起始字节

这是我的代码:

from PIL import Image

def str2bin(message):
    binary = bin(int.from_bytes(message.encode('utf-8'), 'big'))
    return binary[2:]

def bin2str(binary):
    n = int(binary, 2)
    return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode()

def hide(filename, message):
    image = Image.open(filename)
    binary = str2bin(message) + '00000000'

    data = list(image.getdata())

    newData = []

    index = 0
    for pixel in data:
        if index < len(binary):
            pixel = list(pixel)
            pixel[0] >>= 2
            pixel[0] <<= 2
            pixel[0] += int('0b' + binary[index:index+2], 2)
            pixel = tuple(pixel)
            index += 2

        newData.append(pixel)

    print(binary)

    image.putdata(newData)
    image.save('coded-'+filename, 'PNG')

def unhide(filename):
    image = Image.open(filename)
    data = image.getdata()

    binary = '0'

    index = 0

    while binary[-8:] != '00000000':
        binary += bin(data[index][0])[-2:]
        index += 1

    binary = binary[:-1]

    print(binary)
    print(index*2)

    message = bin2str(binary)
    return message


hide('img.png', 'alpha.')
print(unhide('coded-img.png'))

请帮忙。谢谢!

【问题讨论】:

    标签: python python-3.x steganography


    【解决方案1】:

    您的代码至少有两个问题。

    第一个问题是您的编码可能会错位 1 位,因为 bin() 函数的输出中不包含前导空位:

    >>> bin(int.from_bytes('a'.encode('utf-8'), 'big'))[2:]
    '1100001'
    # This string is of odd length and (when joined with the terminating '00000000')
    # turns into a still odd-length '110000100000000' which is then handled by your
    # code as if there was an extra trailing zero (so that the length is even).
    # During decoding you compensate for that effect with the
    #
    #       binary = binary[:-1]
    #
    # line. The latter is responsible for your stated problem when the binary
    # representation of your string is in fact of even length and doesn't need
    # the extra bit as in the below example:
    >>> bin(int.from_bytes('.'.encode('utf-8'), 'big'))[2:]
    '101110'
    

    您最好通过在前面添加一个额外的空位(如果需要)来补充二进制字符串的长度。

    另一个问题是,在恢复隐藏消息时,停止条件 binary[-8:] == '00000000' 可以通过将一个(部分恢复)符号的前导位连接到另一个符号的尾随位来过早地满足。例如,在以下情况下可能会发生这种情况

    • 符号 @(ASCII 码=64,即未设置 6 个低位)后跟任何 ASCII 码值小于 64 的字符(即未设置 2 个最高位) );

    • 一个空格字符(ASCII 码=32,即 4 个低位未设置)后跟换行符/换行符(ASCII 码=10,即 4 个高位未设置)。

    您可以通过要求在最后 8 位似乎全部未设置时解码完整字节来修复该错误:

    while not (len(binary) % 8 == 0 and binary[-8:] == '00000000'):
        # ...
    

    【讨论】:

    • 非常感谢。尤其是第二个技巧,我已经完全看过了,以后会出现很多错误。谢谢。
    猜你喜欢
    • 2013-05-26
    • 1970-01-01
    • 2014-07-11
    • 2020-03-12
    • 2011-02-17
    • 2011-06-06
    • 2014-06-04
    • 2014-10-04
    相关资源
    最近更新 更多