Gdi і многокадровостью tiff зображення

GDI + і многокадровостью зображення у форматі TIFF

На відміну від інших растрових графічних форматів, формат TIFF (Tag Image File Format) дозволяє:

  • створювати многокадровостью (multiframe) файли
  • вказувати кількість біт на піксель в збереженому зображенні
  • використовувати чотири різних алгоритму стиснення

Формат має виняткову гнучкість. Ви можете вибрати свій алгоритм стиснення і кількість біт на піксель для кожного кадру, збереженого в TIFF файлі.

У цій статті розглядаються всі аспекти роботи з форматом TIFF з додатків Visual FoxPro.

Перетворення графічних форматів в GDI +

GDI + дозволяє досить просто перетворювати зображення з одного формату в інший; для цього функції збереження зображення (наприклад, GdipSaveImageToFile) досить просто передати ClsID відповідного кодека. У наступному прикладі виконується перетворення зображення з формату BMP в формат TIFF.

Функція GdipLoadImageFromFile зчитує вихідне зображення з файлу InputFile.bmp в пам'ять комп'ютера, а функція GdipSaveImageToFile зберігає це зображення у форматі TIFF в файлі OutputFile.tif. Ці функції вимагають, щоб імена файлів передавалися їм як нуль-терминировать рядки в форматі Unicode.

Значення ClsID кодеків GDI + перераховані в наступній таблиці:

Тип графічного формату

Бінарне значення ClsID

зауваження
Бінарні значення ClsID ви можете використовувати тільки в дев'ятій версії Visual FoxPro. У попередніх версіях необхідно використовувати Windows API функції для конвертування валюти символьного подання ClsID, зазначеного в таблиці, в двійкове.

Microsoft попереджає, що значення ClsID кодеків можуть відрізнятися в різних версіях бібліотеки GDI +. Тому більш правильним буде використання спеціального механізму, що надається функціями GdipGetImageEncodersSize і GdipGetImageEncoders. що дозволяє отримати значення ClsID кодека для заданого графічного формату зображення. Швидше за все, така необхідність з'явиться в Windows Vista.

структура EncoderParameters

У розглянутому вище прикладі при виконанні функції GdipSaveImageToFile їй не передається покажчик на структуру EncoderParameters (це останній, четвертий параметр функції); замість нього вказано NULL. Дійсно, ви можете конвертувати будь-який підтримуваний в GDI + графічний формат в інший і без використання цієї структури. Але, якщо ви хочете керувати якістю зберігається зображення формату JPEG або якщо ви створюєте многокадровостью TIFF файли або TIFF файли, що використовують алгоритми стиснення і управління палітрою кольорів зображення, то тоді ви повинні використовувати структуру EncoderParameters для управління параметрами кодека.

Фактично структура EncoderParameters являє собою масив з вкладених структур. Перше поле цієї структури містить чотири байти для зберігання цілочисельного значення, що визначає кількість вкладених в неї структур. Кожна з вкладених структур містить наступні поля:

Найменування
поля в MSDN

Визначає, що параметр - масив з чотирьох 32-х розрядних цілих чисел без знака. Перші два числа представляють одну дріб, другі два числа - другу дріб. Ці дробу представляють діапазон раціональних чисел. Перша дріб визначає мінімальну, а друга - максимальне значення діапазону.

При роботі з форматом TIFF значення переданого кодеку параметра є одним 32-х розрядне ціле число, тому значення поля NumberOfValues ​​завжди має дорівнювати одиниці, а значення поля Type - чотирьом (EncoderParameterValueTypeLong, 32-х розрядне ціле без знака).

Поле Value містить покажчик на область пам'яті, в якій знаходиться значення параметра. Як випливає зі сказаного вище, розмір цієї пам'яті має дорівнювати 4-м байтам.
Ви можете розподілити необхідну пам'ять як всередині процесу, так і глобально. Я звичайно віддаю перевагу останній спосіб.

