скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Вшивание информации в растровые рисунки



Автор: Юрий Писарев

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

Так выглядит программа в "рабочем" состоянии. А текст я взял из какого-то файла, валявшегося у меня под рукой.

Как работать с программой

Для того, чтобы создать "слепок" существующего рисунка, нужно:
  • Загрузить текстовый файл (секция 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)
Скачать :





Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook