【python】图片隐写术的简单实现

逻辑非常简单,需要numpy pillow库,需要位运算基础,直接上代码:

from PIL import Image
import numpy as np


def pack(img: np.ndarray[np.uint8], text: str, encoding: str = 'utf-8') -> np.ndarray[np.uint8]:
    img_shape = img.shape  # 存储原始图片大小
    # 将图片转为[r,g,b,r,g,b,...,r,g,b]形式
    img = img.reshape(img_shape[0]*img_shape[1]*img_shape[2])
    text = list(bytearray(text, encoding))  # 文本转字节串列表
    bytes_long = len(text)  # 文本大小
    # 隐写文本大小
    img[-8] = (img[-8] & 0b1111_1100) | ((bytes_long >> 14) & 0b0000_0011)
    img[-7] = (img[-7] & 0b1111_1100) | ((bytes_long >> 12) & 0b0000_0011)
    img[-6] = (img[-6] & 0b1111_1100) | ((bytes_long >> 10) & 0b0000_0011)
    img[-5] = (img[-5] & 0b1111_1100) | ((bytes_long >> 8) & 0b0000_0011)
    img[-4] = (img[-4] & 0b1111_1100) | ((bytes_long >> 6) & 0b0000_0011)
    img[-3] = (img[-3] & 0b1111_1100) | ((bytes_long >> 4) & 0b0000_0011)
    img[-2] = (img[-2] & 0b1111_1100) | ((bytes_long >> 2) & 0b0000_0011)
    img[-1] = (img[-1] & 0b1111_1100) | ((bytes_long     ) & 0b0000_0011)
    # 隐写文本内容
    for i in range(bytes_long):
        byte = text[i]  # 按字节隐写
        img[i * 4    ] = (img[i * 4    ] & 0b1111_1100) | ((byte >> 6) & 0b0000_0011)
        img[i * 4 + 1] = (img[i * 4 + 1] & 0b1111_1100) | ((byte >> 4) & 0b0000_0011)
        img[i * 4 + 2] = (img[i * 4 + 2] & 0b1111_1100) | ((byte >> 2) & 0b0000_0011)
        img[i * 4 + 3] = (img[i * 4 + 3] & 0b1111_1100) | ((byte     ) & 0b0000_0011)
    img = img.reshape(img_shape)  # 复原图片形状
    return img


def unpack(img: np.ndarray[np.uint8], encoding: str = 'utf-8') -> str:
    # 将图片转为[r,g,b,r,g,b,...,r,g,b]形式
    img = img.reshape(img.shape[0]*img.shape[1]*img.shape[2])
    # 解码文本大小
    bytes_long = (((img[-8] << 14) & 0b1100_0000_0000_0000) |
                  ((img[-7] << 12) & 0b0000_0000_0000_0000) |
                  ((img[-6] << 10) & 0b0000_1100_0000_0000) |
                  ((img[-5] << 8 ) & 0b0000_0011_0000_0000) |
                  ((img[-4] << 6 ) & 0b0000_0000_1100_0000) |
                  ((img[-3] << 4 ) & 0b0000_0000_0011_0000) |
                  ((img[-2] << 2 ) & 0b0000_0000_0000_1100) |
                  ((img[-1]      ) & 0b0000_0000_0000_0011))
    # 按字节复原文本内容
    text = b''
    for i in range(bytes_long):
        byte = img[i * 4:i * 4 + 4]
        byte = (((byte[0] << 6) & 0b1100_0000) | ((byte[1] << 4) & 0b0011_0000) |
                ((byte[2] << 2) & 0b0000_1100) | (byte[3]        & 0b0000_0011))
        text += int(byte).to_bytes()
    text = str(text, encoding=encoding)  # 以特定编码转为字符串
    return text


if __name__ == '__main__':
    # 隐写
    img = Image.open(r"E:\Users\Expector\Desktop\lty.png")
    text = open(r"E:\Users\Expector\Desktop\book.txt", 'r', encoding='utf-8')
    img = Image.fromarray(pack(np.array(img), text.read()))
    img.save(r"E:\Users\Expector\Desktop\lty.c.png")

    # 解密
    img = Image.open(r"E:\Users\Expector\Desktop\lty.c.png")
    text = open(r"E:\Users\Expector\Desktop\book.c.txt", 'w', encoding='utf-8')
    text.write(unpack(np.array(img)))

附图:

pillow·python·numpy
298 views
Comments
登录后评论
Sign In
·

什么是图片隐写术?