Мы собираемся создать программу для скрытия текста в файле изображения без изменения внешнего вида изображения.

Предварительные требования: базовый Python и основы работы с битами

Сначала давайте рассмотрим основы изображения 101, поэтому изображение сохраняется в виде массива пикселей, а цвет каждого пикселя обозначается числом (обычно от 0 до 255), где значение 0 соответствует полной темноте, а 255 соответствует максимально возможному значению яркости.

Для цветных изображений нам нужно указать три значения для каждого пикселя, эти значения представляют собой количество красного, количество зеленого и количество синего, присутствующих в каждом пикселе. Это называется окраской RGB, и таким образом мы можем воспроизвести любой цвет.

Снова значения для красного, зеленого и синего находятся в диапазоне от 0 до 255.

Таким образом, цветное изображение, по сути, имеет три цветовых канала, каждый из которых можно рассматривать как изображение в градациях серого, обозначающее интенсивность этого конкретного цвета в различных частях изображения.

Теперь вам следует знать кое-что еще, а именно, что не все изображения хранятся просто как матрица целых чисел, в некоторых типах изображений для экономии места на диске значения данных сначала сжимаются, в то время как в некоторых других значениях полностью преобразуется во что-то еще, и поэтому некоторая информация об изображении также теряется. На основе сжатия существует три основных класса файлов изображений:

  1. Без сжатия. Сюда входят изображения .bmp и .tiff.
  2. Сжатие без потерь: включая изображения в формате PNG.
  3. Сжатие с потерями. Это изображения с высокой степенью сжатия, например .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 и тем, о чем вы хотите написать, и мы вернуться к вам!