Files
CourseWork/core/lsb.py

95 lines
3.3 KiB
Python

"""
Модуль LSB (Least Significant Bit) стеганографии.
Поддержка цветных изображений и русских текстов.
"""
import numpy as np
from PIL import Image
from .utils import text_to_bits, bits_to_text
def encode_lsb(image_path: str, message: str, output_path: str) -> bool:
"""Скрывает сообщение в изображении методом LSB."""
img = Image.open(image_path).convert('RGB')
pixels = np.array(img, dtype=np.uint8)
height, width, channels = pixels.shape
# Формат: [длина сообщения: 32 бита] + [сообщение]
msg_bytes = message.encode('utf-8')
msg_length = len(msg_bytes)
length_bits = format(msg_length, '032b')
message_bits = text_to_bits(message)
all_bits = length_bits + message_bits
bit_list = [int(b) for b in all_bits]
total_bits = len(bit_list)
# Проверка вместимости
max_bits = height * width * channels
if total_bits > max_bits:
print(f"Ошибка: сообщение слишком большое.")
print(f"Доступно: {max_bits} бит, требуется: {total_bits}")
return False
# Внедрение битов
bit_index = 0
for i in range(height):
for j in range(width):
for c in range(channels):
if bit_index >= total_bits:
break
pixel_value = pixels[i, j, c]
bit = bit_list[bit_index]
pixels[i, j, c] = (pixel_value & 0xFE) | bit
bit_index += 1
if bit_index >= total_bits:
break
if bit_index >= total_bits:
break
result_img = Image.fromarray(pixels, mode='RGB')
result_img.save(output_path)
print(f"Успешно! Спрятано {total_bits} бит ({total_bits // 8} байт)")
return True
def decode_lsb(image_path: str) -> str:
"""Извлекает сообщение из изображения методом LSB."""
img = Image.open(image_path).convert('RGB')
pixels = np.array(img, dtype=np.uint8)
height, width, channels = pixels.shape
# Извлекаем все биты
all_bits = []
for i in range(height):
for j in range(width):
for c in range(channels):
all_bits.append(pixels[i, j, c] & 1)
# Читаем длину сообщения (первые 32 бита)
if len(all_bits) < 32:
return ""
length_bits = all_bits[:32]
length_str = ''.join(str(b) for b in length_bits)
msg_length = int(length_str, 2)
# Проверяем, что длина разумная
if msg_length > (len(all_bits) - 32) // 8:
return ""
# Читаем сообщение
message_bits = all_bits[32:32 + msg_length * 8]
# Дополняем до кратности 8 (на всякий случай)
remainder = len(message_bits) % 8
if remainder != 0:
message_bits.extend([0] * (8 - remainder))
if len(message_bits) == 0:
return ""
bits_string = ''.join(str(b) for b in message_bits)
try:
return bits_to_text(bits_string)
except Exception as e:
print(f"Ошибка при декодировании: {e}")
return ""