python - 隐写术 - UnicodeDecodeError
python - Steganography - UnicodeDecode Error
我正在编写 Python 脚本来隐藏图像中的数据。它基本上隐藏了 .PNG 中每个像素的 RGB 图中红色的最后两位中的位。该脚本适用于小写字母,但会产生带有句号的错误。它会产生此错误:
Traceback (most recent call last): File
"E:\Python\Steganography\main.py", line 65, in
print(unhide('coded-img.png')) File "E:\Python\Steganography\main.py", line 60, in unhide
message = bin2str(binary) File "E:\Python\Steganography\main.py", line 16, in bin2str
return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode() UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position
6: invalid start byte
这是我的代码:
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'))
请帮忙。谢谢!
您的代码至少有两个问题。
第一个问题是您的编码可能会错位 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 个最高位);
一个space字符(ASCII码=32,即4个低位未设置)后跟一个linefeed/newline字符(ASCII码=10,即4个高位)订单位未设置)。
您可以通过要求在最后 8 位似乎都未设置时解码完整字节来修复该错误:
while not (len(binary) % 8 == 0 and binary[-8:] == '00000000'):
# ...
我正在编写 Python 脚本来隐藏图像中的数据。它基本上隐藏了 .PNG 中每个像素的 RGB 图中红色的最后两位中的位。该脚本适用于小写字母,但会产生带有句号的错误。它会产生此错误:
Traceback (most recent call last): File "E:\Python\Steganography\main.py", line 65, in print(unhide('coded-img.png')) File "E:\Python\Steganography\main.py", line 60, in unhide message = bin2str(binary) File "E:\Python\Steganography\main.py", line 16, in bin2str return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode() UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 6: invalid start byte
这是我的代码:
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'))
请帮忙。谢谢!
您的代码至少有两个问题。
第一个问题是您的编码可能会错位 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 个最高位);
一个space字符(ASCII码=32,即4个低位未设置)后跟一个linefeed/newline字符(ASCII码=10,即4个高位)订单位未设置)。
您可以通过要求在最后 8 位似乎都未设置时解码完整字节来修复该错误:
while not (len(binary) % 8 == 0 and binary[-8:] == '00000000'):
# ...