Files
CourseWork/core/lsb.py
Игорь a5b932c6fa сделал модуль LSB
добавил уточнения в gitignore
2026-03-24 22:56:32 +03:00

134 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Модуль LSB (Least Significant Bit) стеганографии.
Скрывает текст в изображении путем замены последних битов пикселей.
Каждый пиксель RGB хранит 3 бита информации (по одному в каждом канале).
"""
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.
Алгоритм:
1. Преобразует текст в битовую строку
2. Добавляет стоп-маркер (8 нулевых битов) для обозначения конца
3. Проходит по всем пикселям изображения
4. В каждом канале (R,G,B) заменяет последний бит на бит сообщения
Аргументы:
image_path (str): Путь к исходному изображению
message (str): Текст для сокрытия
output_path (str): Путь для сохранения результата
Возвращает:
bool: True если успешно, False если сообщение слишком длинное
"""
# Загружаем изображение
img = Image.open(image_path).convert('RGB')
pixels = np.array(img, dtype=np.uint8)
height, width, channels = pixels.shape
# Преобразуем сообщение в биты и добавляем стоп-маркер
bits = text_to_bits(message) + '00000000'
# Проверяем, поместится ли сообщение
max_bits = height * width * channels
if len(bits) > max_bits:
print(f"Ошибка: сообщение слишком большое.")
print(f"Доступно битов: {max_bits}, требуется: {len(bits)}")
return False
# Прячем биты в изображение
bit_index = 0
total_bits = len(bits)
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 = int(bits[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.
Алгоритм:
1. Проходит по всем пикселям изображения
2. Из каждого канала извлекает последний бит
3. Собирает биты в байты
4. Останавливается при обнаружении стоп-маркера (8 нулевых битов)
Аргументы:
image_path (str): Путь к изображению со скрытым сообщением
Возвращает:
str: Извлеченное сообщение
"""
# Загружаем изображение
img = Image.open(image_path).convert('RGB')
pixels = np.array(img, dtype=np.uint8)
height, width, channels = pixels.shape
# Извлекаем биты
extracted_bits = []
stop_counter = 0
stop_marker_length = 8
for i in range(height):
for j in range(width):
for c in range(channels):
# Извлекаем последний бит
bit = pixels[i, j, c] & 1
extracted_bits.append(bit)
# Проверяем стоп-маркер
if bit == 0:
stop_counter += 1
if stop_counter == stop_marker_length:
# Убираем стоп-маркер из результата
extracted_bits = extracted_bits[:-stop_marker_length]
break
else:
stop_counter = 0
if stop_counter == stop_marker_length:
break
if stop_counter == stop_marker_length:
break
if len(extracted_bits) == 0:
return ""
# Преобразуем биты в строку и декодируем
bits_string = ''.join(str(bit) for bit in extracted_bits)
try:
return bits_to_text(bits_string)
except Exception as e:
print(f"Ошибка при декодировании: {e}")
return ""