""" Вспомогательные функции для стеганографии Модуль содержит утилиты для работы с текстом, битами и метриками качества """ import numpy as np from math import log10, sqrt def text_to_bits(text: str) -> str: """ Преобразует текст в строку битов. Аргументы: text (str): Входной текст (например, "Привет") Возвращает: str: Строка из '0' и '1' (например, "11010001...") Пример: >>> text_to_bits("A") '01000001' """ # Кодируем текст в байты (UTF-8 поддерживает русский язык) bytes_data = text.encode('utf-8') # Преобразуем каждый байт в 8-битную строку и объединяем bits = ''.join(format(byte, '08b') for byte in bytes_data) return bits def bits_to_text(bits: str) -> str: """ Преобразует строку битов обратно в текст. Аргументы: bits (str): Строка из '0' и '1' (длина должна быть кратна 8) Возвращает: str: Декодированный текст Пример: >>> bits_to_text("01000001") 'A' """ # Проверяем, что длина строки кратна 8 if len(bits) % 8 != 0: raise ValueError("Длина битовой строки должна быть кратна 8") # Разбиваем строку на блоки по 8 бит и преобразуем в байты bytes_data = bytearray() for i in range(0, len(bits), 8): byte = bits[i:i + 8] # берем 8 бит bytes_data.append(int(byte, 2)) # преобразуем из двоичной в число # Декодируем байты в строку (UTF-8) return bytes_data.decode('utf-8') def calculate_psnr(original_path: str, modified_path: str) -> float: """ Вычисляет PSNR (Peak Signal-to-Noise Ratio) между двумя изображениями. PSNR показывает, насколько сильно изменилось изображение после внедрения. Чем выше значение, тем меньше изменений. - PSNR > 40 dB: отличное качество (изменения практически незаметны) - PSNR 30-40 dB: хорошее качество - PSNR 20-30 dB: заметные искажения - PSNR < 20 dB: сильные искажения Аргументы: original_path (str): Путь к исходному изображению modified_path (str): Путь к измененному изображению Возвращает: float: Значение PSNR в децибелах (dB) """ from PIL import Image # Загружаем изображения img1 = Image.open(original_path).convert('RGB') img2 = Image.open(modified_path).convert('RGB') # Преобразуем в массивы numpy img1_array = np.array(img1, dtype=np.float64) img2_array = np.array(img2, dtype=np.float64) # Вычисляем среднеквадратичную ошибку (MSE) mse = np.mean((img1_array - img2_array) ** 2) # Если MSE = 0, изображения идентичны if mse == 0: return float('inf') # Максимальное значение пикселя (для RGB это 255) max_pixel = 255.0 # Формула PSNR: 10 * log10(MAX^2 / MSE) psnr = 10 * log10((max_pixel ** 2) / mse) return psnr def calculate_capacity(image_path: str) -> int: """ Рассчитывает максимальную вместимость изображения в байтах для LSB метода. Для LSB: каждый пиксель (RGB) = 3 бита = 0.375 байта. Аргументы: image_path (str): Путь к изображению Возвращает: int: Максимальное количество байт, которое можно спрятать """ from PIL import Image img = Image.open(image_path) width, height = img.size total_pixels = width * height # 3 бита на пиксель, переводим в байты max_bits = total_pixels * 3 max_bytes = max_bits // 8 return max_bytes