Мы собираемся создать программу для скрытия текста в файле изображения без изменения внешнего вида изображения.
Предварительные требования: базовый Python и основы работы с битами
Сначала давайте рассмотрим основы изображения 101, поэтому изображение сохраняется в виде массива пикселей, а цвет каждого пикселя обозначается числом (обычно от 0 до 255), где значение 0 соответствует полной темноте, а 255 соответствует максимально возможному значению яркости.
Для цветных изображений нам нужно указать три значения для каждого пикселя, эти значения представляют собой количество красного, количество зеленого и количество синего, присутствующих в каждом пикселе. Это называется окраской RGB, и таким образом мы можем воспроизвести любой цвет.
Снова значения для красного, зеленого и синего находятся в диапазоне от 0 до 255.
Таким образом, цветное изображение, по сути, имеет три цветовых канала, каждый из которых можно рассматривать как изображение в градациях серого, обозначающее интенсивность этого конкретного цвета в различных частях изображения.
Теперь вам следует знать кое-что еще, а именно, что не все изображения хранятся просто как матрица целых чисел, в некоторых типах изображений для экономии места на диске значения данных сначала сжимаются, в то время как в некоторых других значениях полностью преобразуется во что-то еще, и поэтому некоторая информация об изображении также теряется. На основе сжатия существует три основных класса файлов изображений:
- Без сжатия. Сюда входят изображения .bmp и .tiff.
- Сжатие без потерь: включая изображения в формате PNG.
- Сжатие с потерями. Это изображения с высокой степенью сжатия, например .jpg.
Таким образом, хотя мы можем читать любой файл изображения, мы не можем сохранить файл изображения в формате сжатия с потерями, иначе наши данные будут потеряны. Лучше всего использовать формат .png.
Хорошо, теперь приступим к кодированию.
Сначала мы выполним импорт, чтобы прочитать изображение, мы будем использовать библиотеку PIL и numpy для управления данными.
Затем нам нужно составить список битовых масок со значениями [128, 64, 32, 16, 8, 4, 2, 1], мы будем использовать его позже, чтобы получить k-й бит числа . Если вы не знаете, как работает битовая маска, прочтите это.
Затем мы загружаем изображение с помощью PIL и конвертируем его в массив numpy, это дает нам 3-мерный массив numpy, первые два параметра - это высота и ширина изображения, а третий параметр представляет цветовой канал.
Теперь мы создадим функцию для записи нашего текстового сообщения во входной файл. Для простоты будем писать только в красный канал. Мы преобразуем каждый символ сообщения в соответствующее ему значение ASCII, затем применяем все битовые маски, представленные в lis, к этому значению ASCII одну за другой, выполняя побитовую операцию и, и сохраняем каждый полученный бит в один элемент массива, изменив младший бит (последний бит) этого элемента массива на 0 или 1.
Но это просто записывает сообщение в файл, и невозможно определить, был ли файл записан ранее. Чтобы решить эту проблему, мы добавим к нашему сообщению текст индикатора:
‘^START:’ + str(len(msg)+ ‘:’
Это также добавит длину исходного сообщения, что будет полезно при чтении файла изображения.
Затем мы напишем функцию для чтения первых «n» символов из входного изображения. Для каждого символа мы прочитаем 8 бит из 8 элементов массива, преобразуем данные в символ, а затем добавим этот символ в список.
Затем мы создадим другую функцию чтения, которая вызовет функцию read_imgn () для чтения первых 7 символов, чтобы проверить, совпадает ли она со строкой «^ START:»
Затем он прочитает значение целого числа n, присутствующее после начальной строки, а затем, наконец, вызовет read_imgn () для n целых чисел и вернет сообщение.
Теперь мы можем как кодировать, так и декодировать наш файл изображения.
Ура, мы закончили!
Но есть много возможностей для улучшения, например, запись данных во всех каналах и изменение более одного бита на пиксель для каждого цветового канала, а также кодирование других данных, таких как другое изображение.
Подпишитесь на мой GitHub, чтобы увидеть улучшенную версию того же кода.
Примечание команды Plain English
Вы знали, что у нас четыре публикации? Проявите немного любви, предложив им следующие слова: JavaScript на простом английском, AI на простом английском, UX на простом английском , Python на простом английском - спасибо и продолжайте учиться!
Кроме того, мы всегда заинтересованы в продвижении хорошего контента. Если у вас есть статья, которую вы хотели бы отправить в какую-либо из наших публикаций, отправьте электронное письмо на адрес [email protected] с вашим именем пользователя Medium и тем, о чем вы хотите написать, и мы вернуться к вам!