сделал модуль LSB

добавил уточнения в gitignore
This commit is contained in:
Игорь
2026-03-24 22:56:32 +03:00
parent 56ff6d2492
commit a5b932c6fa
2 changed files with 141 additions and 1 deletions

6
.gitignore vendored
View File

@@ -17,3 +17,9 @@ output.txt
# OS
.DS_Store
Thumbs.db
# Тестовые файлы
test_image.png
encoded_lsb.png
test_*.png
*_lsb.png

View File

@@ -0,0 +1,134 @@
"""
Модуль 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 ""