Вернуться к разделу "Реализация проекта BookScanLib ".
На первом этапе проекта BookScanLib мы создаём каркасное консольное Win32-приложение на базе FreeImage. Оно может быть использовано как для первого знакомства с библиотекой FreeImage, так и как отправная точка для всего проекта.
FreeImage - это свободно-бесплатная графическая библиотека. Последняя её версия - 3.9.2.
Библиотека FreeImage поставляется в 2 вариантах на выбор:
1. Source distribution - в виде набора полных исходников. FreeImage добавляется в Вашу программу как статическая библиотека.
2. Binary distribution - в виде DLL-библиотеки плюс заголовочный файл к ней. FreeImage добавляется в Вашу программу как динамическая библиотека.
Библиотека FreeImage написана на языке программирования Си.
Пока что давайте остановимся на наипростейшем варианте поставки - на втором (Binary distribution).
Этому варианту соответствует пакет: Download FreeImage 3.9.2 [WIN32] (1,0 МБ)
Так как в этом пакете есть много не нужных нам пока файлов, то его можно сейчас не скачивать, а взамен скачать составленную мною его облегчённую версию:
FreeImage DLL v3.9.2 (432 КБ)
Этот мини-пакет в дальнейшем потребуется нам при написании КАЖДОГО алгоритма библиотеки (в виде FreeImage-программы). Там внутри только 3 файла (+ readme к ним): dll-библиотека, заголовочный и компоновочный файлы к ней.
Кроме того, библиотека FreeImage имеет общий пакет документации в формате Pdf:
FreeImage Documentation (1,99 МБ)
Этот пакет рекомендуется скачать всем с самого начала и начинать постепенно знакомиться с ним.
В дальнейшем, быть может, будет создан усечённый вариант библиотеки FreeImage - путём удаления оттуда "лишней" функциональности - в целях уменьшения её размера. Однако пока что, на этапе разработки алгоритмов, это совершенно несущественно - подобное "усечение" можно будет сделать в самый последний момент.
В первую очередь давайте попробуем получить каркасное (т.е. наипростейшее) консольное Win32 FreeImage-приложение. Такое приложение можно составить на базе примеров, изложенных в документации FreeImage Documentation.
Я сделал такую программу и назвал её fi_demo. Вот её компиляционный проект для MS Visual C++ v6.0:
FreeImage Demo (15 КБ)
Это - простейшая консольная программа, она принимает на входе графический файл любого поддерживаемого формата (через командную строку по его имени) и сохраняет его как "test.png". (Для работы программы требуется FreeImage dll-библиотека из пакета FreeImage DLL v3.9.2 - см. выше).
Ниже приводится полный исходный код этой программы:
// ========================================================== // This is a FreeImage 3.92 Example // // Load From File Demo // // // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER // THIS DISCLAIMER. // // Use at own risk! // ========================================================== // // This example shows how to load a graphical file from the hard disk using the FreeImage // Library // // Functions used in this sample: // // FreeImage_GetFormatFromFIF, FreeImage_GetFileType, FreeImage_GetFIFFromFilename, // FreeImage_FIFSupportsReading, FreeImage_Load, FreeImage_SetOutputMessage, FreeImage_Save, // FreeImage_Unload. // // ========================================================== #include <assert.h> #include <stdio.h> #include <stdlib.h> #include "FreeImage.h" // ---------------------------------------------------------- /** FreeImage error handler @param fif Format / Plugin responsible for the error @param message Error message */ void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) { printf("\n*** "); printf("%s Format\n", FreeImage_GetFormatFromFIF(fif)); printf(message); printf(" ***\n"); } // ---------------------------------------------------------- /** Generic image loader @param lpszPathName Pointer to the full file name @param flag Optional load flag constant @return Returns the loaded dib if successful, returns NULL otherwise */ FIBITMAP* GenericLoader(const char* lpszPathName, int flag) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; // check the file signature and deduce its format // (the second argument is currently not used by FreeImage) fif = FreeImage_GetFileType(lpszPathName, 0); if(fif == FIF_UNKNOWN) { // no signature ? // try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilename(lpszPathName); } // check that the plugin has reading capabilities ... if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { // ok, let's load the file FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag); // unless a bad file format, we are done ! return dib; } return NULL; } // ---------------------------------------------------------- int main(int argc, char *argv[]) { // call this ONLY when linking with FreeImage as a static library #ifdef FREEIMAGE_LIB FreeImage_Initialise(); #endif // FREEIMAGE_LIB // initialize your own FreeImage error handler FreeImage_SetOutputMessage(FreeImageErrorHandler); if(argc != 2) { printf("Usage : fi_demo <input file name>\n"); return 0; } FIBITMAP *dib = GenericLoader(argv[1], 0); if (dib) { // bitmap successfully loaded! // save the bitmap as a PNG ... const char *output_filename = "test.png"; // first, check the output format from the file name or file extension FREE_IMAGE_FORMAT out_fif = FreeImage_GetFIFFromFilename(output_filename); if(out_fif != FIF_UNKNOWN) { // then save the file FreeImage_Save(out_fif, dib, output_filename, 0); } // free the loaded FIBITMAP FreeImage_Unload(dib); } // call this ONLY when linking with FreeImage as a static library #ifdef FREEIMAGE_LIB FreeImage_DeInitialise(); #endif // FREEIMAGE_LIB return 0; } |
Примечание: более подробную информацию о библиотеке FreeImage и об используемых в ней функциях смотрите в её англоязычной документации FreeImage Documentation (1,99 МБ).
DLL_API const char* DLL_CALLCONV FreeImage_GetFormatFromFIF(FREE_IMAGE_FORMAT fif);
Возвращает строку - название графического формата.
На входе принимает "тип файла" (значение типа FREE_IMAGE_FORMAT - в библиотеке FreeImage это символическое обозначение графического типа данных - см. Таблицу 1 внизу страницы).
DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileType(const char *filename, int size FI_DEFAULT(0));
Определяет тип графического файла - путём анализа его характерного содержимого (сигнатуры).
На входе принимает строку - путь к графическому файлу на диске. Входной параметр size пока не используется и выставляется в ноль. В случае удачи функция возвращает "тип файла" (значение типа FREE_IMAGE_FORMAT).
В случае неудачи (т.к. не всегда возможно определить тип графического файла по его сигнатуре) функция возвращает FIF_UNKNOWN, и тогда остаётся последний шанс - попытаться вычислить тип данного графического файла при помощи функции FreeImage_GetFIFFromFilename, которая судит о типе файла просто по его расширению (что, естественно, ненадёжно и медленно). |
DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFilename(const char *filename);
Определяет тип графического файла просто по его расширению.
На входе принимает строку - путь к графическому файлу на диске. Возвращает "тип файла" (значение типа FREE_IMAGE_FORMAT). Это медленная и ненадёжная функция (по самой своей сути).
DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsReading(FREE_IMAGE_FORMAT fif);
Проверяет, поддерживается ли данный графический формат на чтение.
На входе принимает "тип файла" (значение типа FREE_IMAGE_FORMAT), возвращает TRUE / FALSE.
DLL_API FIBITMAP* DLL_CALLCONV FreeImage_Load(FREE_IMAGE_FORMAT fif, const char *filename, int flags FI_DEFAULT(0));
Загружает в память графический файл с диска.
На входе принимает "тип файла" (значение типа FREE_IMAGE_FORMAT), строку - путь к графическому файлу на диске, опции открытия файла (по умолчанию ноль). Возвращает указатель на значение типа FIBITMAP ("графический файл, загруженный в память").
DLL_API void DLL_CALLCONV FreeImage_SetOutputMessage(FreeImage_OutputMessageFunction omf);
Задаёт имя функции - обработчика ошибок.
Поведение обработчика ошибок зависит от "типа файла" (значение типа FREE_IMAGE_FORMAT), при работе с которым возникла ошибка.
/** FreeImage error handler @param fif Format / Plugin responsible for the error @param message Error message */ void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) { printf("\n*** "); if(fif != FIF_UNKNOWN) { printf("%s Format\n", FreeImage_GetFormatFromFIF(fif)); } printf(message); printf(" ***\n"); } // In your main program … FreeImage_SetOutputMessage(FreeImageErrorHandler) |
DLL_API BOOL DLL_CALLCONV FreeImage_Save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags FI_DEFAULT(0));
Сохраняет на диск ранее загруженный в память графический файл.
На входе принимает "тип файла" (значение типа FREE_IMAGE_FORMAT), "графический файл, загруженный в память" (указатель на значение типа FIBITMAP), строку - путь, по которому будет сохранён на диске графический файл, опции сохранения файла (по умолчанию ноль). Возвращает TRUE / FALSE (успешно/не успешно). Если файл уже существует, он будет перезаписан.
DLL_API void DLL_CALLCONV FreeImage_Unload(FIBITMAP *dib);
Удаляет из памяти ранее загруженный туда графический файл.
На входе принимает "графический файл, загруженный в память" (указатель на значение типа FIBITMAP).
Вам всегда необходимо вызывать эту функцию по окончании работы с файлом, иначе будет утечка памяти. |
Для удобства работы в библиотеке FreeImage используются "обобщённые" типы графических данных. Это даёт "дополнительный слой абстракции" - т.е. возможность не менять исходные коды, когда меняются стандарты и представления графических файлов, появляются новые форматы, исчезают старые и т.п.
Для этого используется специальный параметр - перечисление типа FREE_IMAGE_FORMAT. Это перечисление определено в заголовочном файле FREEIMAGE.H. Пока доступны следующие его значения:
Таблица 1: Предопределённые идентификаторы типа FREE_IMAGE_FORMAT.
FIF | Description |
FIF_UNKNOWN | Unknown format (returned value only, never use it as input value) |
FIF_BMP | Windows or OS/2 Bitmap File (*.BMP) |
FIF_CUT | Dr. Halo (*.CUT) |
FIF_DDS | DirectDraw Surface (*.DDS) |
FIF_FAXG3 | Raw Fax format CCITT G3 (*.G3) |
FIF_GIF | Graphics Interchange Format (*.GIF) |
FIF_HDR | High Dynamic Range (*.HDR) |
FIF_ICO | Windows Icon (*.ICO) |
FIF_IFF | Amiga IFF (*.IFF, *.LBM) |
FIF_JNG | JPEG Network Graphics (*.JNG) |
FIF_JPEG | Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) |
FIF_KOALA | Commodore 64 Koala format (*.KOA) |
FIF_MNG | Multiple Network Graphics (*.MNG) |
FIF_PBM | Portable Bitmap (ASCII) (*.PBM) |
FIF_PBMRAW | Portable Bitmap (BINARY) (*.PBM) |
FIF_PCD | Kodak PhotoCD (*.PCD) |
FIF_PCX | Zsoft Paintbrush PCX bitmap format (*.PCX) |
FIF_PGM | Portable Graymap (ASCII) (*.PGM) |
FIF_PGMRAW | Portable Graymap (BINARY) (*.PGM) |
FIF_PNG | Portable Network Graphics (*.PNG) |
FIF_PPM | Portable Pixelmap (ASCII) (*.PPM) |
FIF_PPMRAW | Portable Pixelmap (BINARY) (*.PPM) |
FIF_PSD | Adobe Photoshop (*.PSD) |
FIF_RAS | Sun Rasterfile (*.RAS) |
FIF_SGI | Silicon Graphics SGI image format (*.SGI) |
FIF_TARGA | Truevision Targa files (*.TGA, *.TARGA) |
FIF_TIFF | Tagged Image File Format (*.TIF, *.TIFF) |
FIF_WBMP | Wireless Bitmap (*.WBMP) |
FIF_XBM | X11 Bitmap Format (*.XBM) |
FIF_XPM | X11 Pixmap Format (*.XPM) |
В дополнение к существующим, Вы можете определить свой тип графических данных - если Вы создали обработчик для работы с ним.