Вернуться к разделу "Реализация проекта 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) |
В дополнение к существующим, Вы можете определить свой тип графических данных - если Вы создали обработчик для работы с ним.