Вшивание информации в растровые рисунки
Оформил: DeeCo
Автор: Юрий Писарев
В данной статье демонстрируется программа, позволяющая сохранять
текстовую информацию в растровые рисунки. Суть программы состоит в следующем:
берется текстовый файл и набор файлов рисунков. Далее выбирается подходящий
рисунок и на его основе создается второй рисунок, несколько измененный. Причем
степень изменения зависит от количества "вшиваемых" данных. При небольшом
количестве информации отличить рисунки практически невозможно. А получить
обратно текстовую информацию можно только лишь совместив эти два рисунка, а
также имея библиотеку, реализующую алгоритм "склеивания" этих рисунков.
Так выглядит программа в "рабочем" состоянии. А текст я взял из
какого-то файла, валявшегося у меня под рукой.
Как работать с программой
Для того, чтобы создать "слепок" существующего рисунка, нужно:
- Загрузить текстовый файл (секция text, кнопка Open)
- Загрузить понравившиеся рисунки (секция Picture, кнопка Open, можно
загружать несколько раз, загруженные ранее картинки не пропадут)
- Выделить нужный рисунок в компоненте TGraphGrid
- При желании, отмасштабировать его (кнопка Resize, масштабирует рисунок в
соответствии с его пропорциями)
- Нажать на кнопку Reflect. Через несколько секунд (это если картинка
большая, а так - через несколько миллисекунд) в компоненте TGraphGrid появится
сгенерированное изображение, созданное на основе выбраной картинки и
текстового файла. Новая картинка будет иметь имя "Data".
- Сохранить при необходимости нужный файл изображения, выбрав его в
компоненте TDrawGrid и нажав на кнопку Save.
Для того, чтобы получить
текст из двух одинаковых (на первый взгляд) картинок, нужно:
- Загрузить картинку, на основе которой был сделан "слепок"
- Нажать на кнопку Assembly. При этом появится диалоговое окно загрузки
изображения и на этот раз Вам надо будет выбрать файл "слепка", т.е.
измененную картинку.
- Далее, через некоторое время (в зависимости от количества данных,
содержащихся в картинке и размера самой картинки) в компоненте TRichEdit
появится этот самый закодированный текст.
Некоторые важные моменты
Выше было сказано, что при больших размерах картинки и при небольшем
объеме текстового файла отличить исходную и "слепленную" картинку практически
невозможно. Это правильно, но только отчасти. Если взглянуть на изображения, в
котором "зашит" большой текстовый файл, то сразу же в глаза бросаются чужеродные
пиксели, распределенные по всему изображению (кстати, коэффициент разброса можно
менять) а особенно хорошо эти пиксели видны на рисунке, с однородным фоном.
Сравните следующие два рисунка:
На правом рисунке отчетливо виден шум. Этого отчасти можно было бы
избежать, используя неоднороные рисунки с резкими переходами цвета, а также
рисунки большего формата. Или можно написать такой хитрый алгоритм кодирования,
что второе изображение будет невозможно отличить от первого. В примере вместо
увеличения размера рисунка я просто уменьшил количество информации:
Как работает программа
Программа использует компонент Graph, о котором я рассказывал в прошлой
статье.
Примечание: Материал Компоненты
для работы с графикой раздела Сокровищница
Сейчас я несколько улучшил этот компонент. Плюс, в нем появилось две
новых функции: function ReflectData(BaseBitmap, DataBitmap: TBitmap;
List: TStrings;
Reflection: TReflectionProc;
ScatterType: TScatterType;
Factor: Integer = 1): TReflectionResult; virtual;
function AssemblyData(BaseBitmap, DataBitmap: TBitmap;
Assembling: TAssemblingProc): Boolean; virtual;
Первая функция создает изображение, содержащее информацию; вторая -
получает информацию из двух изображений, как я рассказывал выше. Параметры
функции ReflectData:
- BaseBitmap - Базовое изображение, на его основе создается
изображение, содержащее информацию
- DataBitmap - Изображение, содержащее информацию
- Reflection - Процедура, которая изменяет соответствующий
байт исходного изображения и формирует DataBitmap Эта процедура отвечает за
сохранение информации во второй картинке. Но о ней - чуть позже.
- ScatterType - Тип распределения информации Может
принимать два значения: stGiven и stEvenly По умолчанию в программе
установлено значение stEvenly. Это означает, что вся информация будет
равномерно распределена по всей картинке. Если так, то задавать значение
следующего параметра Factor не нужно. Если ScatterType установить в stGiven,
то распределение информации зависит от коэффициента распределения.
- Factor - Коэффициент распределения. Если параметр
ScatterType равен stGiven, то фактически Factor означает через сколько байт то
начала картинки (не совсем от начала - первые восемь байт идут на длину
записываемого текста и на этот коэффициент) будет вписан следующий код символа
текста. В программе этот коэффициент задается в компоненте TEdit.
Теперь несколько слов о используемой функции Reflection. Эту функцию я
вынес в библиотеку. Эта библиотека является специфическим ключем, паролем для
соединения двух картинок. В нее могут быть заложены самые разные методы
шифрования, в данный же момент использзуется самый примитивный: при шифровании
код очередного символа просто прибавляется к значению из картинки BaseBitmap,
при расшифровке - наооборот. Эта процедура имеет тип: TReflectionProc = procedure(var Value: Byte; Text: string; Index: Integer); Параметры
функции Reflection:
- Value - Величина из BaseBitmap. Именно это значение
шифруется.
- Text - Текст в виде единой строки.
- Index - Текущий символ в тексте, который должен быть
зашифрован. В эой программе код этого символа складывается с параметром Value
при зашифровке.
В процедуре AsseblyData происходит обратный процесс,
выделение данных на основе двух изображений. Параметры функции AsseblyData:
- BaseBitmap - Базовое изображение
- DataBitmap - Изображение, содержащее информацию
- Assembling - Процедура, формирующая текстовые данные
Процедура Assembling имеет следующий тип: TAssemblingProc = procedure(BaseValue, DataValue: Byte); Ее
параметры:
- BaseValue - Текущая величина из BaseBitmap
- DataValue - Текущая величина из DestBitmap
В этой
программе каждое значение символа высчитывается путем вычитания DataValue из
BaseValue.
Заключение
На последок хочу дать один совет. Не стоит сохранять полученное
изображение в -jpg файле :) Хотя я один раз попробовал, текст оказался сильно
поврежден, хотя такие слова как Microsoft все-таки сохранились... в этом что-то
есть... :)
И еще одно, практический, такой пример:
Попробуйте получить информацию из этих рисунков. Должна получиться
статья, (в формате HTML) которую Вы сейчас читаете.
Примечание: В тексте статьи использовано
конвертированное изображение, если Вы хотите получить реальный рисунок в
формате BMP, содержащий информацию для вышеописанного конкретного примера,
необходимо скачать Image7.zip (162
K)
Скачать :
|