diff options
author | George Hazan <ghazan@miranda.im> | 2019-02-07 23:58:40 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-02-07 23:58:40 +0300 |
commit | bd864aa049acee3bd236858b29ab5e219bf79b62 (patch) | |
tree | 412d8cafc87f897244b2033cd4c9eb8f693f3315 /libs/freeimage/src | |
parent | 62385245de7390d630cdd1459d13c69fd315a302 (diff) |
FreeImage: update to 3.18.0
Diffstat (limited to 'libs/freeimage/src')
23 files changed, 735 insertions, 490 deletions
diff --git a/libs/freeimage/src/CacheFile.h b/libs/freeimage/src/CacheFile.h index a1e5e782c9..7f1ab72a31 100644 --- a/libs/freeimage/src/CacheFile.h +++ b/libs/freeimage/src/CacheFile.h @@ -19,8 +19,8 @@ // Use at your own risk! // ========================================================== -#ifndef CACHEFILE_H -#define CACHEFILE_H +#ifndef FREEIMAGE_CACHEFILE_H +#define FREEIMAGE_CACHEFILE_H // ---------------------------------------------------------- @@ -61,11 +61,12 @@ class CacheFile { typedef std::map<int, PageCacheIt>::iterator PageMapIt; public : - CacheFile(const std::string filename, BOOL keep_in_memory); + CacheFile(); ~CacheFile(); - - BOOL open(); + + BOOL open(const std::string& filename = "", BOOL keep_in_memory = TRUE); void close(); + BOOL readFile(BYTE *data, int nr, int size); int writeFile(BYTE *data, int size); void deleteFile(int nr); @@ -89,4 +90,4 @@ private : BOOL m_keep_in_memory; }; -#endif // CACHEFILE_H +#endif // FREEIMAGE_CACHEFILE_H diff --git a/libs/freeimage/src/FreeImage.h b/libs/freeimage/src/FreeImage.h index 980360d1ec..c6dd2221ea 100644 --- a/libs/freeimage/src/FreeImage.h +++ b/libs/freeimage/src/FreeImage.h @@ -1,4 +1,4 @@ -// ========================================================== +// ========================================================== // FreeImage 3 // // Design and implementation by @@ -29,7 +29,7 @@ // Version information ------------------------------------------------------ #define FREEIMAGE_MAJOR_VERSION 3 -#define FREEIMAGE_MINOR_VERSION 17 +#define FREEIMAGE_MINOR_VERSION 18 #define FREEIMAGE_RELEASE_SERIAL 0 // Compiler options --------------------------------------------------------- @@ -75,7 +75,7 @@ // or define any of FREEIMAGE_BIGENDIAN and FREEIMAGE_LITTLEENDIAN directly // to specify the desired endianness. #if (!defined(FREEIMAGE_BIGENDIAN) && !defined(FREEIMAGE_LITTLEENDIAN)) - #if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || defined(__BIG_ENDIAN__) +#if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER==__ORDER_BIG_ENDIAN__) || defined(__BIG_ENDIAN__) #define FREEIMAGE_BIGENDIAN #endif // BYTE_ORDER #endif // !FREEIMAGE_[BIG|LITTLE]ENDIAN @@ -733,6 +733,9 @@ typedef void (DLL_CALLCONV *FI_InitProc)(Plugin *plugin, int format_id); #define PSD_DEFAULT 0 #define PSD_CMYK 1 //! reads tags for separated CMYK (default is conversion to RGB) #define PSD_LAB 2 //! reads tags for CIELab (default is conversion to RGB) +#define PSD_NONE 0x0100 //! save without any compression +#define PSD_RLE 0x0200 //! save using RLE compression +#define PSD_PSB 0x2000 //! save using Adobe Large Document Format (use | to combine with other save flags) #define RAS_DEFAULT 0 #define RAW_DEFAULT 0 //! load the file as linear RGB 48-bit #define RAW_PREVIEW 1 //! try to load the embedded JPEG preview with included Exif Data or default to RGB 24-bit @@ -880,13 +883,19 @@ DLL_API void DLL_CALLCONV FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP * DLL_API BOOL DLL_CALLCONV FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source); DLL_API BOOL DLL_CALLCONV FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count); -// Filetype request routines ------------------------------------------------ +// File type request routines ------------------------------------------------ DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileType(const char *filename, int size FI_DEFAULT(0)); DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeU(const wchar_t *filename, int size FI_DEFAULT(0)); DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size FI_DEFAULT(0)); DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromMemory(FIMEMORY *stream, int size FI_DEFAULT(0)); +DLL_API BOOL DLL_CALLCONV FreeImage_Validate(FREE_IMAGE_FORMAT fif, const char *filename); +DLL_API BOOL DLL_CALLCONV FreeImage_ValidateU(FREE_IMAGE_FORMAT fif, const wchar_t *filename); +DLL_API BOOL DLL_CALLCONV FreeImage_ValidateFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle); +DLL_API BOOL DLL_CALLCONV FreeImage_ValidateFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream); + + // Image type request routine ----------------------------------------------- DLL_API FREE_IMAGE_TYPE DLL_CALLCONV FreeImage_GetImageType(FIBITMAP *dib); @@ -986,8 +995,11 @@ DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_555(BYTE *target, BYTE *so DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_565(BYTE *target, BYTE *source, int width_in_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To24(BYTE *target, BYTE *source, int width_in_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_555(BYTE *target, BYTE *source, int width_in_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_565(BYTE *target, BYTE *source, int width_in_pixels); DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels); @@ -1099,8 +1111,6 @@ DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransformCombinedFromMemory(FIMEMORY* sr // -------------------------------------------------------------------------- // rotation and flipping -/// @deprecated see FreeImage_Rotate -DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateClassic(FIBITMAP *dib, double angle); DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Rotate(FIBITMAP *dib, double angle, const void *bkcolor FI_DEFAULT(NULL)); DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask); DLL_API BOOL DLL_CALLCONV FreeImage_FlipHorizontal(FIBITMAP *dib); @@ -1137,7 +1147,7 @@ DLL_API BOOL DLL_CALLCONV FreeImage_Paste(FIBITMAP *dst, FIBITMAP *src, int left DLL_API FIBITMAP *DLL_CALLCONV FreeImage_CreateView(FIBITMAP *dib, unsigned left, unsigned top, unsigned right, unsigned bottom); DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg FI_DEFAULT(FALSE), RGBQUAD *appBkColor FI_DEFAULT(NULL), FIBITMAP *bg FI_DEFAULT(NULL)); -DLL_API BOOL DLL_CALLCONV FreeImage_PremultiplyWithAlpha(FIBITMAP *dib); +DLL_API BOOL DLL_CALLCONV FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib); // background filling routines DLL_API BOOL DLL_CALLCONV FreeImage_FillBackground(FIBITMAP *dib, const void *color, int options FI_DEFAULT(0)); diff --git a/libs/freeimage/src/FreeImage/BitmapAccess.cpp b/libs/freeimage/src/FreeImage/BitmapAccess.cpp index c3be7a1742..e77344e1e1 100644 --- a/libs/freeimage/src/FreeImage/BitmapAccess.cpp +++ b/libs/freeimage/src/FreeImage/BitmapAccess.cpp @@ -1,4 +1,4 @@ -// ========================================================== +// ========================================================== // FreeImage implementation // // Design and implementation by @@ -537,6 +537,7 @@ FreeImage_Clone(FIBITMAP *dib) { unsigned height = FreeImage_GetHeight(dib); unsigned bpp = FreeImage_GetBPP(dib); + // if the FIBITMAP is a wrapper to a user provided pixel buffer, get a pointer to this buffer const BYTE *ext_bits = ((FREEIMAGEHEADER *)dib->data)->external_bits; // check for pixel availability ... @@ -558,7 +559,7 @@ FreeImage_Clone(FIBITMAP *dib) { METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata; - // calculate the size of the src image + // calculate the size of the dst image // align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary // palette is aligned on a 16 bytes boundary // pixels are aligned on a 16 bytes boundary @@ -579,6 +580,10 @@ FreeImage_Clone(FIBITMAP *dib) { // reset thumbnail link for new_dib ((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL; + // reset external wrapped buffer link for new_dib + ((FREEIMAGEHEADER *)new_dib->data)->external_bits = NULL; + ((FREEIMAGEHEADER *)new_dib->data)->external_pitch = 0; + // copy possible ICC profile FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size); dst_iccProfile->flags = src_iccProfile->flags; @@ -697,12 +702,14 @@ FreeImage_GetColorType(FIBITMAP *dib) { return FIC_MINISBLACK; } break; + case FIT_RGB16: case FIT_RGBF: return FIC_RGB; + case FIT_RGBA16: case FIT_RGBAF: - return FIC_RGBALPHA; + return (((FreeImage_GetICCProfile(dib)->flags) & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) ? FIC_CMYK : FIC_RGBALPHA; } return FIC_MINISBLACK; @@ -767,7 +774,7 @@ FreeImage_GetColorType(FIBITMAP *dib) { case 32: { - if (FreeImage_GetICCProfile(dib)->flags & FIICC_COLOR_IS_CMYK) { + if (((FreeImage_GetICCProfile(dib)->flags) & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) { return FIC_CMYK; } @@ -944,7 +951,7 @@ FreeImage_IsTransparent(FIBITMAP *dib) { break; case FIT_RGBA16: case FIT_RGBAF: - return TRUE; + return (((FreeImage_GetICCProfile(dib)->flags) & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) ? FALSE : TRUE; default: break; } @@ -1085,6 +1092,9 @@ FreeImage_DestroyICCProfile(FIBITMAP *dib) { profile->data = NULL; profile->size = 0; } + + // destroy also Exif-Main ICC profile + FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, "InterColorProfile", NULL); } // ---------------------------------------------------------- @@ -1194,12 +1204,12 @@ FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag FIMETADATA *handle = (FIMETADATA *)malloc(sizeof(FIMETADATA)); if(handle) { // calculate the size of a METADATAHEADER - int header_size = sizeof(METADATAHEADER); + const size_t header_size = sizeof(METADATAHEADER); - handle->data = (BYTE *)malloc(header_size * sizeof(BYTE)); + handle->data = (BYTE *)malloc(header_size); if(handle->data) { - memset(handle->data, 0, header_size * sizeof(BYTE)); + memset(handle->data, 0, header_size); // write out the METADATAHEADER METADATAHEADER *mdh = (METADATAHEADER *)handle->data; @@ -1334,6 +1344,11 @@ FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, if(key != NULL) { + if ((tag == NULL) && !tagmap) { + // remove a tag from an unknown tagmap, nothing to do + return TRUE; + } + if(!tagmap) { // this model, doesn't exist: create it tagmap = new(std::nothrow) TAGMAP(); diff --git a/libs/freeimage/src/FreeImage/CacheFile.cpp b/libs/freeimage/src/FreeImage/CacheFile.cpp index 086393bf03..e98906d39e 100644 --- a/libs/freeimage/src/FreeImage/CacheFile.cpp +++ b/libs/freeimage/src/FreeImage/CacheFile.cpp @@ -4,6 +4,7 @@ // Design and implementation by // - Floris van den Berg (flvdberg@wxs.nl) // - checkered (checkered@users.sourceforge.net) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) // // This file is part of FreeImage 3 // @@ -28,25 +29,31 @@ // ---------------------------------------------------------- -CacheFile::CacheFile(const std::string filename, BOOL keep_in_memory) : +CacheFile::CacheFile() : m_file(NULL), -m_filename(filename), m_free_pages(), m_page_cache_mem(), m_page_cache_disk(), m_page_map(), m_page_count(0), m_current_block(NULL), -m_keep_in_memory(keep_in_memory) { +m_keep_in_memory(TRUE) { } CacheFile::~CacheFile() { + close(); } BOOL -CacheFile::open() { +CacheFile::open(const std::string& filename, BOOL keep_in_memory) { + + assert(!m_file); + + m_filename = filename; + m_keep_in_memory = keep_in_memory; + if ((!m_filename.empty()) && (!m_keep_in_memory)) { - m_file = fopen(m_filename.c_str(), "w+b"); + m_file = fopen(m_filename.c_str(), "w+b"); return (m_file != NULL); } @@ -72,11 +79,10 @@ CacheFile::close() { if (m_file) { // close the file - fclose(m_file); - + m_file = NULL; + // delete the file - remove(m_filename.c_str()); } } @@ -164,10 +170,8 @@ BOOL CacheFile::unlockBlock(int nr) { if (m_current_block) { m_current_block = NULL; - return TRUE; } - return FALSE; } @@ -178,8 +182,9 @@ CacheFile::deleteBlock(int nr) { // remove block from cache - if (it != m_page_map.end()) + if (it != m_page_map.end()) { m_page_map.erase(nr); + } // add block to free page list diff --git a/libs/freeimage/src/FreeImage/Conversion.cpp b/libs/freeimage/src/FreeImage/Conversion.cpp index 9ef49f393b..f8d8ce4512 100644 --- a/libs/freeimage/src/FreeImage/Conversion.cpp +++ b/libs/freeimage/src/FreeImage/Conversion.cpp @@ -28,8 +28,17 @@ // ---------------------------------------------------------- #define CONVERT(from, to) case to : FreeImage_ConvertLine##from##To##to(bits, scanline, FreeImage_GetWidth(dib)); break; + #define CONVERTWITHPALETTE(from, to) case to : FreeImage_ConvertLine##from##To##to(bits, scanline, FreeImage_GetWidth(dib), FreeImage_GetPalette(dib)); break; +#define CONVERTTO32WITHPALETTE(from) case 32 : \ + if (bIsTransparent) { \ + FreeImage_ConvertLine##from##To32MapTransparency(bits, scanline, FreeImage_GetWidth(dib), FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); \ + } else { \ + FreeImage_ConvertLine##from##To32(bits, scanline, FreeImage_GetWidth(dib), FreeImage_GetPalette(dib)); \ + } \ + break; + #define CONVERTTO16(from) \ case 16 : \ if ((red_mask == FI16_555_RED_MASK) && (green_mask == FI16_555_GREEN_MASK) && (blue_mask == FI16_555_BLUE_MASK)) { \ @@ -491,14 +500,15 @@ FreeImage_ConvertToRawBits(BYTE *bits, FIBITMAP *dib, int pitch, unsigned bpp, u } } } else if (FreeImage_GetBPP(dib) != bpp) { + BOOL bIsTransparent = FreeImage_IsTransparent(dib); switch(FreeImage_GetBPP(dib)) { case 1 : switch(bpp) { CONVERT(1, 8) CONVERTTO16WITHPALETTE(1) CONVERTWITHPALETTE(1, 24) - CONVERTWITHPALETTE(1, 32) - } + CONVERTTO32WITHPALETTE(1) + } break; @@ -507,7 +517,7 @@ FreeImage_ConvertToRawBits(BYTE *bits, FIBITMAP *dib, int pitch, unsigned bpp, u CONVERT(4, 8) CONVERTTO16WITHPALETTE(4) CONVERTWITHPALETTE(4, 24) - CONVERTWITHPALETTE(4, 32) + CONVERTTO32WITHPALETTE(4) } break; @@ -516,7 +526,7 @@ FreeImage_ConvertToRawBits(BYTE *bits, FIBITMAP *dib, int pitch, unsigned bpp, u switch(bpp) { CONVERTTO16WITHPALETTE(8) CONVERTWITHPALETTE(8, 24) - CONVERTWITHPALETTE(8, 32) + CONVERTTO32WITHPALETTE(8) } break; diff --git a/libs/freeimage/src/FreeImage/Conversion32.cpp b/libs/freeimage/src/FreeImage/Conversion32.cpp index f5eb0c2103..17dbe7e7b8 100644 --- a/libs/freeimage/src/FreeImage/Conversion32.cpp +++ b/libs/freeimage/src/FreeImage/Conversion32.cpp @@ -131,7 +131,7 @@ FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels) { // ---------------------------------------------------------- -inline void +void DLL_CALLCONV FreeImage_ConvertLine1To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { for (int cols = 0; cols < width_in_pixels; cols++) { int index = (source[cols>>3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0; @@ -144,7 +144,7 @@ FreeImage_ConvertLine1To32MapTransparency(BYTE *target, BYTE *source, int width_ } } -inline void +void DLL_CALLCONV FreeImage_ConvertLine4To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { BOOL low_nibble = FALSE; int x = 0; @@ -170,7 +170,7 @@ FreeImage_ConvertLine4To32MapTransparency(BYTE *target, BYTE *source, int width_ } } -inline void +void DLL_CALLCONV FreeImage_ConvertLine8To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { for (int cols = 0; cols < width_in_pixels; cols++) { target[FI_RGBA_BLUE] = palette[source[cols]].rgbBlue; diff --git a/libs/freeimage/src/FreeImage/GetType.cpp b/libs/freeimage/src/FreeImage/GetType.cpp index b2991a0e49..625b81246a 100644 --- a/libs/freeimage/src/FreeImage/GetType.cpp +++ b/libs/freeimage/src/FreeImage/GetType.cpp @@ -1,8 +1,9 @@ -// ========================================================== -// GetType +// ========================================================== +// GetType / Validate // // Design and implementation by // - Floris van den Berg (flvdberg@wxs.nl) +// - Hervé Drolon (drolon@infonie.fr) // // This file is part of FreeImage 3 // @@ -25,7 +26,9 @@ #include "../stdafx.h" -// ---------------------------------------------------------- +// ===================================================================== +// Generic stream file type access +// ===================================================================== FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size) { @@ -34,7 +37,7 @@ FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size) { for (int i = 0; i < fif_count; ++i) { FREE_IMAGE_FORMAT fif = (FREE_IMAGE_FORMAT)i; - if (FreeImage_Validate(fif, io, handle)) { + if (FreeImage_ValidateFIF(fif, io, handle)) { /*if(fif == FIF_TIFF) { // many camera raw files use a TIFF signature ... // ... try to revalidate against FIF_RAW (even if it breaks the code genericity) @@ -50,6 +53,10 @@ FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size) { return FIF_UNKNOWN; } +// ===================================================================== +// File stream file type access +// ===================================================================== + FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileType(const char *filename, int size) { FreeImageIO io; @@ -86,3 +93,70 @@ FreeImage_GetFileTypeU(const wchar_t *filename, int size) { return FIF_UNKNOWN; } +// ===================================================================== +// Memory stream file type access +// ===================================================================== + +FREE_IMAGE_FORMAT DLL_CALLCONV +FreeImage_GetFileTypeFromMemory(FIMEMORY *stream, int size) { + FreeImageIO io; + SetMemoryIO(&io); + + if (stream != NULL) { + return FreeImage_GetFileTypeFromHandle(&io, (fi_handle)stream, size); + } + + return FIF_UNKNOWN; +} + +// -------------------------------------------------------------------------- + +BOOL DLL_CALLCONV +FreeImage_ValidateFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle) { + return FreeImage_ValidateFIF(fif, io, handle); +} + +BOOL DLL_CALLCONV +FreeImage_Validate(FREE_IMAGE_FORMAT fif, const char *filename) { + FreeImageIO io; + SetDefaultIO(&io); + + FILE *handle = fopen(filename, "rb"); + + if (handle != NULL) { + BOOL bIsValidFIF = FreeImage_ValidateFromHandle(fif, &io, (fi_handle)handle); + fclose(handle); + return bIsValidFIF; + } + + return FALSE; +} + +BOOL DLL_CALLCONV +FreeImage_ValidateU(FREE_IMAGE_FORMAT fif, const wchar_t *filename) { +#ifdef _WIN32 + FreeImageIO io; + SetDefaultIO(&io); + FILE *handle = _wfopen(filename, L"rb"); + + if (handle != NULL) { + BOOL bIsValidFIF = FreeImage_ValidateFromHandle(fif, &io, (fi_handle)handle); + fclose(handle); + return bIsValidFIF; + } +#endif + return FALSE; +} + +BOOL DLL_CALLCONV +FreeImage_ValidateFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream) { + FreeImageIO io; + SetMemoryIO(&io); + + if (stream != NULL) { + BOOL bIsValidFIF = FreeImage_ValidateFromHandle(fif, &io, (fi_handle)stream); + return bIsValidFIF; + } + + return FALSE; +} diff --git a/libs/freeimage/src/FreeImage/MemoryIO.cpp b/libs/freeimage/src/FreeImage/MemoryIO.cpp index c04612373a..cda97e1e71 100644 --- a/libs/freeimage/src/FreeImage/MemoryIO.cpp +++ b/libs/freeimage/src/FreeImage/MemoryIO.cpp @@ -126,22 +126,6 @@ FreeImage_AcquireMemory(FIMEMORY *stream, BYTE **data, DWORD *size_in_bytes) { } // ===================================================================== -// Memory stream file type access -// ===================================================================== - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_GetFileTypeFromMemory(FIMEMORY *stream, int size) { - FreeImageIO io; - SetMemoryIO(&io); - - if (stream != NULL) { - return FreeImage_GetFileTypeFromHandle(&io, (fi_handle)stream, size); - } - - return FIF_UNKNOWN; -} - -// ===================================================================== // Seeking in Memory stream // ===================================================================== diff --git a/libs/freeimage/src/FreeImage/MultiPage.cpp b/libs/freeimage/src/FreeImage/MultiPage.cpp index 0d49f46633..5788d241fd 100644 --- a/libs/freeimage/src/FreeImage/MultiPage.cpp +++ b/libs/freeimage/src/FreeImage/MultiPage.cpp @@ -10,6 +10,7 @@ // - Vadim Alexandrov (vadimalexandrov@users.sourceforge.net // - Martin Dyring-Andersen (mda@spamfighter.com) // - Volodymyr Goncharov (volodymyr.goncharov@gmail.com) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) // // This file is part of FreeImage 3 // @@ -32,58 +33,89 @@ #include "../stdafx.h" +namespace { + // ---------------------------------------------------------- enum BlockType { BLOCK_CONTINUEUS, BLOCK_REFERENCE }; // ---------------------------------------------------------- -struct BlockTypeS { - BlockType m_type; - - BlockTypeS(BlockType type) : m_type(type) { - } - virtual ~BlockTypeS() {} -}; - -struct BlockContinueus : public BlockTypeS { - int m_start; - int m_end; - - BlockContinueus(int s, int e) : BlockTypeS(BLOCK_CONTINUEUS), - m_start(s), - m_end(e) { - } -}; - -struct BlockReference : public BlockTypeS { - int m_reference; - int m_size; - - BlockReference(int r, int size) : BlockTypeS(BLOCK_REFERENCE), - m_reference(r), - m_size(size) { - } +class PageBlock { + + union { + struct { + int m_start; + int m_end; + }; + struct { + int m_reference; + int m_size; + }; + }; + +public: + BlockType m_type; + + PageBlock(BlockType type = BLOCK_CONTINUEUS, int val1 = -1, int val2 = -1) : m_type(type) + { + if(m_type == BLOCK_CONTINUEUS) + { + m_start = val1; + m_end = val2; + } + else + { + m_reference = val1; + m_size = val2; + } + } + + bool isValid() const { return !(m_type == BLOCK_CONTINUEUS && m_start == -1 && m_end == -1); } + /*explicit*/ operator bool() const { return isValid(); } + + int getStart() const { assert(isValid() && m_type == BLOCK_CONTINUEUS); return m_start; } + int getEnd() const { assert(isValid() && m_type == BLOCK_CONTINUEUS); return m_end; } + + bool isSinglePage() const { assert(isValid()); return m_type == BLOCK_CONTINUEUS ? (m_start == m_end) : true; } + int getPageCount() const { assert(isValid()); return m_type == BLOCK_CONTINUEUS ? (m_end - m_start + 1) : 1;} + + int getReference() const { assert(isValid() && m_type == BLOCK_REFERENCE); return m_reference; } + int getSize() const { assert(isValid() && m_type == BLOCK_REFERENCE); return m_size; } }; // ---------------------------------------------------------- -typedef std::list<BlockTypeS *> BlockList; -typedef std::list<BlockTypeS *>::iterator BlockListIterator; +typedef std::list<PageBlock> BlockList; +typedef BlockList::iterator BlockListIterator; // ---------------------------------------------------------- -FI_STRUCT (MULTIBITMAPHEADER) { +struct MULTIBITMAPHEADER { + + MULTIBITMAPHEADER() + : node(NULL) + , fif(FIF_UNKNOWN) + , handle(NULL) + , changed(FALSE) + , page_count(0) + , read_only(TRUE) + , cache_fif(fif) + , load_flags(0) + { + SetDefaultIO(&io); + } + PluginNode *node; FREE_IMAGE_FORMAT fif; - FreeImageIO *io; + FreeImageIO io; fi_handle handle; - CacheFile *m_cachefile; + CacheFile m_cachefile; std::map<FIBITMAP *, int> locked_pages; BOOL changed; int page_count; BlockList m_blocks; - char *m_filename; + std::string m_filename; BOOL read_only; FREE_IMAGE_FORMAT cache_fif; int load_flags; @@ -107,6 +139,9 @@ ReplaceExtension(std::string& dst_filename, const std::string& src_filename, con } } +} //< ns + + // ===================================================================== // Internal Multipage functions // ===================================================================== @@ -127,77 +162,55 @@ FreeImage_FindBlock(FIMULTIBITMAP *bitmap, int position) { int prev_count = 0; int count = 0; BlockListIterator i; - BlockTypeS *current_block = NULL; for (i = header->m_blocks.begin(); i != header->m_blocks.end(); ++i) { prev_count = count; + + count += i->getPageCount(); - switch((*i)->m_type) { - case BLOCK_CONTINUEUS : - count += ((BlockContinueus *)(*i))->m_end - ((BlockContinueus *)(*i))->m_start + 1; - break; - - case BLOCK_REFERENCE : - count++; - break; - } - - current_block = *i; - - if (count > position) + if (count > position) { break; + } } // step 2: make sure we found the node. from here it gets a little complicated: - // * if the block is there, just return it - // * if the block is a series of blocks, split it in max 3 new blocks - // and return the splitted block - - if ((current_block) && (count > position)) { - switch(current_block->m_type) { - case BLOCK_REFERENCE : - return i; - - case BLOCK_CONTINUEUS : - { - BlockContinueus *block = (BlockContinueus *)current_block; - - if (block->m_start != block->m_end) { - int item = block->m_start + (position - prev_count); - - // left part - - if (item != block->m_start) { - BlockContinueus *block_a = new BlockContinueus(block->m_start, item - 1); - header->m_blocks.insert(i, (BlockTypeS *)block_a); - } - - // middle part - - BlockContinueus *block_b = new BlockContinueus(item, item); - BlockListIterator block_target = header->m_blocks.insert(i, (BlockTypeS *)block_b); - - // right part - - if (item != block->m_end) { - BlockContinueus *block_c = new BlockContinueus(item + 1, block->m_end); - header->m_blocks.insert(i, (BlockTypeS *)block_c); - } - - // remove the old block that was just splitted - - header->m_blocks.remove((BlockTypeS *)block); - delete block; - - // return the splitted block - - return block_target; - } - - return i; - } + // * if the block is single page, just return it + // * if the block is a span of pages, split it in 3 new blocks + // and return the middle block, which is now a single page + + if ((i != header->m_blocks.end()) && (count > position)) { + + if (i->isSinglePage()) { + return i; + } + + const int item = i->getStart() + (position - prev_count); + + // left part + + if (item != i->getStart()) { + header->m_blocks.insert(i, PageBlock(BLOCK_CONTINUEUS, i->getStart(), item - 1)); + } + + // middle part + + BlockListIterator block_target = header->m_blocks.insert(i, PageBlock(BLOCK_CONTINUEUS, item, item)); + + // right part + + if (item != i->getEnd()) { + header->m_blocks.insert(i, PageBlock(BLOCK_CONTINUEUS, item + 1, i->getEnd())); } + + // remove the old block that was just splitted + + header->m_blocks.erase(i); + + // return the splitted block + + return block_target; } + // we should never go here ... assert(false); return header->m_blocks.end(); @@ -208,19 +221,19 @@ FreeImage_InternalGetPageCount(FIMULTIBITMAP *bitmap) { if (bitmap) { if (((MULTIBITMAPHEADER *)bitmap->data)->handle) { MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - header->io->seek_proc(header->handle, 0, SEEK_SET); - - void *data = FreeImage_Open(header->node, header->io, header->handle, TRUE); - - int page_count = (header->node->m_plugin->pagecount_proc != NULL) ? header->node->m_plugin->pagecount_proc(header->io, header->handle, data) : 1; - - FreeImage_Close(header->node, header->io, header->handle, data); - + + header->io.seek_proc(header->handle, 0, SEEK_SET); + + void *data = FreeImage_Open(header->node, &header->io, header->handle, TRUE); + + int page_count = (header->node->m_plugin->pagecount_proc != NULL) ? header->node->m_plugin->pagecount_proc(&header->io, header->handle, data) : 1; + + FreeImage_Close(header->node, &header->io, header->handle, data); + return page_count; } } - + return 0; } @@ -247,10 +260,6 @@ FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL crea PluginNode *node = list->FindNodeFromFIF(fif); if (node) { - std::auto_ptr<FreeImageIO> io (new FreeImageIO); - - SetDefaultIO(io.get()); - if (!create_new) { handle = fopen(filename, "rb"); if (handle == NULL) { @@ -260,15 +269,12 @@ FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL crea std::auto_ptr<FIMULTIBITMAP> bitmap (new FIMULTIBITMAP); std::auto_ptr<MULTIBITMAPHEADER> header (new MULTIBITMAPHEADER); - header->m_filename = new char[strlen(filename) + 1]; - strcpy(header->m_filename, filename); + header->m_filename = filename; + // io is default header->node = node; header->fif = fif; - header->io = io.get (); header->handle = handle; - header->changed = FALSE; header->read_only = read_only; - header->m_cachefile = NULL; header->cache_fif = fif; header->load_flags = flags; @@ -283,7 +289,7 @@ FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL crea // allocate a continueus block to describe the bitmap if (!create_new) { - header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1)); + header->m_blocks.push_back(PageBlock(BLOCK_CONTINUEUS, 0, header->page_count - 1)); } // set up the cache @@ -291,13 +297,8 @@ FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL crea if (!read_only) { std::string cache_name; ReplaceExtension(cache_name, filename, "ficache"); - - std::auto_ptr<CacheFile> cache_file (new CacheFile(cache_name, keep_cache_in_memory)); - - if (cache_file->open()) { - // we can use release() as std::bad_alloc won't be thrown from here on - header->m_cachefile = cache_file.release(); - } else { + + if (!header->m_cachefile.open(cache_name, keep_cache_in_memory)) { // an error occured ... fclose(handle); return NULL; @@ -306,15 +307,15 @@ FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL crea // return the multibitmap // std::bad_alloc won't be thrown from here on header.release(); // now owned by bitmap - io.release(); // now owned by bitmap return bitmap.release(); // now owned by caller } } } catch (std::bad_alloc &) { /** @todo report error */ } - if (handle) + if (handle) { fclose(handle); + } return NULL; } @@ -350,15 +351,11 @@ FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_h if (node) { std::auto_ptr<FIMULTIBITMAP> bitmap (new FIMULTIBITMAP); std::auto_ptr<MULTIBITMAPHEADER> header (new MULTIBITMAPHEADER); - std::auto_ptr<FreeImageIO> tmp_io (new FreeImageIO (*io)); - header->io = tmp_io.get(); - header->m_filename = NULL; + header->io = *io; header->node = node; header->fif = fif; header->handle = handle; - header->changed = FALSE; header->read_only = read_only; - header->m_cachefile = NULL; header->cache_fif = fif; header->load_flags = flags; @@ -371,18 +368,11 @@ FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_h header->page_count = FreeImage_InternalGetPageCount(bitmap.get()); // allocate a continueus block to describe the bitmap + + header->m_blocks.push_back(PageBlock(BLOCK_CONTINUEUS, 0, header->page_count - 1)); + + // no need to open cache - it is in-memory by default - header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1)); - - if (!read_only) { - // set up the cache - std::auto_ptr<CacheFile> cache_file (new CacheFile("", TRUE)); - - if (cache_file->open()) { - header->m_cachefile = cache_file.release(); - } - } - tmp_io.release(); header.release(); return bitmap.release(); } @@ -418,8 +408,8 @@ FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, if(header->handle) { // open src - header->io->seek_proc(header->handle, 0, SEEK_SET); - data_read = FreeImage_Open(header->node, header->io, header->handle, TRUE); + header->io.seek_proc(header->handle, 0, SEEK_SET); + data_read = FreeImage_Open(header->node, &header->io, header->handle, TRUE); } // write all the pages to the file using handle and io @@ -428,15 +418,13 @@ FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); i++) { if (success) { - switch((*i)->m_type) { + switch(i->m_type) { case BLOCK_CONTINUEUS: { - BlockContinueus *block = (BlockContinueus *)(*i); - - for (int j = block->m_start; j <= block->m_end; j++) { - + for (int j = i->getStart(); j <= i->getEnd(); j++) { + // load the original source data - FIBITMAP *dib = header->node->m_plugin->load_proc(header->io, header->handle, j, header->load_flags, data_read); + FIBITMAP *dib = header->node->m_plugin->load_proc(&header->io, header->handle, j, header->load_flags, data_read); // save the data success = node->m_plugin->save_proc(io, dib, handle, count, flags, data); @@ -450,17 +438,15 @@ FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, case BLOCK_REFERENCE: { - BlockReference *ref = (BlockReference *)(*i); - // read the compressed data - BYTE *compressed_data = (BYTE*)malloc(ref->m_size * sizeof(BYTE)); + BYTE *compressed_data = (BYTE*)malloc(i->getSize() * sizeof(BYTE)); - header->m_cachefile->readFile((BYTE *)compressed_data, ref->m_reference, ref->m_size); + header->m_cachefile.readFile((BYTE *)compressed_data, i->getReference(), i->getSize()); // uncompress the data - FIMEMORY *hmem = FreeImage_OpenMemory(compressed_data, ref->m_size); + FIMEMORY *hmem = FreeImage_OpenMemory(compressed_data, i->getSize()); FIBITMAP *dib = FreeImage_LoadFromMemory(header->cache_fif, hmem, 0); FreeImage_CloseMemory(hmem); @@ -486,7 +472,7 @@ FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, // close the files - FreeImage_Close(header->node, header->io, header->handle, data_read); + FreeImage_Close(header->node, &header->io, header->handle, data_read); FreeImage_Close(node, io, handle, data); @@ -507,7 +493,7 @@ FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) { MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); // saves changes only of images loaded directly from a file - if (header->changed && header->m_filename) { + if (header->changed && !header->m_filename.empty()) { try { // open a temp file @@ -524,7 +510,7 @@ FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) { FreeImage_OutputMessageProc(header->fif, "Failed to open %s, %s", spool_name.c_str(), strerror(errno)); success = FALSE; } else { - success = FreeImage_SaveMultiBitmapToHandle(header->fif, bitmap, header->io, (fi_handle)f, flags); + success = FreeImage_SaveMultiBitmapToHandle(header->fif, bitmap, &header->io, (fi_handle)f, flags); // close the files @@ -540,10 +526,10 @@ FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) { // applies changes to the destination file if (success) { - remove(header->m_filename); - success = (rename(spool_name.c_str(), header->m_filename) == 0) ? TRUE:FALSE; + remove(header->m_filename.c_str()); + success = (rename(spool_name.c_str(), header->m_filename.c_str()) == 0) ? TRUE:FALSE; if(!success) { - FreeImage_OutputMessageProc(header->fif, "Failed to rename %s to %s", spool_name.c_str(), header->m_filename); + FreeImage_OutputMessageProc(header->fif, "Failed to rename %s to %s", spool_name.c_str(), header->m_filename.c_str()); } } else { remove(spool_name.c_str()); @@ -553,24 +539,11 @@ FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) { } } else { - if (header->handle && header->m_filename) { + if (header->handle && !header->m_filename.empty()) { fclose((FILE *)header->handle); } } - // clear the blocks list - - for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); ++i) { - delete *i; - } - - // flush and dispose the cache - - if (header->m_cachefile) { - header->m_cachefile->close(); - delete header->m_cachefile; - } - // delete the last open bitmaps while (!header->locked_pages.empty()) { @@ -579,16 +552,6 @@ FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) { header->locked_pages.erase(header->locked_pages.begin()->first); } - // get rid of the IO structure - - delete header->io; - - // delete the filename - - if(header->m_filename) { - delete[] header->m_filename; - } - // delete the FIMULTIBITMAPHEADER delete header; @@ -611,15 +574,7 @@ FreeImage_GetPageCount(FIMULTIBITMAP *bitmap) { header->page_count = 0; for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); ++i) { - switch((*i)->m_type) { - case BLOCK_CONTINUEUS : - header->page_count += ((BlockContinueus *)(*i))->m_end - ((BlockContinueus *)(*i))->m_start + 1; - break; - - case BLOCK_REFERENCE : - header->page_count++; - break; - } + header->page_count += i->getPageCount(); } } @@ -629,10 +584,13 @@ FreeImage_GetPageCount(FIMULTIBITMAP *bitmap) { return 0; } -static BlockReference* +static PageBlock FreeImage_SavePageToBlock(MULTIBITMAPHEADER *header, FIBITMAP *data) { - if (header->read_only || !header->locked_pages.empty()) - return NULL; + PageBlock res; + + if (header->read_only || !header->locked_pages.empty()) { + return res; + } DWORD compressed_size = 0; BYTE *compressed_data = NULL; @@ -641,66 +599,69 @@ FreeImage_SavePageToBlock(MULTIBITMAPHEADER *header, FIBITMAP *data) { // open a memory handle FIMEMORY *hmem = FreeImage_OpenMemory(); - if(hmem==NULL) return NULL; + if(hmem==NULL) { + return res; + } // save the file to memory if(!FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0)) { FreeImage_CloseMemory(hmem); - return NULL; + return res; } // get the buffer from the memory stream if(!FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size)) { FreeImage_CloseMemory(hmem); - return NULL; + return res; } - + // write the compressed data to the cache - int ref = header->m_cachefile->writeFile(compressed_data, compressed_size); + int ref = header->m_cachefile.writeFile(compressed_data, compressed_size); // get rid of the compressed data FreeImage_CloseMemory(hmem); - - return new(std::nothrow) BlockReference(ref, compressed_size); + + res = PageBlock(BLOCK_REFERENCE, ref, compressed_size); + + return res; } void DLL_CALLCONV FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *data) { - if (!bitmap || !data) + if (!bitmap || !data) { return; - + } + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - BlockReference *block = FreeImage_SavePageToBlock(header, data); - if(block==NULL) return; - - // add the block - header->m_blocks.push_back((BlockTypeS *)block); - header->changed = TRUE; - header->page_count = -1; + + if(const PageBlock block = FreeImage_SavePageToBlock(header, data)) { + // add the block + header->m_blocks.push_back(block); + header->changed = TRUE; + header->page_count = -1; + } } void DLL_CALLCONV FreeImage_InsertPage(FIMULTIBITMAP *bitmap, int page, FIBITMAP *data) { - if (!bitmap || !data) + if (!bitmap || !data) { return; - - if (page >= FreeImage_GetPageCount(bitmap)) + } + if (page >= FreeImage_GetPageCount(bitmap)) { return; - + } + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - BlockReference *block = FreeImage_SavePageToBlock(header, data); - if(block==NULL) return; - - // add a block - if (page > 0) { - BlockListIterator block_source = FreeImage_FindBlock(bitmap, page); - - header->m_blocks.insert(block_source, (BlockTypeS *)block); - } else { - header->m_blocks.push_front((BlockTypeS *)block); + + if(const PageBlock block = FreeImage_SavePageToBlock(header, data)) { + // add a block + if (page > 0) { + BlockListIterator block_source = FreeImage_FindBlock(bitmap, page); + header->m_blocks.insert(block_source, block); + } else { + header->m_blocks.push_front(block); + } + + header->changed = TRUE; + header->page_count = -1; } - - header->changed = TRUE; - header->page_count = -1; } void DLL_CALLCONV @@ -711,21 +672,19 @@ FreeImage_DeletePage(FIMULTIBITMAP *bitmap, int page) { if ((!header->read_only) && (header->locked_pages.empty())) { if (FreeImage_GetPageCount(bitmap) > 1) { BlockListIterator i = FreeImage_FindBlock(bitmap, page); - + if (i != header->m_blocks.end()) { - switch((*i)->m_type) { + switch(i->m_type) { case BLOCK_CONTINUEUS : - delete *i; header->m_blocks.erase(i); break; - + case BLOCK_REFERENCE : - header->m_cachefile->deleteFile(((BlockReference *)(*i))->m_reference); - delete *i; + header->m_cachefile.deleteFile(i->getReference()); header->m_blocks.erase(i); break; } - + header->changed = TRUE; header->page_count = -1; } @@ -734,7 +693,6 @@ FreeImage_DeletePage(FIMULTIBITMAP *bitmap, int page) { } } - FIBITMAP * DLL_CALLCONV FreeImage_LockPage(FIMULTIBITMAP *bitmap, int page) { if (bitmap) { @@ -749,19 +707,19 @@ FreeImage_LockPage(FIMULTIBITMAP *bitmap, int page) { } // open the bitmap - - header->io->seek_proc(header->handle, 0, SEEK_SET); - - void *data = FreeImage_Open(header->node, header->io, header->handle, TRUE); - + + header->io.seek_proc(header->handle, 0, SEEK_SET); + + void *data = FreeImage_Open(header->node, &header->io, header->handle, TRUE); + // load the bitmap data - + if (data != NULL) { - FIBITMAP *dib = (header->node->m_plugin->load_proc != NULL) ? header->node->m_plugin->load_proc(header->io, header->handle, page, header->load_flags, data) : NULL; + FIBITMAP *dib = (header->node->m_plugin->load_proc != NULL) ? header->node->m_plugin->load_proc(&header->io, header->handle, page, header->load_flags, data) : NULL; // close the file - - FreeImage_Close(header->node, header->io, header->handle, data); + + FreeImage_Close(header->node, &header->io, header->handle, data); // if there was still another bitmap open, get rid of it @@ -787,7 +745,7 @@ FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed) { if (header->locked_pages.find(page) != header->locked_pages.end()) { // store the bitmap compressed in the cache for later writing - + if (changed && !header->read_only) { header->changed = TRUE; @@ -808,35 +766,15 @@ FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed) { FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size); // write the data to the cache - - switch ((*i)->m_type) { - case BLOCK_CONTINUEUS : - { - int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size); - - delete (*i); - - *i = (BlockTypeS *)new BlockReference(iPage, compressed_size); - - break; - } - - case BLOCK_REFERENCE : - { - BlockReference *reference = (BlockReference *)(*i); - - header->m_cachefile->deleteFile(reference->m_reference); - - delete (*i); - - int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size); - - *i = (BlockTypeS *)new BlockReference(iPage, compressed_size); - - break; - } + + if (i->m_type == BLOCK_REFERENCE) { + header->m_cachefile.deleteFile(i->getReference()); } - + + int iPage = header->m_cachefile.writeFile(compressed_data, compressed_size); + + *i = PageBlock(BLOCK_REFERENCE, iPage, compressed_size); + // get rid of the compressed data FreeImage_CloseMemory(hmem); @@ -863,9 +801,9 @@ FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source) { header->m_blocks.insert(block_target, *block_source); header->m_blocks.erase(block_source); - + header->changed = TRUE; - + return TRUE; } } @@ -889,8 +827,9 @@ FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count) { c++; - if (c == *count) + if (c == *count) { break; + } } } @@ -916,10 +855,6 @@ FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int PluginNode *node = list->FindNodeFromFIF(fif); if (node) { - FreeImageIO *io = new(std::nothrow) FreeImageIO; - - if (io) { - SetMemoryIO(io); FIMULTIBITMAP *bitmap = new(std::nothrow) FIMULTIBITMAP; @@ -927,14 +862,11 @@ FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int MULTIBITMAPHEADER *header = new(std::nothrow) MULTIBITMAPHEADER; if (header) { - header->m_filename = NULL; header->node = node; header->fif = fif; - header->io = io; + SetMemoryIO(&header->io); header->handle = (fi_handle)stream; - header->changed = FALSE; header->read_only = read_only; - header->m_cachefile = NULL; header->cache_fif = fif; header->load_flags = flags; @@ -947,26 +879,17 @@ FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int header->page_count = FreeImage_InternalGetPageCount(bitmap); // allocate a continueus block to describe the bitmap - - header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1)); - if (!read_only) { - // set up the cache - CacheFile *cache_file = new(std::nothrow) CacheFile("", TRUE); - - if (cache_file && cache_file->open()) { - header->m_cachefile = cache_file; - } - } + header->m_blocks.push_back(PageBlock(BLOCK_CONTINUEUS, 0, header->page_count - 1)); + + // no need to open cache - it is in-memory by default return bitmap; } delete bitmap; } - - delete io; - } + } } diff --git a/libs/freeimage/src/FreeImage/Plugin.cpp b/libs/freeimage/src/FreeImage/Plugin.cpp index 048237a540..0e5452c929 100644 --- a/libs/freeimage/src/FreeImage/Plugin.cpp +++ b/libs/freeimage/src/FreeImage/Plugin.cpp @@ -791,7 +791,7 @@ FreeImage_GetFIFFromFilenameU(const wchar_t *filename) { } BOOL DLL_CALLCONV -FreeImage_Validate(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle) { +FreeImage_ValidateFIF(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle) { if (s_plugins != NULL) { BOOL validated = FALSE; diff --git a/libs/freeimage/src/FreeImage/PluginBMP.cpp b/libs/freeimage/src/FreeImage/PluginBMP.cpp index 713a9140f7..ceae053893 100644 --- a/libs/freeimage/src/FreeImage/PluginBMP.cpp +++ b/libs/freeimage/src/FreeImage/PluginBMP.cpp @@ -1,4 +1,4 @@ -// ========================================================== +// ========================================================== // BMP Loader and Writer // // Design and implementation by @@ -7,6 +7,7 @@ // - Martin Weber (martweb@gmx.net) // - Hervé Drolon (drolon@infonie.fr) // - Michal Novotny (michal@etc.cz) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) // // This file is part of FreeImage 3 // @@ -579,8 +580,13 @@ LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bit DWORD bitfields[4]; io->read_proc(bitfields, use_bitfields * sizeof(DWORD), 1, handle); dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); - } else - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + if( bit_count == 32 ) { + dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } + } if (dib == NULL) { throw FI_MSG_ERROR_DIB_MEMORY; @@ -782,7 +788,11 @@ LoadOS22XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_ case 24 : case 32 : { - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + if( bit_count == 32 ) { + dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } if (dib == NULL) { throw FI_MSG_ERROR_DIB_MEMORY; @@ -925,7 +935,11 @@ LoadOS21XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_ case 24 : case 32 : { - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + if( bit_count == 32 ) { + dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } if (dib == NULL) { throw FI_MSG_ERROR_DIB_MEMORY; @@ -1249,16 +1263,24 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void if ((dib != NULL) && (handle != NULL)) { // write the file header + const unsigned dst_width = FreeImage_GetWidth(dib); + const unsigned dst_height = FreeImage_GetHeight(dib); + + // note that the dib may have been created using FreeImage_CreateView + // we need to recalculate the dst pitch here + const unsigned dst_bpp = FreeImage_GetBPP(dib); + const unsigned dst_pitch = CalculatePitch(CalculateLine(dst_width, dst_bpp)); + BITMAPFILEHEADER bitmapfileheader; bitmapfileheader.bfType = 0x4D42; bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD); - bitmapfileheader.bfSize = bitmapfileheader.bfOffBits + FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib); + bitmapfileheader.bfSize = bitmapfileheader.bfOffBits + dst_height * dst_pitch; bitmapfileheader.bfReserved1 = 0; bitmapfileheader.bfReserved2 = 0; // take care of the bit fields data of any - bool bit_fields = (FreeImage_GetBPP(dib) == 16); + bool bit_fields = (dst_bpp == 16) ? true : false; if (bit_fields) { bitmapfileheader.bfSize += 3 * sizeof(DWORD); @@ -1268,28 +1290,33 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void #ifdef FREEIMAGE_BIGENDIAN SwapFileHeader(&bitmapfileheader); #endif - if (io->write_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle) != 1) - return FALSE; + if (io->write_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle) != 1) { + return FALSE; + } // update the bitmap info header BITMAPINFOHEADER bih; memcpy(&bih, FreeImage_GetInfoHeader(dib), sizeof(BITMAPINFOHEADER)); - if (bit_fields) + if (bit_fields) { bih.biCompression = BI_BITFIELDS; - else if ((bih.biBitCount == 8) && (flags & BMP_SAVE_RLE)) + } + else if ((bih.biBitCount == 8) && ((flags & BMP_SAVE_RLE) == BMP_SAVE_RLE)) { bih.biCompression = BI_RLE8; - else + } + else { bih.biCompression = BI_RGB; + } // write the bitmap info header #ifdef FREEIMAGE_BIGENDIAN SwapInfoHeader(&bih); #endif - if (io->write_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1) + if (io->write_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1) { return FALSE; + } // write the bit fields when we are dealing with a 16 bit BMP @@ -1298,18 +1325,21 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void d = FreeImage_GetRedMask(dib); - if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) + if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) { return FALSE; + } d = FreeImage_GetGreenMask(dib); - if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) + if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) { return FALSE; + } d = FreeImage_GetBlueMask(dib); - if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) + if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) { return FALSE; + } } // write the palette @@ -1322,18 +1352,18 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void bgra.g = pal[i].rgbGreen; bgra.r = pal[i].rgbRed; bgra.a = pal[i].rgbReserved; - if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1) + if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1) { return FALSE; + } } } // write the bitmap data... if RLE compression is enable, use it - unsigned bpp = FreeImage_GetBPP(dib); - if ((bpp == 8) && (flags & BMP_SAVE_RLE)) { - BYTE *buffer = (BYTE*)malloc(FreeImage_GetPitch(dib) * 2 * sizeof(BYTE)); + if ((dst_bpp == 8) && ((flags & BMP_SAVE_RLE) == BMP_SAVE_RLE)) { + BYTE *buffer = (BYTE*)malloc(dst_pitch * 2 * sizeof(BYTE)); - for (DWORD i = 0; i < FreeImage_GetHeight(dib); ++i) { + for (unsigned i = 0; i < dst_height; ++i) { int size = RLEEncodeLine(buffer, FreeImage_GetScanLine(dib, i), FreeImage_GetLine(dib)); if (io->write_proc(buffer, size, 1, handle) != 1) { @@ -1353,16 +1383,17 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void free(buffer); #ifdef FREEIMAGE_BIGENDIAN } else if (bpp == 16) { - int padding = FreeImage_GetPitch(dib) - FreeImage_GetWidth(dib) * sizeof(WORD); + int padding = dst_pitch - dst_width * sizeof(WORD); WORD pad = 0; WORD pixel; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + for(unsigned y = 0; y < dst_height; y++) { BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { + for(unsigned x = 0; x < dst_width; x++) { pixel = ((WORD *)line)[x]; SwapShort(&pixel); - if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1) + if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1) { return FALSE; + } } if(padding != 0) { if(io->write_proc(&pad, padding, 1, handle) != 1) { @@ -1373,18 +1404,19 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void #endif #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB } else if (bpp == 24) { - int padding = FreeImage_GetPitch(dib) - FreeImage_GetWidth(dib) * sizeof(FILE_BGR); + int padding = dst_pitch - dst_width * sizeof(FILE_BGR); DWORD pad = 0; FILE_BGR bgr; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + for(unsigned y = 0; y < dst_height; y++) { BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { + for(unsigned x = 0; x < dst_width; x++) { RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x; bgr.b = triple->rgbtBlue; bgr.g = triple->rgbtGreen; bgr.r = triple->rgbtRed; - if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1) + if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1) { return FALSE; + } } if(padding != 0) { if(io->write_proc(&pad, padding, 1, handle) != 1) { @@ -1394,24 +1426,36 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void } } else if (bpp == 32) { FILE_BGRA bgra; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + for(unsigned y = 0; y < dst_height; y++) { BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { + for(unsigned x = 0; x < dst_width; x++) { RGBQUAD *quad = ((RGBQUAD *)line)+x; bgra.b = quad->rgbBlue; bgra.g = quad->rgbGreen; bgra.r = quad->rgbRed; bgra.a = quad->rgbReserved; - if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1) + if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1) { return FALSE; + } } } #endif - } else if (io->write_proc(FreeImage_GetBits(dib), FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib), 1, handle) != 1) { - return FALSE; + } + else if (FreeImage_GetPitch(dib) == dst_pitch) { + return (io->write_proc(FreeImage_GetBits(dib), dst_height * dst_pitch, 1, handle) != 1) ? FALSE : TRUE; + } + else { + for (unsigned y = 0; y < dst_height; y++) { + BYTE *line = (BYTE*)FreeImage_GetScanLine(dib, y); + + if (io->write_proc(line, dst_pitch, 1, handle) != 1) { + return FALSE; + } + } } return TRUE; + } else { return FALSE; } diff --git a/libs/freeimage/src/FreeImage/PluginGIF.cpp b/libs/freeimage/src/FreeImage/PluginGIF.cpp index 1a7a84041b..8fe0422b31 100644 --- a/libs/freeimage/src/FreeImage/PluginGIF.cpp +++ b/libs/freeimage/src/FreeImage/PluginGIF.cpp @@ -3,9 +3,13 @@ // // Design and implementation by // - Ryan Rubley <ryan@lostreality.org> -// - Raphaлl Gaquer <raphael.gaquer@alcer.com> +// - Raphaël Gaquer <raphael.gaquer@alcer.com> // - Aaron Shumate <aaron@shumate.us> // +// References +// http://www.w3.org/Graphics/GIF/spec-gif87.txt +// http://www.w3.org/Graphics/GIF/spec-gif89a.txt +// // This file is part of FreeImage 3 // // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY @@ -41,6 +45,7 @@ // Constant/Typedef declarations // ========================================================== + struct GIFinfo { BOOL read; //only really used when reading @@ -488,23 +493,20 @@ MimeType() { return "image/gif"; } -static BOOL DLL_CALLCONV +static BOOL DLL_CALLCONV Validate(FreeImageIO *io, fi_handle handle) { - char buf[6]; - if( io->read_proc(buf, 6, 1, handle) < 1 ) { - return FALSE; - } + BYTE GIF89a[] = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }; // ASCII code for "GIF89a" + BYTE GIF87a[] = { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }; // ASCII code for "GIF87a" + BYTE signature[6] = { 0, 0, 0, 0, 0, 0 }; - BOOL bResult = FALSE; - if( !strncmp(buf, "GIF", 3) ) { - if( buf[3] >= '0' && buf[3] <= '9' && buf[4] >= '0' && buf[4] <= '9' && buf[5] >= 'a' && buf[5] <= 'z' ) { - bResult = TRUE; - } - } + io->read_proc(signature, 1, 6, handle); - io->seek_proc(handle, -6, SEEK_CUR); + if (memcmp(GIF89a, signature, 6) == 0) + return TRUE; + if (memcmp(GIF87a, signature, 6) == 0) + return TRUE; - return bResult; + return FALSE; } static BOOL DLL_CALLCONV @@ -528,18 +530,15 @@ Open(FreeImageIO *io, fi_handle handle, BOOL read) { return NULL; } - // 25/02/2008 MDA: Not safe to memset GIFinfo structure with VS 2008 (safe iterators), - // perform initialization in constructor instead. - // memset(info, 0, sizeof(GIFinfo)); - + // set Read/Write mode info->read = read; + if( read ) { try { - //Header + // read Header (6 bytes) if( !Validate(io, handle) ) { throw FI_MSG_ERROR_MAGIC_NUMBER; } - io->seek_proc(handle, 6, SEEK_CUR); //Logical Screen Descriptor io->seek_proc(handle, 4, SEEK_CUR); @@ -1013,19 +1012,19 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { } FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "Loop", ANIMTAG_LOOP, FIDT_LONG, 1, 4, &loop); - // Comment Extension - for (idx = 0; idx < info->comment_extension_offsets.size(); idx++) { + //Comment Extension + for( idx = 0; idx < info->comment_extension_offsets.size(); idx++ ) { io->seek_proc(handle, (long)info->comment_extension_offsets[idx], SEEK_SET); std::string comment; char buf[255]; io->read_proc(&b, 1, 1, handle); - while (b) { + while( b ) { io->read_proc(buf, b, 1, handle); comment.append(buf, b); io->read_proc(&b, 1, 1, handle); } comment.append(1, '\0'); - sprintf(buf, "Comment%d", (int)idx); + sprintf(buf, "Comment%zd", idx); DWORD comment_size = (DWORD)comment.size(); FreeImage_SetMetadataEx(FIMD_COMMENTS, dib, buf, 1, FIDT_ASCII, comment_size, comment_size, comment.c_str()); } diff --git a/libs/freeimage/src/FreeImage/PluginJPEG.cpp b/libs/freeimage/src/FreeImage/PluginJPEG.cpp index 49e653d9e0..4dbd5d26a6 100644 --- a/libs/freeimage/src/FreeImage/PluginJPEG.cpp +++ b/libs/freeimage/src/FreeImage/PluginJPEG.cpp @@ -1,4 +1,4 @@ -// ========================================================== +// ========================================================== // JPEG Loader and writer // Based on code developed by The Independent JPEG Group // @@ -1126,8 +1126,9 @@ Validate(FreeImageIO *io, fi_handle handle) { static BOOL DLL_CALLCONV SupportsExportDepth(int depth) { return ( - (depth == 8) || - (depth == 24) + (depth == 8) || + (depth == 24) || + (depth == 32) // only if 32-bit CMYK ); } @@ -1315,6 +1316,10 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { dst += 3; } } + + // if original image is CMYK but is converted to RGB, remove ICC profile from Exif-TIFF metadata + FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, "InterColorProfile", NULL); + } else if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) == JPEG_CMYK)) { // convert from LibJPEG CMYK to standard CMYK @@ -1400,12 +1405,12 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void try { // Check dib format - const char *sError = "only 24-bit highcolor or 8-bit greyscale/palette bitmaps can be saved as JPEG"; + const char *sError = "only 24-bit RGB, 8-bit greyscale/palette or 32-bit CMYK bitmaps can be saved as JPEG"; FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); WORD bpp = (WORD)FreeImage_GetBPP(dib); - if ((bpp != 24) && (bpp != 8)) { + if ((bpp != 24) && (bpp != 8) && !(bpp == 32 && (color_type == FIC_CMYK))) { throw sError; } @@ -1454,7 +1459,10 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void cinfo.in_color_space = JCS_GRAYSCALE; cinfo.input_components = 1; break; - + case FIC_CMYK: + cinfo.in_color_space = JCS_CMYK; + cinfo.input_components = 4; + break; default : cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3; @@ -1481,14 +1489,14 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void // thumbnail support (JFIF 1.02 extension markers) if(FreeImage_GetThumbnail(dib) != NULL) { - cinfo.write_JFIF_header = 1; //<### force it, though when color is CMYK it will be incorrect + cinfo.write_JFIF_header = static_cast<boolean>(1); //<### force it, though when color is CMYK it will be incorrect cinfo.JFIF_minor_version = 2; } // baseline JPEG support - if ((flags & JPEG_BASELINE) == JPEG_BASELINE) { - cinfo.write_JFIF_header = 0; // No marker for non-JFIF colorspaces - cinfo.write_Adobe_marker = 0; // write no Adobe marker by default + if ((flags & JPEG_BASELINE) == JPEG_BASELINE) { + cinfo.write_JFIF_header = static_cast<boolean>(0); // No marker for non-JFIF colorspaces + cinfo.write_Adobe_marker = static_cast<boolean>(0); // write no Adobe marker by default } // set subsampling options if required @@ -1598,6 +1606,33 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void } free(target); } + else if(color_type == FIC_CMYK) { + unsigned pitch = FreeImage_GetPitch(dib); + BYTE *target = (BYTE*)malloc(pitch * sizeof(BYTE)); + if (target == NULL) { + throw FI_MSG_ERROR_MEMORY; + } + + while (cinfo.next_scanline < cinfo.image_height) { + // get a copy of the scanline + memcpy(target, FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1), pitch); + + BYTE *target_p = target; + for(unsigned x = 0; x < cinfo.image_width; x++) { + // CMYK pixels are inverted + target_p[0] = ~target_p[0]; // C + target_p[1] = ~target_p[1]; // M + target_p[2] = ~target_p[2]; // Y + target_p[3] = ~target_p[3]; // K + + target_p += 4; + } + + // write the scanline + jpeg_write_scanlines(&cinfo, &target, 1); + } + free(target); + } else if(color_type == FIC_MINISBLACK) { // 8-bit standard greyscale images while (cinfo.next_scanline < cinfo.image_height) { diff --git a/libs/freeimage/src/FreeImage/PluginPNG.cpp b/libs/freeimage/src/FreeImage/PluginPNG.cpp index 0753192140..c64f12d465 100644 --- a/libs/freeimage/src/FreeImage/PluginPNG.cpp +++ b/libs/freeimage/src/FreeImage/PluginPNG.cpp @@ -1,9 +1,9 @@ -// ========================================================== +// ========================================================== // PNG Loader and Writer // // Design and implementation by // - Floris van den Berg (flvdberg@wxs.nl) -// - Herve Drolon (drolon@infonie.fr) +// - Hervé Drolon (drolon@infonie.fr) // - Detlev Vendt (detlev.vendt@brillit.de) // - Aaron Shumate (trek@startreker.com) // - Tanner Helland (tannerhelland@users.sf.net) @@ -50,6 +50,12 @@ typedef struct { } fi_ioStructure, *pfi_ioStructure; // ========================================================== +// Plugin Interface +// ========================================================== + +static int s_format_id; + +// ========================================================== // libpng interface // ========================================================== @@ -76,8 +82,8 @@ _FlushProc(png_structp png_ptr) { static void error_handler(png_structp png_ptr, const char *error) { - (png_structp)png_ptr; - throw error; + FreeImage_OutputMessageProc(s_format_id, error); + png_longjmp(png_ptr, 1); } // in FreeImage warnings disabled @@ -234,12 +240,6 @@ WriteMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) { } // ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== // Plugin Implementation // ========================================================== @@ -548,11 +548,13 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { // init the IO - png_set_read_fn(png_ptr, &fio, _ReadProc); + png_set_read_fn(png_ptr, &fio, _ReadProc); + + // PNG errors will be redirected here - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return NULL; + if (setjmp(png_jmpbuf(png_ptr))) { + // assume error_handler was called before by the PNG library + throw((const char*)NULL); } // because we have already read the signature... @@ -789,7 +791,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { if (dib) { FreeImage_Unload(dib); } - FreeImage_OutputMessageProc(s_format_id, text); + if (NULL != text) { + FreeImage_OutputMessageProc(s_format_id, text); + } return NULL; } @@ -990,6 +994,8 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); if (iccProfile->size && iccProfile->data) { + // skip ICC profile check + png_set_option(png_ptr, PNG_SKIP_sRGB_CHECK_PROFILE, 1); png_set_iCCP(png_ptr, info_ptr, "Embedded Profile", 0, (png_const_bytep)iccProfile->data, iccProfile->size); } diff --git a/libs/freeimage/src/FreeImageToolkit/BSplineRotate.cpp b/libs/freeimage/src/FreeImageToolkit/BSplineRotate.cpp index c58c46af2b..6c4c7a7bd2 100644 --- a/libs/freeimage/src/FreeImageToolkit/BSplineRotate.cpp +++ b/libs/freeimage/src/FreeImageToolkit/BSplineRotate.cpp @@ -1,4 +1,4 @@ -// ========================================================== +// ========================================================== // Bitmap rotation using B-Splines // // Design and implementation by @@ -667,7 +667,11 @@ FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, // allocate dst image int width = FreeImage_GetWidth(dib); int height = FreeImage_GetHeight(dib); - dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + if( bpp == 24 ) { + dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } if(!dst) throw(1); // allocate a temporary 8-bit dib (no need to build a palette) diff --git a/libs/freeimage/src/FreeImageToolkit/Display.cpp b/libs/freeimage/src/FreeImageToolkit/Display.cpp index deaefe5a39..aa61f37493 100644 --- a/libs/freeimage/src/FreeImageToolkit/Display.cpp +++ b/libs/freeimage/src/FreeImageToolkit/Display.cpp @@ -1,4 +1,4 @@ -// ========================================================== +// ========================================================== // Display routines // // Design and implementation by @@ -191,7 +191,7 @@ channel(x, y) = channel(x, y) * alpha_channel(x, y) / 255 @return Returns TRUE on success, FALSE otherwise (e.g. when the bitdepth of the source dib cannot be handled). */ BOOL DLL_CALLCONV -FreeImage_PremultiplyWithAlpha(FIBITMAP *dib) { +FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib) { if (!FreeImage_HasPixels(dib)) return FALSE; if ((FreeImage_GetBPP(dib) != 32) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { diff --git a/libs/freeimage/src/MapIntrospector.h b/libs/freeimage/src/MapIntrospector.h index 091ba68b26..4c10c2cafa 100644 --- a/libs/freeimage/src/MapIntrospector.h +++ b/libs/freeimage/src/MapIntrospector.h @@ -19,8 +19,8 @@ // Use at your own risk! // ========================================================== -#ifndef MAPINTROSPECTOR_H_ -#define MAPINTROSPECTOR_H_ +#ifndef FREEIMAGE_MAPINTROSPECTOR_H_ +#define FREEIMAGE_MAPINTROSPECTOR_H_ // we need at least one C++ header included, // that defines the C++ Standard Library's version macro, @@ -209,4 +209,5 @@ public: #endif // Standard C++ Library -#endif // MAPINTROSPECTOR_H_ +#endif // FREEIMAGE_MAPINTROSPECTOR_H_ + diff --git a/libs/freeimage/src/Metadata/Exif.cpp b/libs/freeimage/src/Metadata/Exif.cpp index 1d456ab3bd..8c37455b32 100644 --- a/libs/freeimage/src/Metadata/Exif.cpp +++ b/libs/freeimage/src/Metadata/Exif.cpp @@ -1,10 +1,11 @@ -// ========================================================== +// ========================================================== // Metadata functions implementation // Exif metadata model // // Design and implementation by // - Hervé Drolon (drolon@infonie.fr) // - Mihail Naydenov (mnaydenov@users.sourceforge.net) +// - Garrick Meeker (garrickmeeker@users.sourceforge.net) // // Based on the following implementations: // - metadata-extractor : http://www.drewnoakes.com/code/exif/ @@ -1251,3 +1252,106 @@ tiff_get_ifd_profile(FIBITMAP *dib, FREE_IMAGE_MDMODEL md_model, BYTE **ppbProfi return FALSE; } } + +// ---------------------------------------------------------- +// Exif PSD routines +// ---------------------------------------------------------- + +/** +Read and decode PSD image resource (Exif profile) +@param dib Input FIBITMAP +@param data Pointer to the resource data +@param length Resource length +@return Returns TRUE if successful, FALSE otherwise +*/ +BOOL +psd_read_exif_profile(FIBITMAP *dib, const BYTE *data, unsigned int length) { + BYTE lsb_first[4] = { 0x49, 0x49, 0x2A, 0x00 }; // Classic TIFF signature - little-endian order + BYTE msb_first[4] = { 0x4D, 0x4D, 0x00, 0x2A }; // Classic TIFF signature - big-endian order + + // profile size is up to 32-bit + DWORD dwProfileLength = (DWORD)length; + BYTE *pbProfile = (BYTE*)data; + + // This is an Exif profile + // should contain a TIFF header with up to 2 IFDs (IFD stands for 'Image File Directory') + // 0th IFD : the image attributes, 1st IFD : may be used for thumbnail + + // read the TIFF header (8 bytes) + + // check the endianess order + + BOOL bBigEndian = TRUE; + + if(memcmp(pbProfile, lsb_first, sizeof(lsb_first)) == 0) { + // Exif section is in little-endian order + bBigEndian = FALSE; + } else { + if(memcmp(pbProfile, msb_first, sizeof(msb_first)) == 0) { + // Exif section is in big-endian order + bBigEndian = TRUE; + } else { + // Invalid Exif alignment marker + return FALSE; + } + } + + // this is the offset to the first IFD (Image File Directory) + DWORD dwFirstOffset = ReadUint32(bBigEndian, pbProfile + 4); + if (dwFirstOffset > dwProfileLength) { + // bad Exif data + return FALSE; + } + + // process Exif directories, starting with Exif-TIFF IFD + return jpeg_read_exif_dir(dib, pbProfile, dwFirstOffset, dwProfileLength, 0, bBigEndian, TagLib::EXIF_MAIN); +} + +/** +Read PSD image resource (Exif profile) +@param dib Input FIBITMAP +@param dataptr Pointer to the resource data +@param datalen Resource length +@return Returns TRUE if successful, FALSE otherwise +*/ +BOOL +psd_read_exif_profile_raw(FIBITMAP *dib, const BYTE *profile, unsigned length) { + // marker identifying string for Exif = "Exif\0\0" + // used by JPEG not PSD + BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; + + if(NULL == profile || length == 0) { + return FALSE; + } + + DWORD dwProfileLength = (DWORD)length + sizeof(exif_signature); + BYTE *pbProfile = (BYTE*)malloc(dwProfileLength); + if(NULL == pbProfile) { + // out of memory ... + return FALSE; + } + memcpy(pbProfile, exif_signature, sizeof(exif_signature)); + memcpy(pbProfile + sizeof(exif_signature), profile, length); + + // create a tag + FITAG *tag = FreeImage_CreateTag(); + BOOL bSuccess = FALSE; + if(tag) { + FreeImage_SetTagKey(tag, g_TagLib_ExifRawFieldName); + FreeImage_SetTagLength(tag, dwProfileLength); + FreeImage_SetTagCount(tag, dwProfileLength); + FreeImage_SetTagType(tag, FIDT_BYTE); + FreeImage_SetTagValue(tag, pbProfile); + + // store the tag + FreeImage_SetMetadata(FIMD_EXIF_RAW, dib, FreeImage_GetTagKey(tag), tag); + + // destroy the tag + FreeImage_DeleteTag(tag); + + bSuccess = TRUE; + } + free(pbProfile); + + return bSuccess; +} diff --git a/libs/freeimage/src/Metadata/FreeImageTag.h b/libs/freeimage/src/Metadata/FreeImageTag.h index 5a6e4f99f6..728470f806 100644 --- a/libs/freeimage/src/Metadata/FreeImageTag.h +++ b/libs/freeimage/src/Metadata/FreeImageTag.h @@ -1,4 +1,4 @@ -// ========================================================== +// ========================================================== // Tag manipulation functions // // Design and implementation by @@ -19,8 +19,8 @@ // Use at your own risk! // ========================================================== -#ifndef FREEIMAGETAG_H -#define FREEIMAGETAG_H +#ifndef FREEIMAGE_TAG_H +#define FREEIMAGE_TAG_H // ========================================================== // Exif JPEG tags @@ -484,7 +484,13 @@ BOOL jpegxr_read_exif_gps_profile(FIBITMAP *dib, const BYTE *profile, unsigned l BOOL tiff_get_ifd_profile(FIBITMAP *dib, FREE_IMAGE_MDMODEL md_model, BYTE **ppbProfile, unsigned *uProfileLength); -// JPEG / TIFF IPTC profile (see IPTC.cpp) +// PSD Exif profile (see Exif.cpp) +// -------------------------------------------------------------------------- +BOOL psd_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned datalen); +BOOL psd_read_exif_profile_raw(FIBITMAP *dib, const BYTE *dataptr, unsigned datalen); + + +// JPEG / PSD / TIFF IPTC profile (see IPTC.cpp) // -------------------------------------------------------------------------- BOOL read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen); BOOL write_iptc_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size); @@ -494,6 +500,6 @@ BOOL write_iptc_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size); #endif -#endif // FREEIMAGETAG_H +#endif // FREEIMAGE_TAG_H diff --git a/libs/freeimage/src/Plugin.h b/libs/freeimage/src/Plugin.h index 76ffc90522..5886fd7721 100644 --- a/libs/freeimage/src/Plugin.h +++ b/libs/freeimage/src/Plugin.h @@ -97,7 +97,7 @@ int FreeImage_stricmp(const char *s1, const char *s2); // ========================================================== extern "C" { - BOOL DLL_CALLCONV FreeImage_Validate(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle); + BOOL DLL_CALLCONV FreeImage_ValidateFIF(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle); void * DLL_CALLCONV FreeImage_Open(PluginNode *node, FreeImageIO *io, fi_handle handle, BOOL open_for_reading); void DLL_CALLCONV FreeImage_Close(PluginNode *node, FreeImageIO *io, fi_handle handle, void *data); // plugin.cpp PluginList * DLL_CALLCONV FreeImage_GetPluginList(); // plugin.cpp diff --git a/libs/freeimage/src/Quantizers.h b/libs/freeimage/src/Quantizers.h index a6f0acd17c..23c4b7afca 100644 --- a/libs/freeimage/src/Quantizers.h +++ b/libs/freeimage/src/Quantizers.h @@ -1,4 +1,4 @@ -// ============================================================= +// ============================================================= // Quantizer objects and functions // // Design and implementation by: @@ -20,7 +20,8 @@ // Use at your own risk! // ============================================================= -#pragma once +#ifndef FREEIMAGE_QUANTIZER_H +#define FREEIMAGE_QUANTIZER_H // //////////////////////////////////////////////////////////////// @@ -354,3 +355,5 @@ protected: void WritePalette(void *palette); }; + +#endif // FREEIMAGE_QUANTIZER_H diff --git a/libs/freeimage/src/ToneMapping.h b/libs/freeimage/src/ToneMapping.h index 20f283fee9..692e2ee496 100644 --- a/libs/freeimage/src/ToneMapping.h +++ b/libs/freeimage/src/ToneMapping.h @@ -1,4 +1,4 @@ -// ========================================================== +// ========================================================== // High Dynamic Range bitmap conversion routines // // Design and implementation by @@ -19,8 +19,8 @@ // Use at your own risk! // ========================================================== -#ifndef TONE_MAPPING_H -#define TONE_MAPPING_H +#ifndef FREEIMAGE_TONE_MAPPING_H +#define FREEIMAGE_TONE_MAPPING_H #ifdef __cplusplus extern "C" { @@ -41,4 +41,5 @@ FIBITMAP* ClampConvertRGBFTo24(FIBITMAP *src); } #endif -#endif // TONE_MAPPING_H +#endif // FREEIMAGE_TONE_MAPPING_H + diff --git a/libs/freeimage/src/Utilities.h b/libs/freeimage/src/Utilities.h index adc16e31eb..8afb1c918a 100644 --- a/libs/freeimage/src/Utilities.h +++ b/libs/freeimage/src/Utilities.h @@ -22,8 +22,8 @@ // Use at your own risk! // ========================================================== -#ifndef UTILITIES_H -#define UTILITIES_H +#ifndef FREEIMAGE_UTILITIES_H +#define FREEIMAGE_UTILITIES_H // ========================================================== // Bitmap palette and pixels alignment @@ -249,25 +249,26 @@ CalculateUsedBits(int bits) { } inline unsigned -CalculateLine(unsigned width, unsigned bitdepth) { +CalculateLine(const unsigned width, const unsigned bitdepth) { return (unsigned)( ((unsigned long long)width * bitdepth + 7) / 8 ); } inline unsigned -CalculatePitch(unsigned line) { - return line + 3 & ~3; +CalculatePitch(const unsigned line) { + return (line + 3) & ~3; } inline unsigned -CalculateUsedPaletteEntries(unsigned bit_count) { - if ((bit_count >= 1) && (bit_count <= 8)) +CalculateUsedPaletteEntries(const unsigned bit_count) { + if ((bit_count >= 1) && (bit_count <= 8)) { return 1 << bit_count; + } return 0; } -inline unsigned char * -CalculateScanLine(unsigned char *bits, unsigned pitch, int scanline) { +inline BYTE* +CalculateScanLine(BYTE *bits, const unsigned pitch, const int scanline) { return bits ? (bits + ((size_t)pitch * scanline)) : NULL; } @@ -406,25 +407,6 @@ __SwapUInt32(DWORD arg) { return result; #endif } - -/** -for later use ... -inline uint64_t -SwapInt64(uint64_t arg) { -#if defined(_MSC_VER) && _MSC_VER >= 1310 - return _byteswap_uint64(arg); -#else - union Swap { - uint64_t sv; - uint32_t ul[2]; - } tmp, result; - tmp.sv = arg; - result.ul[0] = SwapInt32(tmp.ul[1]); - result.ul[1] = SwapInt32(tmp.ul[0]); - return result.sv; -#endif -} -*/ inline void SwapShort(WORD *sp) { @@ -435,6 +417,24 @@ inline void SwapLong(DWORD *lp) { *lp = __SwapUInt32(*lp); } + +inline void +SwapInt64(UINT64 *arg) { +#if defined(_MSC_VER) && _MSC_VER >= 1310 + *arg = _byteswap_uint64(*arg); +#else + union Swap { + UINT64 sv; + DWORD ul[2]; + } tmp, result; + tmp.sv = *arg; + SwapLong(&tmp.ul[0]); + SwapLong(&tmp.ul[1]); + result.ul[0] = tmp.ul[1]; + result.ul[1] = tmp.ul[0]; + *arg = result.sv; +#endif +} // ========================================================== // Greyscale and color conversion @@ -458,17 +458,37 @@ A Standard Default Color Space for the Internet - sRGB. #define GREY(r, g, b) (BYTE)(((WORD)r * 169 + (WORD)g * 256 + (WORD)b * 87) >> 9) // .33R + 0.5G + .17B */ +/** +Convert a RGB 24-bit value to a 16-bit 565 value +*/ #define RGB565(b, g, r) ((((b) >> 3) << FI16_565_BLUE_SHIFT) | (((g) >> 2) << FI16_565_GREEN_SHIFT) | (((r) >> 3) << FI16_565_RED_SHIFT)) + +/** +Convert a RGB 24-bit value to a 16-bit 555 value +*/ #define RGB555(b, g, r) ((((b) >> 3) << FI16_555_BLUE_SHIFT) | (((g) >> 3) << FI16_555_GREEN_SHIFT) | (((r) >> 3) << FI16_555_RED_SHIFT)) +/** +Returns TRUE if the format of a dib is RGB565 +*/ #define IS_FORMAT_RGB565(dib) ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) + +/** +Convert a RGB565 or RGB555 RGBQUAD pixel to a WORD +*/ #define RGBQUAD_TO_WORD(dib, color) (IS_FORMAT_RGB565(dib) ? RGB565((color)->rgbBlue, (color)->rgbGreen, (color)->rgbRed) : RGB555((color)->rgbBlue, (color)->rgbGreen, (color)->rgbRed)) +/** +Create a greyscale palette +*/ #define CREATE_GREYSCALE_PALETTE(palette, entries) \ for (unsigned i = 0, v = 0; i < entries; i++, v += 0x00FFFFFF / (entries - 1)) { \ ((unsigned *)palette)[i] = v; \ } +/** +Create a reverse greyscale palette +*/ #define CREATE_GREYSCALE_PALETTE_REVERSE(palette, entries) \ for (unsigned i = 0, v = 0x00FFFFFF; i < entries; i++, v -= (0x00FFFFFF / (entries - 1))) { \ ((unsigned *)palette)[i] = v; \ @@ -486,4 +506,4 @@ static const char *FI_MSG_ERROR_UNSUPPORTED_FORMAT = "Unsupported format"; static const char *FI_MSG_ERROR_UNSUPPORTED_COMPRESSION = "Unsupported compression type"; static const char *FI_MSG_WARNING_INVALID_THUMBNAIL = "Warning: attached thumbnail cannot be written to output file (invalid format) - Thumbnail saving aborted"; -#endif // UTILITIES_H +#endif // FREEIMAGE_UTILITIES_H |