У наступній таблиці наведено допустимі значення параметра, переданого в структурі, що управляє створенням многокадрового TIFF (з полем Guid, що містить EncoderSaveFlag):

Найменування константи в MSDN

Визначає, що в файл додається черговий кадр

Нижче показаний фрагмент коду, який демонструє спосіб створення структури EncoderParameters в Visual FoxPro.

Для зберігання значення параметра в прикладі за допомогою функції GlobalAlloc розподіляється фіксована глобальна пам'ять Windows.

Запис багатокадрових зображень у форматі TIFF

Створення многокадрового зображення TIFF дещо відрізняється від запису звичайного файлу. Найперший кадр, як зазвичай, записується функцією GdipSaveImageToFile. Для додавання кожного наступного кадру використовується функція GdipSaveAddImage. а функція GdipSaveAdd грає роль завершального акорду, додаючи в файл ознака його закінчення. Всім цим функціям передається покажчик на структуру EncoderParameters. при цьому передається в структурі значення параметра (покажчик на параметр зберігається в поле Value) для кожної з цих функцій буде різним:

EncoderValueMultiFrame - для функції GdipSaveImageToFile

EncoderValueFrameDimensionPage - для функції GdipSaveAddImage

EncoderValueFrameDimensionPage - для функції GdipSaveAdd

У лістингу 1 наведено код процедури, що створює многокадровий TIFF файл.

Лістинг 1. Процедура створення многокадрового TIFF файлу

У процедурі використовується об'єкт Microsoft Common Dialog. дозволяє вибрати будь-яку кількість файлів для копіювання в TIFF файл.

