LSB(最低有效位)隐写插件
| 14 | |
| 15 | |
| 16 | class LSBPlugin(StegaPyPlugin): |
| 17 | """LSB(最低有效位)隐写插件""" |
| 18 | |
| 19 | NAMESPACE = "LSB" |
| 20 | |
| 21 | def __init__(self, config: Optional[LSBConfig] = None): |
| 22 | """初始化LSB插件""" |
| 23 | super().__init__(config or LSBConfig()) |
| 24 | |
| 25 | def get_name(self) -> str: |
| 26 | """获取插件名称""" |
| 27 | return "LSB" |
| 28 | |
| 29 | def get_purposes(self) -> List[Purpose]: |
| 30 | """获取插件支持的用途""" |
| 31 | return [Purpose.DATA_HIDING] |
| 32 | |
| 33 | def get_description(self) -> str: |
| 34 | """获取插件描述""" |
| 35 | return "LSB(最低有效位)隐写算法,将数据隐藏在图像像素的最低有效位中" |
| 36 | |
| 37 | def embed_data(self, msg: bytes, msg_filename: Optional[str], |
| 38 | cover: Optional[bytes], cover_filename: Optional[str], |
| 39 | stego_filename: Optional[str]) -> bytes: |
| 40 | """嵌入数据到封面图像""" |
| 41 | try: |
| 42 | # 如果没有提供封面图像,生成随机图像 |
| 43 | if cover is None: |
| 44 | # 计算需要的像素数 |
| 45 | from .lsb_data_header import LSBDataHeader |
| 46 | header_size = LSBDataHeader.get_max_header_size() |
| 47 | num_pixels = int(header_size * 8 / 3.0) |
| 48 | num_pixels += int(len(msg) * 8 / (3.0 * self.config.get_max_bits_used_per_channel())) |
| 49 | image = ImageUtil.generate_random_image(num_pixels) |
| 50 | else: |
| 51 | image = ImageUtil.byte_array_to_image(cover, cover_filename) |
| 52 | |
| 53 | # 使用LSB输出流嵌入数据 |
| 54 | lsb_os = LSBOutputStream(image, len(msg), msg_filename, self.config) |
| 55 | lsb_os.write(msg) |
| 56 | lsb_os.flush() |
| 57 | image = lsb_os.get_image() |
| 58 | |
| 59 | return ImageUtil.image_to_byte_array(image, stego_filename) |
| 60 | except Exception as e: |
| 61 | raise StegaPyException(str(e), StegaPyErrors.UNHANDLED_EXCEPTION, self.NAMESPACE) |
| 62 | |
| 63 | def extract_msg_filename(self, stego_data: bytes, |
| 64 | stego_filename: Optional[str]) -> str: |
| 65 | """从隐写数据中提取消息文件名""" |
| 66 | try: |
| 67 | image = ImageUtil.byte_array_to_image(stego_data, stego_filename) |
| 68 | lsb_is = LSBInputStream(image, self.config) |
| 69 | return lsb_is.get_data_header().get_filename() |
| 70 | except Exception as e: |
| 71 | raise StegaPyException(str(e), StegaPyErrors.UNHANDLED_EXCEPTION, self.NAMESPACE) |
| 72 | |
| 73 | def extract_data(self, stego_data: bytes, stego_filename: Optional[str], |
no outgoing calls