Meefik's Blog

Freedom and Open Source

Кодирование данных в картинку PNG

22 Feb 2020 | JavaScript

Хочу рассказать про пару интересных способов кодирования данных - кодирование в виде картинки и встраивание их в уже существующую картинку. Я экспериментировал с форматом PNG, т.к. в нем используется сжатие без потерь и поддерживается в браузерах в элементе canvas. Мне интересен JavaScript, поэтому реализация будет именно на нем. Код реализован в виде JS-библиотеки и выложен на GitHub под лицензией MIT.

Первый вариант кодирования заключается в формировании новой картинки на основе произвольных данных. Для этого каждый байт данных записывается последовательно в RGB каналы картинки PNG, при этом альфа-канал не трогается, т.к. при изменении альфа-канала частично меняются RGB цвета при выгрузки из canvas в PNG. В этом варианте в PNG можно запаковать WIDTH * HEIGHT * 3 байт данных. При кодировании текста размер изображения получается меньше исходного текста, т.к. к данным применяется сжатие Deflate.

// encode file to PNG
asPNG.encode(file).then(blob => {
  // encoded blob
});
// decode file from PNG
asPNG.decode(file).then(blob => {
  // decoded blob
});

aspng_encoded

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

В этом варианте в PNG можно запаковать до WIDTH * HEIGHT байт данных.

// inject data to PNG image
asPNG.inject(data, img).then(blob => {
  // modified image
});
// extract data from PNG image
asPNG.extract(img).then(blob => {
  // extracted data
});

aspng_injected

Comments