Після запуску процедури на виконання виділіть в діалоговому вікні Common Dialog файли, а потім в діалозі Save As вкажіть специфікацію (шлях і ім'я) TIFF файлу, в який будуть поміщені вибрані зображення.

Спочатку в пам'ять зчитується перший файл зі списку, повернутого Common Dialog. Якщо обраний тільки один файл, то структура EncoderParameters не формується, а змінної lcEncoderParameters присвоюється значення NULL.
Якщо вибрано кілька файлів, то в структуру поміщається інформація, що визначає режим запису зображення (тобто в поле Guid заноситься значення EncoderSaveFlag, що визначає ідентифікатор прихованого методу GDI +, керуючого створенням многокадрового зображення, а параметр, покажчик на який зберігається в поле Value, отримує значення EncoderValueMultiFrame).

Якщо в TIFF файл записується більше одного кадру, то за допомогою функції SYS (2600) значення параметра замінюється на EncoderValueFrameDimensionPage, після чого в циклі послідовно зчитуються в пам'ять інші файли зі списку, а функція GdipSaveAddImage додає отримані зображення до вихідного файлу.
Коли всі вихідні файли оброблені, викликається функція GdipSaveAdd. завершальна запис в вивідний файл. Перед викликом цієї функції значення переданого в структурі параметра замінюється на EncoderColorDept.

Функція GdipDisposeImage звільняє займану лічених зображенням пам'ять, а функція GlobalFree повертає Windows пам'ять, розподілену для переданого в структурі параметра функцією GlobalAlloc.

Читання багатокадрових TIFF файлів

Після зчитування многокадрового TIFF файлу в пам'ять за допомогою функції GdipLoadImageFromFile ви повинні визначити кількість розмірностей (dimensions) і кількість кадрів в кожній розмірності.

зауваження
GDI + створює TIFF файл тільки з однієї розмірністю; мабуть, інші виробники можуть створювати багаторозмірний TIFF.

Робиться це за допомогою функцій GdipImageGetFrameDimensionsCount, GdipImageGetFrameDimensionsList і GdipImageGetFrameCount.

Функція GdipImageGetFrameDimensionsCount повертає кількість розмірностей TIFF файлу:

Функція GdipImageGetFrameDimensionsList заповнює масив значеннями GUID розмірностей. Перед її викликом ви повинні створити рядок для збереження повертаються GUID (тобто довжина цього рядка д.б.н. дорівнює 16 байтам, помноженим на кількість розмірностей TIFF файлу):

Кожна розмірність TIFF файлу може містити довільну кількість кадрів. Для того, щоб отримати доступ до цих кадрів, ви повинні витягти з lcDimensionIDs рядок довжиною 16 байт конкретного GUID; так, GUID першої розмірності розташовується, починаючи з першого байта рядки, GUID другий розмірності розташовується, починаючи з 17-го байта, і т.д.

Функція GdipImageGetFrameCount повертає кількість кадрів обраної розмірності:

Якщо ви збираєтеся витягувати кадри з TIFF файлу, створеного засобами GDI +, то, замість застосування розглянутих вище функцій, можете скористатися заздалегідь визначеним значенням для lcDimensionID.

так як GDI + створює однорозмірних TIFF файли.

Функція GdipImageSelectActiveFrame переміщує покажчик всередині області, в яку завантажено зображення, на вказаний кадр:

Номер кадру передається функції в змінної nFrame. Нумерація кадрів починається з нуля.

Після установки покажчика на потрібний кадр ви можете зберегти його за допомогою функції GdipSaveImageToFile або виконати інші дії, дозволені в GDI + (намалювати у вікні форми, роздрукувати на принтері, малювати на цьому кадрі і т.д.).

У лістингу 2 наведено код процедури, що витягає кадри з TIFF файлу

Лістинг 2. Процедура вилучення кадрів з многокадрового TIFF файлу

Після запуску процедури в діалоговому вікні Open. викликається функцією GetFile (), виберіть TIFF файл, і потім в діалоговому вікні, що викликається функцією Getdir (), вкажіть папку для збереження кадрів у вигляді окремих файлів.
Процедура зберігає кадри в файлах формату PNG, привласнюючи їм імена "OutputNM.png", де "N" - номер розмірності, а "M" - номер кадру в розмірності.

Використання алгоритмів стиснення

Для формату TIFF ви можете використовувати один з наступних алгоритмів стиснення:

Найменування в MSDN

Стиснення не виконується

У GDI + за замовчуванням використовується алгоритм стиснення LZW. Алгоритми CCITT3, CCITT4 і Rle можуть застосовуватися тільки до монохромним файлів (чорно-білим), в яких для зберігання пікселя використовується один біт.

За замовчуванням в GDI + застосовується стиснення по алгоритму LWZ. Якщо ви хочете скасувати стиснення або використовувати інший алгоритм, то додайте в структуру EncoderParameters вкладену структуру, полю Guid якої надайте значення EncoderCompression.

зауваження
Алгоритм LWZ по ефективності стиснення можна порівняти з JPEG; якість зображення при такому стискуванні втрачається. Тому, якщо вам необхідно зберегти високу якість зображення, відмовтеся від його стиснення.

У наступному фрагменті коду показано формування структури EncoderParameters для створення многокадрового TIFF без стиснення вихідних файлів.

Як бачите, для кожної вкладеної структури розподіляється глобальна пам'ять Windows; покажчики на розподілені блоки зберігаються в змінних hGlobalMulti і hGlobalCompr. Не забудьте повернути цю пам'ять після створення TIFF файлу!

Управління кількістю біт на піксель

Не всі графічні формати підтримують можливість зберігання інформації в форматі з будь-якою кількістю біт на піксель. Мабуть, єдиним винятком є ​​формат PNG. У разі, якщо зазначена кількість біт на піксель є неприпустимим, то при виконанні ви отримаєте помилку з кодом 2 (неприпустиме значення переданого параметра).

Для управління кількістю біт на піксель ви повинні додати в структуру EncoderParameters вкладену структуру, присвоївши її полю Guid значення EncoderColorDept. Так само розподіліть для цієї структури блок пам'яті, покажчик на яку помістіть в поле Value. Запишіть в розподілену пам'ять значення кількості біт на піксель.