diff options
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage')
45 files changed, 0 insertions, 22944 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp b/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp deleted file mode 100644 index 2fbec7ab24..0000000000 --- a/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp +++ /dev/null @@ -1,1573 +0,0 @@ -// ========================================================== -// FreeImage implementation -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Detlev Vendt (detlev.vendt@brillit.de) -// - Petr Supina (psup@centrum.cz) -// - Carsten Klein (c.klein@datagis.com) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#include <stdlib.h> -#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__) -#include <malloc.h> -#endif // _WIN32 || _WIN64 || __MINGW32__ - -#include "FreeImage.h" -#include "FreeImageIO.h" -#include "Utilities.h" -#include "MapIntrospector.h" - -#include "../Metadata/FreeImageTag.h" - -/** -Constants for the BITMAPINFOHEADER::biCompression field -BI_RGB: -The bitmap is in uncompressed red green blue (RGB) format that is not compressed and does not use color masks. -BI_BITFIELDS: -The bitmap is not compressed and the color table consists of three DWORD color masks that specify the red, green, and blue components, -respectively, of each pixel. This is valid when used with 16 and 32-bits per pixel bitmaps. -*/ -#ifndef _WINGDI_ -#define BI_RGB 0L -#define BI_BITFIELDS 3L -#endif // _WINGDI_ - -// ---------------------------------------------------------- -// Metadata definitions -// ---------------------------------------------------------- - -/** helper for map<key, value> where value is a pointer to a FreeImage tag */ -typedef std::map<std::string, FITAG*> TAGMAP; - -/** helper for map<FREE_IMAGE_MDMODEL, TAGMAP*> */ -typedef std::map<int, TAGMAP*> METADATAMAP; - -/** helper for metadata iterator */ -FI_STRUCT (METADATAHEADER) { - long pos; //! current position when iterating the map - TAGMAP *tagmap; //! pointer to the tag map -}; - -// ---------------------------------------------------------- -// FIBITMAP definition -// ---------------------------------------------------------- - -/** -FreeImage header structure -*/ -FI_STRUCT (FREEIMAGEHEADER) { - /** data type - bitmap, array of long, double, complex, etc */ - FREE_IMAGE_TYPE type; - - /** background color used for RGB transparency */ - RGBQUAD bkgnd_color; - - /**@name transparency management */ - //@{ - /** - why another table ? for easy transparency table retrieval ! - transparency could be stored in the palette, which is better - overall, but it requires quite some changes and it will render - FreeImage_GetTransparencyTable obsolete in its current form; - */ - BYTE transparent_table[256]; - /** number of transparent colors */ - int transparency_count; - /** TRUE if the image is transparent */ - BOOL transparent; - //@} - - /** space to hold ICC profile */ - FIICCPROFILE iccProfile; - - /** contains a list of metadata models attached to the bitmap */ - METADATAMAP *metadata; - - /** FALSE if the FIBITMAP only contains the header and no pixel data */ - BOOL has_pixels; - - /** optionally contains a thumbnail attached to the bitmap */ - FIBITMAP *thumbnail; - - /**@name external pixel buffer management */ - //@{ - /** pointer to user provided pixels, NULL otherwise */ - BYTE *external_bits; - /** user provided pitch, 0 otherwise */ - unsigned external_pitch; - //@} - - //BYTE filler[1]; // fill to 32-bit alignment -}; - -// ---------------------------------------------------------- -// FREEIMAGERGBMASKS definition -// ---------------------------------------------------------- - -/** -RGB mask structure - mainly used for 16-bit RGB555 / RGB 565 FIBITMAP -*/ -FI_STRUCT (FREEIMAGERGBMASKS) { - unsigned red_mask; //! bit layout of the red components - unsigned green_mask; //! bit layout of the green components - unsigned blue_mask; //! bit layout of the blue components -}; - -// ---------------------------------------------------------- -// Memory allocation on a specified alignment boundary -// ---------------------------------------------------------- - -#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) - -void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) { - assert(alignment == FIBITMAP_ALIGNMENT); - return _aligned_malloc(amount, alignment); -} - -void FreeImage_Aligned_Free(void* mem) { - _aligned_free(mem); -} - -#elif defined (__MINGW32__) - -void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) { - assert(alignment == FIBITMAP_ALIGNMENT); - return __mingw_aligned_malloc (amount, alignment); -} - -void FreeImage_Aligned_Free(void* mem) { - __mingw_aligned_free (mem); -} - -#else - -void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) { - assert(alignment == FIBITMAP_ALIGNMENT); - /* - In some rare situations, the malloc routines can return misaligned memory. - The routine FreeImage_Aligned_Malloc allocates a bit more memory to do - aligned writes. Normally, it *should* allocate "alignment" extra memory and then writes - one dword back the true pointer. But if the memory manager returns a - misaligned block that is less than a dword from the next alignment, - then the writing back one dword will corrupt memory. - - For example, suppose that alignment is 16 and malloc returns the address 0xFFFF. - - 16 - 0xFFFF % 16 + 0xFFFF = 16 - 15 + 0xFFFF = 0x10000. - - Now, you subtract one dword from that and write and that will corrupt memory. - - That's why the code below allocates *two* alignments instead of one. - */ - void* mem_real = malloc(amount + 2 * alignment); - if(!mem_real) return NULL; - char* mem_align = (char*)((unsigned long)(2 * alignment - (unsigned long)mem_real % (unsigned long)alignment) + (unsigned long)mem_real); - *((long*)mem_align - 1) = (long)mem_real; - return mem_align; -} - -void FreeImage_Aligned_Free(void* mem) { - free((void*)*((long*)mem - 1)); -} - -#endif // _WIN32 || _WIN64 - -// ---------------------------------------------------------- -// FIBITMAP memory management -// ---------------------------------------------------------- - -/** -Calculate the size of a FreeImage image. -Align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary. -This function includes a protection against malicious images, based on a KISS integer overflow detection mechanism. - -@param header_only If TRUE, calculate a 'header only' FIBITMAP size, otherwise calculate a full FIBITMAP size -@param width Image width -@param height Image height -@param bpp Number of bits-per-pixel -@param need_masks We only store the masks (and allocate memory for them) for 16-bit images of type FIT_BITMAP -@return Returns a size in BYTE units -@see FreeImage_AllocateBitmap -*/ -static size_t -FreeImage_GetInternalImageSize(BOOL header_only, unsigned width, unsigned height, unsigned bpp, BOOL need_masks) { - size_t dib_size = sizeof(FREEIMAGEHEADER); - dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0); - dib_size += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT; - dib_size += sizeof(BITMAPINFOHEADER); - // palette is aligned on a 16 bytes boundary - dib_size += sizeof(RGBQUAD) * CalculateUsedPaletteEntries(bpp); - // we both add palette size and masks size if need_masks is true, since CalculateUsedPaletteEntries - // always returns 0 if need_masks is true (which is only true for 16 bit images). - dib_size += need_masks ? sizeof(DWORD) * 3 : 0; - dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0); - - if(!header_only) { - const size_t header_size = dib_size; - - // pixels are aligned on a 16 bytes boundary - dib_size += (size_t)CalculatePitch(CalculateLine(width, bpp)) * (size_t)height; - - // check for possible malloc overflow using a KISS integer overflow detection mechanism - { - const double dPitch = floor( ((double)bpp * width + 31.0) / 32.0 ) * 4.0; - const double dImageSize = (double)header_size + dPitch * height; - if(dImageSize != (double)dib_size) { - // here, we are sure to encounter a malloc overflow: try to avoid it ... - return 0; - } - - /* - The following constant take into account the additionnal memory used by - aligned malloc functions as well as debug malloc functions. - It is supposed here that using a (8 * FIBITMAP_ALIGNMENT) risk margin will be enough - for the target compiler. - */ - const double FIBITMAP_MAX_MEMORY = (double)((size_t)-1) - 8 * FIBITMAP_ALIGNMENT; - - if(dImageSize > FIBITMAP_MAX_MEMORY) { - // avoid possible overflow inside C allocation functions - return 0; - } - } - } - - return dib_size; -} - -/** -Helper for 16-bit FIT_BITMAP -Returns a pointer to the bitmap's red-, green- and blue masks. -@param dib The bitmap to obtain masks from. -@return Returns a pointer to the bitmap's red-, green- and blue masks -or NULL, if no masks are present (e.g. for 24 bit images). -*/ -static FREEIMAGERGBMASKS * -FreeImage_GetRGBMasks(FIBITMAP *dib) { - return FreeImage_HasRGBMasks(dib) ? (FREEIMAGERGBMASKS *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL; -} - -/** -Internal FIBITMAP allocation. - -This function accepts (ext_bits, ext_pitch) arguments. If these are provided the FIBITMAP -will be allocated as "header only", but bits and pitch will be stored within the FREEIMAGEHEADER -and the resulting FIBITMAP will have pixels, i.e. HasPixels() will return TRUE. -- GetBits() and GetPitch return the correct values - either offsets or the stored values (user-provided bits and pitch). -- Clone() creates a new FIBITMAP with copy of the user pixel data. -- Unload's implementation does not need to change - it just release a "header only" dib. -Note that when using external data, the data does not need to have the same alignment as the default 4-byte alignment. -This enables the possibility to access buffers with, for instance, stricter alignment, -like the ones used in low-level APIs like OpenCL or intrinsics. - -@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP -@param ext_bits Pointer to external user's pixel buffer if using wrapped buffer, NULL otherwise -@param ext_pitch Pointer to external user's pixel buffer pitch if using wrapped buffer, 0 otherwise -@param type Image type -@param width Image width -@param height Image height -@param bpp Number of bits per pixel -@param red_mask Image red mask -@param green_mask Image green mask -@param blue_mask Image blue mask -@return Returns the allocated FIBITMAP if successful, returns NULL otherwise -*/ -static FIBITMAP * -FreeImage_AllocateBitmap(BOOL header_only, BYTE *ext_bits, unsigned ext_pitch, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { - - // check input variables - width = abs(width); - height = abs(height); - if(!((width > 0) && (height > 0))) { - return NULL; - } - if(ext_bits) { - if(ext_pitch == 0) { - return NULL; - } - assert(header_only == FALSE); - } - - // we only store the masks (and allocate memory for them) for 16-bit images of type FIT_BITMAP - BOOL need_masks = FALSE; - - // check pixel bit depth - switch(type) { - case FIT_BITMAP: - switch(bpp) { - case 1: - case 4: - case 8: - break; - case 16: - need_masks = TRUE; - break; - case 24: - case 32: - break; - default: - bpp = 8; - break; - } - break; - case FIT_UINT16: - bpp = 8 * sizeof(unsigned short); - break; - case FIT_INT16: - bpp = 8 * sizeof(short); - break; - case FIT_UINT32: - bpp = 8 * sizeof(DWORD); - break; - case FIT_INT32: - bpp = 8 * sizeof(LONG); - break; - case FIT_FLOAT: - bpp = 8 * sizeof(float); - break; - case FIT_DOUBLE: - bpp = 8 * sizeof(double); - break; - case FIT_COMPLEX: - bpp = 8 * sizeof(FICOMPLEX); - break; - case FIT_RGB16: - bpp = 8 * sizeof(FIRGB16); - break; - case FIT_RGBA16: - bpp = 8 * sizeof(FIRGBA16); - break; - case FIT_RGBF: - bpp = 8 * sizeof(FIRGBF); - break; - case FIT_RGBAF: - bpp = 8 * sizeof(FIRGBAF); - break; - default: - return NULL; - } - - FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP)); - - if (bitmap != NULL) { - - // calculate the size of a FreeImage 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 - - // when using a user provided pixel buffer, force a 'header only' allocation - - size_t dib_size = FreeImage_GetInternalImageSize(header_only || ext_bits, width, height, bpp, need_masks); - - if(dib_size == 0) { - // memory allocation will fail (probably a malloc overflow) - free(bitmap); - return NULL; - } - - bitmap->data = (BYTE *)FreeImage_Aligned_Malloc(dib_size * sizeof(BYTE), FIBITMAP_ALIGNMENT); - - if (bitmap->data != NULL) { - memset(bitmap->data, 0, dib_size); - - // write out the FREEIMAGEHEADER - - FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)bitmap->data; - - fih->type = type; - - memset(&fih->bkgnd_color, 0, sizeof(RGBQUAD)); - - fih->transparent = FALSE; - fih->transparency_count = 0; - memset(fih->transparent_table, 0xff, 256); - - fih->has_pixels = header_only ? FALSE : TRUE; - - // initialize FIICCPROFILE link - - FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap); - iccProfile->size = 0; - iccProfile->data = 0; - iccProfile->flags = 0; - - // initialize metadata models list - - fih->metadata = new(std::nothrow) METADATAMAP; - - // initialize attached thumbnail - - fih->thumbnail = NULL; - - // store a pointer to user provided pixel buffer (if any) - - fih->external_bits = ext_bits; - fih->external_pitch = ext_pitch; - - // write out the BITMAPINFOHEADER - - BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(bitmap); - bih->biSize = sizeof(BITMAPINFOHEADER); - bih->biWidth = width; - bih->biHeight = height; - bih->biPlanes = 1; - bih->biCompression = need_masks ? BI_BITFIELDS : BI_RGB; - bih->biBitCount = (WORD)bpp; - bih->biClrUsed = CalculateUsedPaletteEntries(bpp); - bih->biClrImportant = bih->biClrUsed; - bih->biXPelsPerMeter = 2835; // 72 dpi - bih->biYPelsPerMeter = 2835; // 72 dpi - - if(bpp == 8) { - // build a default greyscale palette (very useful for image processing) - RGBQUAD *pal = FreeImage_GetPalette(bitmap); - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = (BYTE)i; - pal[i].rgbGreen = (BYTE)i; - pal[i].rgbBlue = (BYTE)i; - } - } - - // just setting the masks (only if needed) just like the palette. - if (need_masks) { - FREEIMAGERGBMASKS *masks = FreeImage_GetRGBMasks(bitmap); - masks->red_mask = red_mask; - masks->green_mask = green_mask; - masks->blue_mask = blue_mask; - } - - return bitmap; - } - - free(bitmap); - } - - return NULL; -} - -FIBITMAP * DLL_CALLCONV -FreeImage_AllocateHeaderForBits(BYTE *ext_bits, unsigned ext_pitch, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { - return FreeImage_AllocateBitmap(FALSE, ext_bits, ext_pitch, type, width, height, bpp, red_mask, green_mask, blue_mask); -} - -FIBITMAP * DLL_CALLCONV -FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { - return FreeImage_AllocateBitmap(header_only, NULL, 0, type, width, height, bpp, red_mask, green_mask, blue_mask); -} - -FIBITMAP * DLL_CALLCONV -FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { - return FreeImage_AllocateBitmap(header_only, NULL, 0, FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask); -} - -FIBITMAP * DLL_CALLCONV -FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { - return FreeImage_AllocateBitmap(FALSE, NULL, 0, FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask); -} - -FIBITMAP * DLL_CALLCONV -FreeImage_AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { - return FreeImage_AllocateBitmap(FALSE, NULL, 0, type, width, height, bpp, red_mask, green_mask, blue_mask); -} - -void DLL_CALLCONV -FreeImage_Unload(FIBITMAP *dib) { - if (NULL != dib) { - if (NULL != dib->data) { - // delete possible icc profile ... - if (FreeImage_GetICCProfile(dib)->data) { - free(FreeImage_GetICCProfile(dib)->data); - } - - // delete metadata models - METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; - - for(METADATAMAP::iterator i = (*metadata).begin(); i != (*metadata).end(); i++) { - TAGMAP *tagmap = (*i).second; - - if(tagmap) { - for(TAGMAP::iterator j = tagmap->begin(); j != tagmap->end(); j++) { - FITAG *tag = (*j).second; - FreeImage_DeleteTag(tag); - } - - delete tagmap; - } - } - - delete metadata; - - // delete embedded thumbnail - FreeImage_Unload(FreeImage_GetThumbnail(dib)); - - // delete bitmap ... - FreeImage_Aligned_Free(dib->data); - } - - free(dib); // ... and the wrapper - } -} - -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_Clone(FIBITMAP *dib) { - if(!dib) { - return NULL; - } - - FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); - unsigned width = FreeImage_GetWidth(dib); - unsigned height = FreeImage_GetHeight(dib); - unsigned bpp = FreeImage_GetBPP(dib); - - const BYTE *ext_bits = ((FREEIMAGEHEADER *)dib->data)->external_bits; - - // check for pixel availability ... - BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE; - - // check whether this image has masks defined ... - BOOL need_masks = (bpp == 16 && type == FIT_BITMAP) ? TRUE : FALSE; - - // allocate a new dib - FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, type, width, height, bpp, - FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib)); - - if (new_dib) { - // save ICC profile links - FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib); - FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib); - - // save metadata links - METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; - METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata; - - // calculate the size of the src 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 - - // when using a user provided pixel buffer, force a 'header only' calculation - - size_t dib_size = FreeImage_GetInternalImageSize(header_only || ext_bits, width, height, bpp, need_masks); - - // copy the bitmap + internal pointers (remember to restore new_dib internal pointers later) - memcpy(new_dib->data, dib->data, dib_size); - - // reset ICC profile link for new_dib - memset(dst_iccProfile, 0, sizeof(FIICCPROFILE)); - - // restore metadata link for new_dib - ((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata; - - // reset thumbnail link for new_dib - ((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL; - - // copy possible ICC profile - FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size); - dst_iccProfile->flags = src_iccProfile->flags; - - // copy metadata models - for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) { - int model = (*i).first; - TAGMAP *src_tagmap = (*i).second; - - if(src_tagmap) { - // create a metadata model - TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP(); - - if(dst_tagmap) { - // fill the model - for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) { - std::string dst_key = (*j).first; - FITAG *dst_tag = FreeImage_CloneTag( (*j).second ); - - // assign key and tag value - (*dst_tagmap)[dst_key] = dst_tag; - } - - // assign model and tagmap - (*dst_metadata)[model] = dst_tagmap; - } - } - } - - // copy the thumbnail - FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib)); - - // copy user provided pixel buffer (if any) - if(ext_bits) { - const unsigned pitch = FreeImage_GetPitch(dib); - const unsigned linesize = FreeImage_GetLine(dib); - for(unsigned y = 0; y < height; y++) { - memcpy(FreeImage_GetScanLine(new_dib, y), ext_bits, linesize); - ext_bits += pitch; - } - } - - return new_dib; - } - - return NULL; -} - -// ---------------------------------------------------------- - -BYTE * DLL_CALLCONV -FreeImage_GetBits(FIBITMAP *dib) { - if(!FreeImage_HasPixels(dib)) { - return NULL; - } - - if(((FREEIMAGEHEADER *)dib->data)->external_bits) { - return ((FREEIMAGEHEADER *)dib->data)->external_bits; - } - - // returns the pixels aligned on a FIBITMAP_ALIGNMENT bytes alignment boundary - size_t lp = (size_t)FreeImage_GetInfoHeader(dib); - lp += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * FreeImage_GetColorsUsed(dib); - lp += FreeImage_HasRGBMasks(dib) ? sizeof(DWORD) * 3 : 0; - lp += (lp % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - lp % FIBITMAP_ALIGNMENT : 0); - return (BYTE *)lp; -} - -// ---------------------------------------------------------- -// DIB information functions -// ---------------------------------------------------------- - -FIBITMAP* DLL_CALLCONV -FreeImage_GetThumbnail(FIBITMAP *dib) { - return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->thumbnail : NULL; -} - -BOOL DLL_CALLCONV -FreeImage_SetThumbnail(FIBITMAP *dib, FIBITMAP *thumbnail) { - if(dib == NULL) { - return FALSE; - } - FIBITMAP *currentThumbnail = ((FREEIMAGEHEADER *)dib->data)->thumbnail; - if(currentThumbnail == thumbnail) { - return TRUE; - } - FreeImage_Unload(currentThumbnail); - - ((FREEIMAGEHEADER *)dib->data)->thumbnail = FreeImage_HasPixels(thumbnail) ? FreeImage_Clone(thumbnail) : NULL; - - return TRUE; -} - -// ---------------------------------------------------------- - -FREE_IMAGE_COLOR_TYPE DLL_CALLCONV -FreeImage_GetColorType(FIBITMAP *dib) { - RGBQUAD *rgb; - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - // special bitmap type - if(image_type != FIT_BITMAP) { - switch(image_type) { - case FIT_UINT16: - { - // 16-bit greyscale TIF can be either FIC_MINISBLACK (the most common case) or FIC_MINISWHITE - // you can check this using EXIF_MAIN metadata - FITAG *photometricTag = NULL; - if(FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "PhotometricInterpretation", &photometricTag)) { - const short *value = (short*)FreeImage_GetTagValue(photometricTag); - // PHOTOMETRIC_MINISWHITE = 0 => min value is white - // PHOTOMETRIC_MINISBLACK = 1 => min value is black - return (*value == 0) ? FIC_MINISWHITE : FIC_MINISBLACK; - } - return FIC_MINISBLACK; - } - break; - case FIT_RGB16: - case FIT_RGBF: - return FIC_RGB; - case FIT_RGBA16: - case FIT_RGBAF: - return FIC_RGBALPHA; - } - - return FIC_MINISBLACK; - } - - // standard image type - switch (FreeImage_GetBPP(dib)) { - case 1: - { - rgb = FreeImage_GetPalette(dib); - - if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0)) { - rgb++; - - if ((rgb->rgbRed == 255) && (rgb->rgbGreen == 255) && (rgb->rgbBlue == 255)) { - return FIC_MINISBLACK; - } - } - - if ((rgb->rgbRed == 255) && (rgb->rgbGreen == 255) && (rgb->rgbBlue == 255)) { - rgb++; - - if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0)) { - return FIC_MINISWHITE; - } - } - - return FIC_PALETTE; - } - - case 4: - case 8: // Check if the DIB has a color or a greyscale palette - { - int ncolors = FreeImage_GetColorsUsed(dib); - int minisblack = 1; - rgb = FreeImage_GetPalette(dib); - - for (int i = 0; i < ncolors; i++) { - if ((rgb->rgbRed != rgb->rgbGreen) || (rgb->rgbRed != rgb->rgbBlue)) { - return FIC_PALETTE; - } - - // The DIB has a color palette if the greyscale isn't a linear ramp - // Take care of reversed grey images - if (rgb->rgbRed != i) { - if ((ncolors-i-1) != rgb->rgbRed) { - return FIC_PALETTE; - } else { - minisblack = 0; - } - } - - rgb++; - } - - return minisblack ? FIC_MINISBLACK : FIC_MINISWHITE; - } - - case 16: - case 24: - return FIC_RGB; - - case 32: - { - if (FreeImage_GetICCProfile(dib)->flags & FIICC_COLOR_IS_CMYK) { - return FIC_CMYK; - } - - if( FreeImage_HasPixels(dib) ) { - // check for fully opaque alpha layer - for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - rgb = (RGBQUAD *)FreeImage_GetScanLine(dib, y); - - for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { - if (rgb[x].rgbReserved != 0xFF) { - return FIC_RGBALPHA; - } - } - } - return FIC_RGB; - } - - return FIC_RGBALPHA; - } - - default : - return FIC_MINISBLACK; - } -} - -// ---------------------------------------------------------- - -FREE_IMAGE_TYPE DLL_CALLCONV -FreeImage_GetImageType(FIBITMAP *dib) { - return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->type : FIT_UNKNOWN; -} - -// ---------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_HasPixels(FIBITMAP *dib) { - return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->has_pixels : FALSE; -} - -// ---------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_HasRGBMasks(FIBITMAP *dib) { - return dib && FreeImage_GetInfoHeader(dib)->biCompression == BI_BITFIELDS; -} - -unsigned DLL_CALLCONV -FreeImage_GetRedMask(FIBITMAP *dib) { - FREEIMAGERGBMASKS *masks = NULL; - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - switch(image_type) { - case FIT_BITMAP: - // check for 16-bit RGB (565 or 555) - masks = FreeImage_GetRGBMasks(dib); - if (masks) { - return masks->red_mask; - } - return FreeImage_GetBPP(dib) >= 24 ? FI_RGBA_RED_MASK : 0; - default: - return 0; - } -} - -unsigned DLL_CALLCONV -FreeImage_GetGreenMask(FIBITMAP *dib) { - FREEIMAGERGBMASKS *masks = NULL; - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - switch(image_type) { - case FIT_BITMAP: - // check for 16-bit RGB (565 or 555) - masks = FreeImage_GetRGBMasks(dib); - if (masks) { - return masks->green_mask; - } - return FreeImage_GetBPP(dib) >= 24 ? FI_RGBA_GREEN_MASK : 0; - default: - return 0; - } -} - -unsigned DLL_CALLCONV -FreeImage_GetBlueMask(FIBITMAP *dib) { - FREEIMAGERGBMASKS *masks = NULL; - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - switch(image_type) { - case FIT_BITMAP: - // check for 16-bit RGB (565 or 555) - masks = FreeImage_GetRGBMasks(dib); - if (masks) { - return masks->blue_mask; - } - return FreeImage_GetBPP(dib) >= 24 ? FI_RGBA_BLUE_MASK : 0; - default: - return 0; - } -} - -// ---------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_HasBackgroundColor(FIBITMAP *dib) { - if(dib) { - RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color; - return (bkgnd_color->rgbReserved != 0) ? TRUE : FALSE; - } - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_GetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor) { - if(dib && bkcolor) { - if(FreeImage_HasBackgroundColor(dib)) { - // get the background color - RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color; - memcpy(bkcolor, bkgnd_color, sizeof(RGBQUAD)); - // get the background index - if(FreeImage_GetBPP(dib) == 8) { - RGBQUAD *pal = FreeImage_GetPalette(dib); - for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) { - if(bkgnd_color->rgbRed == pal[i].rgbRed) { - if(bkgnd_color->rgbGreen == pal[i].rgbGreen) { - if(bkgnd_color->rgbBlue == pal[i].rgbBlue) { - bkcolor->rgbReserved = (BYTE)i; - return TRUE; - } - } - } - } - } - - bkcolor->rgbReserved = 0; - - return TRUE; - } - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_SetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor) { - if(dib) { - RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color; - if(bkcolor) { - // set the background color - memcpy(bkgnd_color, bkcolor, sizeof(RGBQUAD)); - // enable the file background color - bkgnd_color->rgbReserved = 1; - } else { - // clear and disable the file background color - memset(bkgnd_color, 0, sizeof(RGBQUAD)); - } - return TRUE; - } - - return FALSE; -} - -// ---------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_IsTransparent(FIBITMAP *dib) { - if(dib) { - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - switch(image_type) { - case FIT_BITMAP: - if(FreeImage_GetBPP(dib) == 32) { - if(FreeImage_GetColorType(dib) == FIC_RGBALPHA) { - return TRUE; - } - } else { - return ((FREEIMAGEHEADER *)dib->data)->transparent ? TRUE : FALSE; - } - break; - case FIT_RGBA16: - case FIT_RGBAF: - return TRUE; - default: - break; - } - } - return FALSE; -} - -BYTE * DLL_CALLCONV -FreeImage_GetTransparencyTable(FIBITMAP *dib) { - return dib ? ((FREEIMAGEHEADER *)dib->data)->transparent_table : NULL; -} - -void DLL_CALLCONV -FreeImage_SetTransparent(FIBITMAP *dib, BOOL enabled) { - if (dib) { - if ((FreeImage_GetBPP(dib) <= 8) || (FreeImage_GetBPP(dib) == 32)) { - ((FREEIMAGEHEADER *)dib->data)->transparent = enabled; - } else { - ((FREEIMAGEHEADER *)dib->data)->transparent = FALSE; - } - } -} - -unsigned DLL_CALLCONV -FreeImage_GetTransparencyCount(FIBITMAP *dib) { - return dib ? ((FREEIMAGEHEADER *)dib->data)->transparency_count : 0; -} - -void DLL_CALLCONV -FreeImage_SetTransparencyTable(FIBITMAP *dib, BYTE *table, int count) { - if (dib) { - count = MAX(0, MIN(count, 256)); - if (FreeImage_GetBPP(dib) <= 8) { - ((FREEIMAGEHEADER *)dib->data)->transparent = (count > 0) ? TRUE : FALSE; - ((FREEIMAGEHEADER *)dib->data)->transparency_count = count; - - if (table) { - memcpy(((FREEIMAGEHEADER *)dib->data)->transparent_table, table, count); - } else { - memset(((FREEIMAGEHEADER *)dib->data)->transparent_table, 0xff, count); - } - } - } -} - -/** @brief Sets the index of the palette entry to be used as transparent color - for the image specified. Does nothing on high color images. - - This method sets the index of the palette entry to be used as single transparent - color for the image specified. This works on palletised images only and does - nothing for high color images. - - Although it is possible for palletised images to have more than one transparent - color, this method sets the palette entry specified as the single transparent - color for the image. All other colors will be set to be non-transparent by this - method. - - As with FreeImage_SetTransparencyTable(), this method also sets the image's - transparency property to TRUE (as it is set and obtained by - FreeImage_SetTransparent() and FreeImage_IsTransparent() respectively) for - palletised images. - - @param dib Input image, whose transparent color is to be set. - @param index The index of the palette entry to be set as transparent color. - */ -void DLL_CALLCONV -FreeImage_SetTransparentIndex(FIBITMAP *dib, int index) { - if (dib) { - int count = FreeImage_GetColorsUsed(dib); - if (count) { - BYTE *new_tt = (BYTE *)malloc(count * sizeof(BYTE)); - memset(new_tt, 0xFF, count); - if ((index >= 0) && (index < count)) { - new_tt[index] = 0x00; - } - FreeImage_SetTransparencyTable(dib, new_tt, count); - free(new_tt); - } - } -} - -/** @brief Returns the palette entry used as transparent color for the image - specified. Works for palletised images only and returns -1 for high color - images or if the image has no color set to be transparent. - - Although it is possible for palletised images to have more than one transparent - color, this function always returns the index of the first palette entry, set - to be transparent. - - @param dib Input image, whose transparent color is to be returned. - @return Returns the index of the palette entry used as transparent color for - the image specified or -1 if there is no transparent color found (e.g. the image - is a high color image). - */ -int DLL_CALLCONV -FreeImage_GetTransparentIndex(FIBITMAP *dib) { - int count = FreeImage_GetTransparencyCount(dib); - BYTE *tt = FreeImage_GetTransparencyTable(dib); - for (int i = 0; i < count; i++) { - if (tt[i] == 0) { - return i; - } - } - return -1; -} - -// ---------------------------------------------------------- - -FIICCPROFILE * DLL_CALLCONV -FreeImage_GetICCProfile(FIBITMAP *dib) { - FIICCPROFILE *profile = (dib) ? (FIICCPROFILE *)&((FREEIMAGEHEADER *)dib->data)->iccProfile : NULL; - return profile; -} - -FIICCPROFILE * DLL_CALLCONV -FreeImage_CreateICCProfile(FIBITMAP *dib, void *data, long size) { - // clear the profile but preserve profile->flags - FreeImage_DestroyICCProfile(dib); - // create the new profile - FIICCPROFILE *profile = FreeImage_GetICCProfile(dib); - if(size && profile) { - profile->data = malloc(size); - if(profile->data) { - memcpy(profile->data, data, profile->size = size); - } - } - return profile; -} - -void DLL_CALLCONV -FreeImage_DestroyICCProfile(FIBITMAP *dib) { - FIICCPROFILE *profile = FreeImage_GetICCProfile(dib); - if(profile) { - if (profile->data) { - free (profile->data); - } - // clear the profile but preserve profile->flags - profile->data = NULL; - profile->size = 0; - } -} - -// ---------------------------------------------------------- - -unsigned DLL_CALLCONV -FreeImage_GetWidth(FIBITMAP *dib) { - return dib ? FreeImage_GetInfoHeader(dib)->biWidth : 0; -} - -unsigned DLL_CALLCONV -FreeImage_GetHeight(FIBITMAP *dib) { - return (dib) ? FreeImage_GetInfoHeader(dib)->biHeight : 0; -} - -unsigned DLL_CALLCONV -FreeImage_GetBPP(FIBITMAP *dib) { - return dib ? FreeImage_GetInfoHeader(dib)->biBitCount : 0; -} - -unsigned DLL_CALLCONV -FreeImage_GetLine(FIBITMAP *dib) { - return dib ? ((FreeImage_GetWidth(dib) * FreeImage_GetBPP(dib)) + 7) / 8 : 0; -} - -unsigned DLL_CALLCONV -FreeImage_GetPitch(FIBITMAP *dib) { - if(dib) { - FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)dib->data; - return fih->external_bits ? fih->external_pitch : (FreeImage_GetLine(dib) + 3 & ~3); - } - return 0; -} - -unsigned DLL_CALLCONV -FreeImage_GetColorsUsed(FIBITMAP *dib) { - return dib ? FreeImage_GetInfoHeader(dib)->biClrUsed : 0; -} - -unsigned DLL_CALLCONV -FreeImage_GetDIBSize(FIBITMAP *dib) { - return (dib) ? sizeof(BITMAPINFOHEADER) + (FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD)) + (FreeImage_GetPitch(dib) * FreeImage_GetHeight(dib)) : 0; -} - -RGBQUAD * DLL_CALLCONV -FreeImage_GetPalette(FIBITMAP *dib) { - return (dib && FreeImage_GetBPP(dib) < 16) ? (RGBQUAD *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL; -} - -unsigned DLL_CALLCONV -FreeImage_GetDotsPerMeterX(FIBITMAP *dib) { - return (dib) ? FreeImage_GetInfoHeader(dib)->biXPelsPerMeter : 0; -} - -unsigned DLL_CALLCONV -FreeImage_GetDotsPerMeterY(FIBITMAP *dib) { - return (dib) ? FreeImage_GetInfoHeader(dib)->biYPelsPerMeter : 0; -} - -void DLL_CALLCONV -FreeImage_SetDotsPerMeterX(FIBITMAP *dib, unsigned res) { - if(dib) { - FreeImage_GetInfoHeader(dib)->biXPelsPerMeter = res; - } -} - -void DLL_CALLCONV -FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res) { - if(dib) { - FreeImage_GetInfoHeader(dib)->biYPelsPerMeter = res; - } -} - -BITMAPINFOHEADER * DLL_CALLCONV -FreeImage_GetInfoHeader(FIBITMAP *dib) { - if(!dib) { - return NULL; - } - size_t lp = (size_t)dib->data + sizeof(FREEIMAGEHEADER); - lp += (lp % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - lp % FIBITMAP_ALIGNMENT : 0); - lp += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT; - return (BITMAPINFOHEADER *)lp; -} - -BITMAPINFO * DLL_CALLCONV -FreeImage_GetInfo(FIBITMAP *dib) { - return (BITMAPINFO *)FreeImage_GetInfoHeader(dib); -} - -// ---------------------------------------------------------- -// Metadata routines -// ---------------------------------------------------------- - -FIMETADATA * DLL_CALLCONV -FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag) { - if(!dib) { - return NULL; - } - - // get the metadata model - METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; - TAGMAP *tagmap = NULL; - if( (*metadata).find(model) != (*metadata).end() ) { - tagmap = (*metadata)[model]; - } - if(tagmap) { - // allocate a handle - FIMETADATA *handle = (FIMETADATA *)malloc(sizeof(FIMETADATA)); - if(handle) { - // calculate the size of a METADATAHEADER - int header_size = sizeof(METADATAHEADER); - - handle->data = (BYTE *)malloc(header_size * sizeof(BYTE)); - - if(handle->data) { - memset(handle->data, 0, header_size * sizeof(BYTE)); - - // write out the METADATAHEADER - METADATAHEADER *mdh = (METADATAHEADER *)handle->data; - - mdh->pos = 1; - mdh->tagmap = tagmap; - - // get the first element - TAGMAP::iterator i = tagmap->begin(); - *tag = (*i).second; - - return handle; - } - - free(handle); - } - } - - return NULL; -} - -BOOL DLL_CALLCONV -FreeImage_FindNextMetadata(FIMETADATA *mdhandle, FITAG **tag) { - if(!mdhandle) { - return FALSE; - } - - METADATAHEADER *mdh = (METADATAHEADER *)mdhandle->data; - TAGMAP *tagmap = mdh->tagmap; - - int current_pos = mdh->pos; - int mapsize = (int)tagmap->size(); - - if(current_pos < mapsize) { - // get the tag element at position pos - int count = 0; - - for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) { - if(count == current_pos) { - *tag = (*i).second; - mdh->pos++; - break; - } - count++; - } - - return TRUE; - } - - return FALSE; -} - -void DLL_CALLCONV -FreeImage_FindCloseMetadata(FIMETADATA *mdhandle) { - if (NULL != mdhandle) { // delete the handle - if (NULL != mdhandle->data) { - free(mdhandle->data); - } - free(mdhandle); // ... and the wrapper - } -} - - -// ---------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_CloneMetadata(FIBITMAP *dst, FIBITMAP *src) { - if(!src || !dst) { - return FALSE; - } - - // get metadata links - METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)src->data)->metadata; - METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)dst->data)->metadata; - - // copy metadata models, *except* the FIMD_ANIMATION model - for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) { - int model = (*i).first; - if(model == (int)FIMD_ANIMATION) { - continue; - } - TAGMAP *src_tagmap = (*i).second; - - if(src_tagmap) { - if( dst_metadata->find(model) != dst_metadata->end() ) { - // destroy dst model - FreeImage_SetMetadata((FREE_IMAGE_MDMODEL)model, dst, NULL, NULL); - } - - // create a metadata model - TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP(); - - if(dst_tagmap) { - // fill the model - for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) { - std::string dst_key = (*j).first; - FITAG *dst_tag = FreeImage_CloneTag( (*j).second ); - - // assign key and tag value - (*dst_tagmap)[dst_key] = dst_tag; - } - - // assign model and tagmap - (*dst_metadata)[model] = dst_tagmap; - } - } - } - - // clone resolution - FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src)); - FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src)); - - return TRUE; -} - -// ---------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag) { - if(!dib) { - return FALSE; - } - - TAGMAP *tagmap = NULL; - - // get the metadata model - METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; - METADATAMAP::iterator model_iterator = metadata->find(model); - if (model_iterator != metadata->end()) { - tagmap = model_iterator->second; - } - - if(key != NULL) { - - if(!tagmap) { - // this model, doesn't exist: create it - tagmap = new(std::nothrow) TAGMAP(); - (*metadata)[model] = tagmap; - } - - if(tag) { - // first check the tag - if(FreeImage_GetTagKey(tag) == NULL) { - FreeImage_SetTagKey(tag, key); - } else if(strcmp(key, FreeImage_GetTagKey(tag)) != 0) { - // set the tag key - FreeImage_SetTagKey(tag, key); - } - if(FreeImage_GetTagCount(tag) * FreeImage_TagDataWidth(FreeImage_GetTagType(tag)) != FreeImage_GetTagLength(tag)) { - FreeImage_OutputMessageProc(FIF_UNKNOWN, "Invalid data count for tag '%s'", key); - return FALSE; - } - - // fill the tag ID if possible and if it's needed - TagLib& tag_lib = TagLib::instance(); - switch(model) { - case FIMD_IPTC: - { - int id = tag_lib.getTagID(TagLib::IPTC, key); - /* - if(id == -1) { - FreeImage_OutputMessageProc(FIF_UNKNOWN, "IPTC: Invalid key '%s'", key); - } - */ - FreeImage_SetTagID(tag, (WORD)id); - } - break; - - default: - break; - } - - // delete existing tag - FITAG *old_tag = (*tagmap)[key]; - if(old_tag) { - FreeImage_DeleteTag(old_tag); - } - - // create a new tag - (*tagmap)[key] = FreeImage_CloneTag(tag); - } - else { - // delete existing tag - TAGMAP::iterator i = tagmap->find(key); - if(i != tagmap->end()) { - FITAG *old_tag = (*i).second; - FreeImage_DeleteTag(old_tag); - tagmap->erase(key); - } - } - } - else { - // destroy the metadata model - if(tagmap) { - for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) { - FITAG *tag = (*i).second; - FreeImage_DeleteTag(tag); - } - - delete tagmap; - metadata->erase(model_iterator); - } - } - - return TRUE; -} - -BOOL DLL_CALLCONV -FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG **tag) { - if(!dib || !key || !tag) { - return FALSE; - } - - TAGMAP *tagmap = NULL; - *tag = NULL; - - // get the metadata model - METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; - if(!(*metadata).empty()) { - METADATAMAP::iterator model_iterator = metadata->find(model); - if (model_iterator != metadata->end() ) { - // this model exists : try to get the requested tag - tagmap = model_iterator->second; - TAGMAP::iterator tag_iterator = tagmap->find(key); - if (tag_iterator != tagmap->end() ) { - // get the requested tag - *tag = tag_iterator->second; - } - } - } - - return (*tag != NULL) ? TRUE : FALSE; -} - -/** -Build and set a FITAG whose type is FIDT_ASCII. -@param model Metadata model to be filled -@param dib Image to be filled -@param key Tag key -@param value Tag value as a ASCII string -@return Returns TRUE if successful, returns FALSE otherwise -*/ -BOOL DLL_CALLCONV -FreeImage_SetMetadataKeyValue(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, const char *value) { - if(!dib || !key || !value) { - return FALSE; - } - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - BOOL bSuccess = TRUE; - // fill the tag - DWORD tag_length = (DWORD)(strlen(value) + 1); - bSuccess &= FreeImage_SetTagKey(tag, key); - bSuccess &= FreeImage_SetTagLength(tag, tag_length); - bSuccess &= FreeImage_SetTagCount(tag, tag_length); - bSuccess &= FreeImage_SetTagType(tag, FIDT_ASCII); - bSuccess &= FreeImage_SetTagValue(tag, value); - if(bSuccess) { - // set the tag - bSuccess &= FreeImage_SetMetadata(model, dib, FreeImage_GetTagKey(tag), tag); - } - // delete the tag - FreeImage_DeleteTag(tag); - - return bSuccess; - } - - return FALSE; -} - -// ---------------------------------------------------------- - -unsigned DLL_CALLCONV -FreeImage_GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP *dib) { - if(!dib) { - return FALSE; - } - - TAGMAP *tagmap = NULL; - - // get the metadata model - METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; - if( (*metadata).find(model) != (*metadata).end() ) { - tagmap = (*metadata)[model]; - } - if(!tagmap) { - // this model, doesn't exist: return - return 0; - } - - // get the tag count - return (unsigned)tagmap->size(); -} - -// ---------------------------------------------------------- - -unsigned DLL_CALLCONV -FreeImage_GetMemorySize(FIBITMAP *dib) { - if (!dib) { - return 0; - } - FREEIMAGEHEADER *header = (FREEIMAGEHEADER *)dib->data; - BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(dib); - - BOOL header_only = !header->has_pixels || header->external_bits != NULL; - BOOL need_masks = bih->biCompression == BI_BITFIELDS; - unsigned width = bih->biWidth; - unsigned height = bih->biHeight; - unsigned bpp = bih->biBitCount; - - // start off with the size of the FIBITMAP structure - size_t size = sizeof(FIBITMAP); - - // add sizes of FREEIMAGEHEADER, BITMAPINFOHEADER, palette and DIB data - size += FreeImage_GetInternalImageSize(header_only, width, height, bpp, need_masks); - - // add ICC profile size - size += header->iccProfile.size; - - // add thumbnail image size - if (header->thumbnail) { - // we assume a thumbnail not having a thumbnail as well, - // so this recursive call should not create an infinite loop - size += FreeImage_GetMemorySize(header->thumbnail); - } - - // add metadata size - METADATAMAP *md = header->metadata; - if (!md) { - return (unsigned)size; - } - - // add size of METADATAMAP - size += sizeof(METADATAMAP); - - const size_t models = md->size(); - if (models == 0) { - return (unsigned)size; - } - - unsigned tags = 0; - - for (METADATAMAP::iterator i = md->begin(); i != md->end(); i++) { - TAGMAP *tm = i->second; - if (tm) { - for (TAGMAP::iterator j = tm->begin(); j != tm->end(); j++) { - ++tags; - const std::string & key = j->first; - size += key.capacity(); - size += FreeImage_GetTagMemorySize(j->second); - } - } - } - - // add size of all TAGMAP instances - size += models * sizeof(TAGMAP); - // add size of tree nodes in METADATAMAP - size += MapIntrospector<METADATAMAP>::GetNodesMemorySize(models); - // add size of tree nodes in TAGMAP - size += MapIntrospector<TAGMAP>::GetNodesMemorySize(tags); - - return (unsigned)size; -} - diff --git a/plugins/AdvaImg/src/FreeImage/CacheFile.cpp b/plugins/AdvaImg/src/FreeImage/CacheFile.cpp deleted file mode 100644 index 309faf8faf..0000000000 --- a/plugins/AdvaImg/src/FreeImage/CacheFile.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// ========================================================== -// Multi-Page functions -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - checkered (checkered@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#include "CacheFile.h" - -// ---------------------------------------------------------- - -CacheFile::CacheFile(const std::string filename, BOOL keep_in_memory) : -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) { -} - -CacheFile::~CacheFile() { -} - -BOOL -CacheFile::open() { - if ((!m_filename.empty()) && (!m_keep_in_memory)) { - m_file = fopen(m_filename.c_str(), "w+b"); - return (m_file != NULL); - } - - return (m_keep_in_memory == TRUE); -} - -void -CacheFile::close() { - // dispose the cache entries - - while (!m_page_cache_disk.empty()) { - Block *block = *m_page_cache_disk.begin(); - m_page_cache_disk.pop_front(); - delete [] block->data; - delete block; - } - while (!m_page_cache_mem.empty()) { - Block *block = *m_page_cache_mem.begin(); - m_page_cache_mem.pop_front(); - delete [] block->data; - delete block; - } - - if (m_file) { - // close the file - - fclose(m_file); - - // delete the file - - remove(m_filename.c_str()); - } -} - -void -CacheFile::cleanupMemCache() { - if (!m_keep_in_memory) { - if (m_page_cache_mem.size() > CACHE_SIZE) { - // flush the least used block to file - - Block *old_block = m_page_cache_mem.back(); - fseek(m_file, old_block->nr * BLOCK_SIZE, SEEK_SET); - fwrite(old_block->data, BLOCK_SIZE, 1, m_file); - - // remove the data - - delete [] old_block->data; - old_block->data = NULL; - - // move the block to another list - - m_page_cache_disk.splice(m_page_cache_disk.begin(), m_page_cache_mem, --m_page_cache_mem.end()); - m_page_map[old_block->nr] = m_page_cache_disk.begin(); - } - } -} - -int -CacheFile::allocateBlock() { - Block *block = new Block; - block->data = new BYTE[BLOCK_SIZE]; - block->next = 0; - - if (!m_free_pages.empty()) { - block->nr = *m_free_pages.begin(); - m_free_pages.pop_front(); - } else { - block->nr = m_page_count++; - } - - m_page_cache_mem.push_front(block); - m_page_map[block->nr] = m_page_cache_mem.begin(); - - cleanupMemCache(); - - return block->nr; -} - -Block * -CacheFile::lockBlock(int nr) { - if (m_current_block == NULL) { - PageMapIt it = m_page_map.find(nr); - - if (it != m_page_map.end()) { - m_current_block = *(it->second); - - // the block is swapped out to disc. load it back - // and remove the block from the cache. it might get cached - // again as soon as the memory buffer fills up - - if (m_current_block->data == NULL) { - m_current_block->data = new BYTE[BLOCK_SIZE]; - - fseek(m_file, m_current_block->nr * BLOCK_SIZE, SEEK_SET); - fread(m_current_block->data, BLOCK_SIZE, 1, m_file); - - m_page_cache_mem.splice(m_page_cache_mem.begin(), m_page_cache_disk, it->second); - m_page_map[nr] = m_page_cache_mem.begin(); - } - - // if the memory cache size is too large, swap an item to disc - - cleanupMemCache(); - - // return the current block - - return m_current_block; - } - } - - return NULL; -} - -BOOL -CacheFile::unlockBlock(int nr) { - if (m_current_block) { - m_current_block = NULL; - - return TRUE; - } - - return FALSE; -} - -BOOL -CacheFile::deleteBlock(int nr) { - if (!m_current_block) { - PageMapIt it = m_page_map.find(nr); - - // remove block from cache - - if (it != m_page_map.end()) - m_page_map.erase(nr); - - // add block to free page list - - m_free_pages.push_back(nr); - - return TRUE; - } - - return FALSE; -} - -BOOL -CacheFile::readFile(BYTE *data, int nr, int size) { - if ((data) && (size > 0)) { - int s = 0; - int block_nr = nr; - - do { - int copy_nr = block_nr; - - Block *block = lockBlock(copy_nr); - - block_nr = block->next; - - memcpy(data + s, block->data, (s + BLOCK_SIZE > size) ? size - s : BLOCK_SIZE); - - unlockBlock(copy_nr); - - s += BLOCK_SIZE; - } while (block_nr != 0); - - return TRUE; - } - - return FALSE; -} - -int -CacheFile::writeFile(BYTE *data, int size) { - if ((data) && (size > 0)) { - int nr_blocks_required = 1 + (size / BLOCK_SIZE); - int count = 0; - int s = 0; - int stored_alloc; - int alloc; - - stored_alloc = alloc = allocateBlock(); - - do { - int copy_alloc = alloc; - - Block *block = lockBlock(copy_alloc); - - block->next = 0; - - memcpy(block->data, data + s, (s + BLOCK_SIZE > size) ? size - s : BLOCK_SIZE); - - if (count + 1 < nr_blocks_required) - alloc = block->next = allocateBlock(); - - unlockBlock(copy_alloc); - - s += BLOCK_SIZE; - } while (++count < nr_blocks_required); - - return stored_alloc; - } - - return 0; -} - -void -CacheFile::deleteFile(int nr) { - do { - Block *block = lockBlock(nr); - - if (block == NULL) - break; - - int next = block->next; - - unlockBlock(nr); - - deleteBlock(nr); - - nr = next; - } while (nr != 0); -} - diff --git a/plugins/AdvaImg/src/FreeImage/ColorLookup.cpp b/plugins/AdvaImg/src/FreeImage/ColorLookup.cpp deleted file mode 100644 index 0f4435a725..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ColorLookup.cpp +++ /dev/null @@ -1,785 +0,0 @@ -// ========================================================== -// X11 and SVG Color name lookup -// -// Design and implementation by -// - Karl-Heinz Bussian (khbussian@moss.de) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// RGB color names --------------------------------------------------------- - -typedef struct tagNamedColor { - const char *name; //! color name - BYTE r; //! red value - BYTE g; //! green value - BYTE b; //! blue value -} NamedColor; - -// -------------------------------------------------------------------------- - -/** -Helper function : perform a binary search on a color array -@param name Color name -@param color_array Color array -@param n Length of the color array -@return Returns the color index in the array if successful, returns -1 otherwise -*/ -static int -binsearch(const char *name, const NamedColor *color_array, int n) { - int cond, low, mid, high; - - low = 0; - high = n - 1; - while (low <= high) { - mid = (low + high) / 2; - if ((cond = strcmp(name, color_array[mid].name)) < 0) { - high = mid - 1; - } else if (cond > 0) { - low = mid + 1; - } else { - return mid; - } - } - return -1; -} - -/** -Perform a binary search on a color array -@param szColor Color name -@param color_array Color array -@param ncolors Length of the color array -@return Returns the color index in the array if successful, returns -1 otherwise -*/ -static int -FreeImage_LookupNamedColor(const char *szColor, const NamedColor *color_array, int ncolors) { - int i; - char color[64]; - - // make lower case name, squezze white space - - for (i = 0; szColor[i] && i < sizeof(color) - 1; i++) { - if (isspace(szColor[i])) { - continue; - } - if (isupper(szColor[i])) { - color[i] = (char)tolower(szColor[i]); - } else { - color[i] = szColor[i]; - } - } - color[i] = 0; - - return binsearch(color, color_array, ncolors); -} - -// ========================================================== -// X11 Color name lookup - -/** - This big list of color names was formed from the file: /usr/X11R6/lib/X11/rgb.txt - found on a standard Linux installation. -*/ - -static NamedColor X11ColorMap[] = { - { "aliceblue", 240, 248, 255 }, - { "antiquewhite", 250, 235, 215 }, - { "antiquewhite1", 255, 239, 219 }, - { "antiquewhite2", 238, 223, 204 }, - { "antiquewhite3", 205, 192, 176 }, - { "antiquewhite4", 139, 131, 120 }, - { "aquamarine", 127, 255, 212 }, - { "aquamarine1", 127, 255, 212 }, - { "aquamarine2", 118, 238, 198 }, - { "aquamarine3", 102, 205, 170 }, - { "aquamarine4", 69, 139, 116 }, - { "azure", 240, 255, 255 }, - { "azure1", 240, 255, 255 }, - { "azure2", 224, 238, 238 }, - { "azure3", 193, 205, 205 }, - { "azure4", 131, 139, 139 }, - { "beige", 245, 245, 220 }, - { "bisque", 255, 228, 196 }, - { "bisque1", 255, 228, 196 }, - { "bisque2", 238, 213, 183 }, - { "bisque3", 205, 183, 158 }, - { "bisque4", 139, 125, 107 }, - { "black", 0, 0, 0 }, - { "blanchedalmond", 255, 235, 205 }, - { "blue", 0, 0, 255 }, - { "blue1", 0, 0, 255 }, - { "blue2", 0, 0, 238 }, - { "blue3", 0, 0, 205 }, - { "blue4", 0, 0, 139 }, - { "blueviolet", 138, 43, 226 }, - { "brown", 165, 42, 42 }, - { "brown1", 255, 64, 64 }, - { "brown2", 238, 59, 59 }, - { "brown3", 205, 51, 51 }, - { "brown4", 139, 35, 35 }, - { "burlywood", 222, 184, 135 }, - { "burlywood1", 255, 211, 155 }, - { "burlywood2", 238, 197, 145 }, - { "burlywood3", 205, 170, 125 }, - { "burlywood4", 139, 115, 85 }, - { "cadetblue", 95, 158, 160 }, - { "cadetblue1", 152, 245, 255 }, - { "cadetblue2", 142, 229, 238 }, - { "cadetblue3", 122, 197, 205 }, - { "cadetblue4", 83, 134, 139 }, - { "chartreuse", 127, 255, 0 }, - { "chartreuse1", 127, 255, 0 }, - { "chartreuse2", 118, 238, 0 }, - { "chartreuse3", 102, 205, 0 }, - { "chartreuse4", 69, 139, 0 }, - { "chocolate", 210, 105, 30 }, - { "chocolate1", 255, 127, 36 }, - { "chocolate2", 238, 118, 33 }, - { "chocolate3", 205, 102, 29 }, - { "chocolate4", 139, 69, 19 }, - { "coral", 255, 127, 80 }, - { "coral1", 255, 114, 86 }, - { "coral2", 238, 106, 80 }, - { "coral3", 205, 91, 69 }, - { "coral4", 139, 62, 47 }, - { "cornflowerblue", 100, 149, 237 }, - { "cornsilk", 255, 248, 220 }, - { "cornsilk1", 255, 248, 220 }, - { "cornsilk2", 238, 232, 205 }, - { "cornsilk3", 205, 200, 177 }, - { "cornsilk4", 139, 136, 120 }, - { "cyan", 0, 255, 255 }, - { "cyan1", 0, 255, 255 }, - { "cyan2", 0, 238, 238 }, - { "cyan3", 0, 205, 205 }, - { "cyan4", 0, 139, 139 }, - { "darkblue", 0, 0, 139 }, - { "darkcyan", 0, 139, 139 }, - { "darkgoldenrod", 184, 134, 11 }, - { "darkgoldenrod1", 255, 185, 15 }, - { "darkgoldenrod2", 238, 173, 14 }, - { "darkgoldenrod3", 205, 149, 12 }, - { "darkgoldenrod4", 139, 101, 8 }, - { "darkgreen", 0, 100, 0 }, - { "darkkhaki", 189, 183, 107 }, - { "darkmagenta", 139, 0, 139 }, - { "darkolivegreen", 85, 107, 47 }, - { "darkolivegreen1", 202, 255, 112 }, - { "darkolivegreen2", 188, 238, 104 }, - { "darkolivegreen3", 162, 205, 90 }, - { "darkolivegreen4", 110, 139, 61 }, - { "darkorange", 255, 140, 0 }, - { "darkorange1", 255, 127, 0 }, - { "darkorange2", 238, 118, 0 }, - { "darkorange3", 205, 102, 0 }, - { "darkorange4", 139, 69, 0 }, - { "darkorchid", 153, 50, 204 }, - { "darkorchid1", 191, 62, 255 }, - { "darkorchid2", 178, 58, 238 }, - { "darkorchid3", 154, 50, 205 }, - { "darkorchid4", 104, 34, 139 }, - { "darkred", 139, 0, 0 }, - { "darksalmon", 233, 150, 122 }, - { "darkseagreen", 143, 188, 143 }, - { "darkseagreen1", 193, 255, 193 }, - { "darkseagreen2", 180, 238, 180 }, - { "darkseagreen3", 155, 205, 155 }, - { "darkseagreen4", 105, 139, 105 }, - { "darkslateblue", 72, 61, 139 }, - { "darkslategray", 47, 79, 79 }, - { "darkslategray1", 151, 255, 255 }, - { "darkslategray2", 141, 238, 238 }, - { "darkslategray3", 121, 205, 205 }, - { "darkslategray4", 82, 139, 139 }, - { "darkslategrey", 47, 79, 79 }, - { "darkturquoise", 0, 206, 209 }, - { "darkviolet", 148, 0, 211 }, - { "deeppink", 255, 20, 147 }, - { "deeppink1", 255, 20, 147 }, - { "deeppink2", 238, 18, 137 }, - { "deeppink3", 205, 16, 118 }, - { "deeppink4", 139, 10, 80 }, - { "deepskyblue", 0, 191, 255 }, - { "deepskyblue1", 0, 191, 255 }, - { "deepskyblue2", 0, 178, 238 }, - { "deepskyblue3", 0, 154, 205 }, - { "deepskyblue4", 0, 104, 139 }, - { "dimgray", 105, 105, 105 }, - { "dimgrey", 105, 105, 105 }, - { "dodgerblue", 30, 144, 255 }, - { "dodgerblue1", 30, 144, 255 }, - { "dodgerblue2", 28, 134, 238 }, - { "dodgerblue3", 24, 116, 205 }, - { "dodgerblue4", 16, 78, 139 }, - { "firebrick", 178, 34, 34 }, - { "firebrick1", 255, 48, 48 }, - { "firebrick2", 238, 44, 44 }, - { "firebrick3", 205, 38, 38 }, - { "firebrick4", 139, 26, 26 }, - { "floralwhite", 255, 250, 240 }, - { "forestgreen", 176, 48, 96 }, - { "gainsboro", 220, 220, 220 }, - { "ghostwhite", 248, 248, 255 }, - { "gold", 255, 215, 0 }, - { "gold1", 255, 215, 0 }, - { "gold2", 238, 201, 0 }, - { "gold3", 205, 173, 0 }, - { "gold4", 139, 117, 0 }, - { "goldenrod", 218, 165, 32 }, - { "goldenrod1", 255, 193, 37 }, - { "goldenrod2", 238, 180, 34 }, - { "goldenrod3", 205, 155, 29 }, - { "goldenrod4", 139, 105, 20 }, - { "gray", 190, 190, 190 }, - { "green", 0, 255, 0 }, - { "green1", 0, 255, 0 }, - { "green2", 0, 238, 0 }, - { "green3", 0, 205, 0 }, - { "green4", 0, 139, 0 }, - { "greenyellow", 173, 255, 47 }, - { "grey", 190, 190, 190 }, - { "honeydew", 240, 255, 240 }, - { "honeydew1", 240, 255, 240 }, - { "honeydew2", 224, 238, 224 }, - { "honeydew3", 193, 205, 193 }, - { "honeydew4", 131, 139, 131 }, - { "hotpink", 255, 105, 180 }, - { "hotpink1", 255, 110, 180 }, - { "hotpink2", 238, 106, 167 }, - { "hotpink3", 205, 96, 144 }, - { "hotpink4", 139, 58, 98 }, - { "indianred", 205, 92, 92 }, - { "indianred1", 255, 106, 106 }, - { "indianred2", 238, 99, 99 }, - { "indianred3", 205, 85, 85 }, - { "indianred4", 139, 58, 58 }, - { "ivory", 255, 255, 240 }, - { "ivory1", 255, 255, 240 }, - { "ivory2", 238, 238, 224 }, - { "ivory3", 205, 205, 193 }, - { "ivory4", 139, 139, 131 }, - { "khaki", 240, 230, 140 }, - { "khaki1", 255, 246, 143 }, - { "khaki2", 238, 230, 133 }, - { "khaki3", 205, 198, 115 }, - { "khaki4", 139, 134, 78 }, - { "lavender", 230, 230, 250 }, - { "lavenderblush", 255, 240, 245 }, - { "lavenderblush1", 255, 240, 245 }, - { "lavenderblush2", 238, 224, 229 }, - { "lavenderblush3", 205, 193, 197 }, - { "lavenderblush4", 139, 131, 134 }, - { "lawngreen", 124, 252, 0 }, - { "lemonchiffon", 255, 250, 205 }, - { "lemonchiffon1", 255, 250, 205 }, - { "lemonchiffon2", 238, 233, 191 }, - { "lemonchiffon3", 205, 201, 165 }, - { "lemonchiffon4", 139, 137, 112 }, - { "lightblue", 173, 216, 230 }, - { "lightblue1", 191, 239, 255 }, - { "lightblue2", 178, 223, 238 }, - { "lightblue3", 154, 192, 205 }, - { "lightblue4", 104, 131, 139 }, - { "lightcoral", 240, 128, 128 }, - { "lightcyan", 224, 255, 255 }, - { "lightcyan1", 224, 255, 255 }, - { "lightcyan2", 209, 238, 238 }, - { "lightcyan3", 180, 205, 205 }, - { "lightcyan4", 122, 139, 139 }, - { "lightgoldenrod", 238, 221, 130 }, - { "lightgoldenrod1", 255, 236, 139 }, - { "lightgoldenrod2", 238, 220, 130 }, - { "lightgoldenrod3", 205, 190, 112 }, - { "lightgoldenrod4", 139, 129, 76 }, - { "lightgoldenrodyellow", 250, 250, 210 }, - { "lightgray", 211, 211, 211 }, - { "lightgreen", 144, 238, 144 }, - { "lightgrey", 211, 211, 211 }, - { "lightpink", 255, 182, 193 }, - { "lightpink1", 255, 174, 185 }, - { "lightpink2", 238, 162, 173 }, - { "lightpink3", 205, 140, 149 }, - { "lightpink4", 139, 95, 101 }, - { "lightsalmon", 255, 160, 122 }, - { "lightsalmon1", 255, 160, 122 }, - { "lightsalmon2", 238, 149, 114 }, - { "lightsalmon3", 205, 129, 98 }, - { "lightsalmon4", 139, 87, 66 }, - { "lightseagreen", 32, 178, 170 }, - { "lightskyblue", 135, 206, 250 }, - { "lightskyblue1", 176, 226, 255 }, - { "lightskyblue2", 164, 211, 238 }, - { "lightskyblue3", 141, 182, 205 }, - { "lightskyblue4", 96, 123, 139 }, - { "lightslateblue", 132, 112, 255 }, - { "lightslategray", 119, 136, 153 }, - { "lightslategrey", 119, 136, 153 }, - { "lightsteelblue", 176, 196, 222 }, - { "lightsteelblue1", 202, 225, 255 }, - { "lightsteelblue2", 188, 210, 238 }, - { "lightsteelblue3", 162, 181, 205 }, - { "lightsteelblue4", 110, 123, 139 }, - { "lightyellow", 255, 255, 224 }, - { "lightyellow1", 255, 255, 224 }, - { "lightyellow2", 238, 238, 209 }, - { "lightyellow3", 205, 205, 180 }, - { "lightyellow4", 139, 139, 122 }, - { "limegreen", 50, 205, 50 }, - { "linen", 250, 240, 230 }, - { "magenta", 255, 0, 255 }, - { "magenta1", 255, 0, 255 }, - { "magenta2", 238, 0, 238 }, - { "magenta3", 205, 0, 205 }, - { "magenta4", 139, 0, 139 }, - { "maroon", 0, 255, 255 }, - { "maroon1", 255, 52, 179 }, - { "maroon2", 238, 48, 167 }, - { "maroon3", 205, 41, 144 }, - { "maroon4", 139, 28, 98 }, - { "mediumaquamarine", 102, 205, 170 }, - { "mediumblue", 0, 0, 205 }, - { "mediumorchid", 186, 85, 211 }, - { "mediumorchid1", 224, 102, 255 }, - { "mediumorchid2", 209, 95, 238 }, - { "mediumorchid3", 180, 82, 205 }, - { "mediumorchid4", 122, 55, 139 }, - { "mediumpurple", 147, 112, 219 }, - { "mediumpurple1", 171, 130, 255 }, - { "mediumpurple2", 159, 121, 238 }, - { "mediumpurple3", 137, 104, 205 }, - { "mediumpurple4", 93, 71, 139 }, - { "mediumseagreen", 60, 179, 113 }, - { "mediumslateblue", 123, 104, 238 }, - { "mediumspringgreen", 0, 250, 154 }, - { "mediumturquoise", 72, 209, 204 }, - { "mediumvioletred", 199, 21, 133 }, - { "midnightblue", 25, 25, 112 }, - { "mintcream", 245, 255, 250 }, - { "mistyrose", 255, 228, 225 }, - { "mistyrose1", 255, 228, 225 }, - { "mistyrose2", 238, 213, 210 }, - { "mistyrose3", 205, 183, 181 }, - { "mistyrose4", 139, 125, 123 }, - { "moccasin", 255, 228, 181 }, - { "navajowhite", 255, 222, 173 }, - { "navajowhite1", 255, 222, 173 }, - { "navajowhite2", 238, 207, 161 }, - { "navajowhite3", 205, 179, 139 }, - { "navajowhite4", 139, 121, 94 }, - { "navy", 0, 0, 128 }, - { "navyblue", 0, 0, 128 }, - { "oldlace", 253, 245, 230 }, - { "olivedrab", 107, 142, 35 }, - { "olivedrab1", 192, 255, 62 }, - { "olivedrab2", 179, 238, 58 }, - { "olivedrab3", 154, 205, 50 }, - { "olivedrab4", 105, 139, 34 }, - { "orange", 255, 165, 0 }, - { "orange1", 255, 165, 0 }, - { "orange2", 238, 154, 0 }, - { "orange3", 205, 133, 0 }, - { "orange4", 139, 90, 0 }, - { "orangered", 255, 69, 0 }, - { "orangered1", 255, 69, 0 }, - { "orangered2", 238, 64, 0 }, - { "orangered3", 205, 55, 0 }, - { "orangered4", 139, 37, 0 }, - { "orchid", 218, 112, 214 }, - { "orchid1", 255, 131, 250 }, - { "orchid2", 238, 122, 233 }, - { "orchid3", 205, 105, 201 }, - { "orchid4", 139, 71, 137 }, - { "palegoldenrod", 238, 232, 170 }, - { "palegreen", 152, 251, 152 }, - { "palegreen1", 154, 255, 154 }, - { "palegreen2", 144, 238, 144 }, - { "palegreen3", 124, 205, 124 }, - { "palegreen4", 84, 139, 84 }, - { "paleturquoise", 175, 238, 238 }, - { "paleturquoise1", 187, 255, 255 }, - { "paleturquoise2", 174, 238, 238 }, - { "paleturquoise3", 150, 205, 205 }, - { "paleturquoise4", 102, 139, 139 }, - { "palevioletred", 219, 112, 147 }, - { "palevioletred1", 255, 130, 171 }, - { "palevioletred2", 238, 121, 159 }, - { "palevioletred3", 205, 104, 137 }, - { "palevioletred4", 139, 71, 93 }, - { "papayawhip", 255, 239, 213 }, - { "peachpuff", 255, 218, 185 }, - { "peachpuff1", 255, 218, 185 }, - { "peachpuff2", 238, 203, 173 }, - { "peachpuff3", 205, 175, 149 }, - { "peachpuff4", 139, 119, 101 }, - { "peru", 205, 133, 63 }, - { "pink", 255, 192, 203 }, - { "pink1", 255, 181, 197 }, - { "pink2", 238, 169, 184 }, - { "pink3", 205, 145, 158 }, - { "pink4", 139, 99, 108 }, - { "plum", 221, 160, 221 }, - { "plum1", 255, 187, 255 }, - { "plum2", 238, 174, 238 }, - { "plum3", 205, 150, 205 }, - { "plum4", 139, 102, 139 }, - { "powderblue", 176, 224, 230 }, - { "purple", 160, 32, 240 }, - { "purple1", 155, 48, 255 }, - { "purple2", 145, 44, 238 }, - { "purple3", 125, 38, 205 }, - { "purple4", 85, 26, 139 }, - { "red", 255, 0, 0 }, - { "red1", 255, 0, 0 }, - { "red2", 238, 0, 0 }, - { "red3", 205, 0, 0 }, - { "red4", 139, 0, 0 }, - { "rosybrown", 188, 143, 143 }, - { "rosybrown1", 255, 193, 193 }, - { "rosybrown2", 238, 180, 180 }, - { "rosybrown3", 205, 155, 155 }, - { "rosybrown4", 139, 105, 105 }, - { "royalblue", 65, 105, 225 }, - { "royalblue1", 72, 118, 255 }, - { "royalblue2", 67, 110, 238 }, - { "royalblue3", 58, 95, 205 }, - { "royalblue4", 39, 64, 139 }, - { "saddlebrown", 139, 69, 19 }, - { "salmon", 250, 128, 114 }, - { "salmon1", 255, 140, 105 }, - { "salmon2", 238, 130, 98 }, - { "salmon3", 205, 112, 84 }, - { "salmon4", 139, 76, 57 }, - { "sandybrown", 244, 164, 96 }, - { "seagreen", 46, 139, 87 }, - { "seagreen1", 84, 255, 159 }, - { "seagreen2", 78, 238, 148 }, - { "seagreen3", 67, 205, 128 }, - { "seagreen4", 46, 139, 87 }, - { "seashell", 255, 245, 238 }, - { "seashell1", 255, 245, 238 }, - { "seashell2", 238, 229, 222 }, - { "seashell3", 205, 197, 191 }, - { "seashell4", 139, 134, 130 }, - { "sienna", 160, 82, 45 }, - { "sienna1", 255, 130, 71 }, - { "sienna2", 238, 121, 66 }, - { "sienna3", 205, 104, 57 }, - { "sienna4", 139, 71, 38 }, - { "skyblue", 135, 206, 235 }, - { "skyblue1", 135, 206, 255 }, - { "skyblue2", 126, 192, 238 }, - { "skyblue3", 108, 166, 205 }, - { "skyblue4", 74, 112, 139 }, - { "slateblue", 106, 90, 205 }, - { "slateblue1", 131, 111, 255 }, - { "slateblue2", 122, 103, 238 }, - { "slateblue3", 105, 89, 205 }, - { "slateblue4", 71, 60, 139 }, - { "slategray", 112, 128, 144 }, - { "slategray1", 198, 226, 255 }, - { "slategray2", 185, 211, 238 }, - { "slategray3", 159, 182, 205 }, - { "slategray4", 108, 123, 139 }, - { "slategrey", 112, 128, 144 }, - { "snow", 255, 250, 250 }, - { "snow1", 255, 250, 250 }, - { "snow2", 238, 233, 233 }, - { "snow3", 205, 201, 201 }, - { "snow4", 139, 137, 137 }, - { "springgreen", 0, 255, 127 }, - { "springgreen1", 0, 255, 127 }, - { "springgreen2", 0, 238, 118 }, - { "springgreen3", 0, 205, 102 }, - { "springgreen4", 0, 139, 69 }, - { "steelblue", 70, 130, 180 }, - { "steelblue1", 99, 184, 255 }, - { "steelblue2", 92, 172, 238 }, - { "steelblue3", 79, 148, 205 }, - { "steelblue4", 54, 100, 139 }, - { "tan", 210, 180, 140 }, - { "tan1", 255, 165, 79 }, - { "tan2", 238, 154, 73 }, - { "tan3", 205, 133, 63 }, - { "tan4", 139, 90, 43 }, - { "thistle", 216, 191, 216 }, - { "thistle1", 255, 225, 255 }, - { "thistle2", 238, 210, 238 }, - { "thistle3", 205, 181, 205 }, - { "thistle4", 139, 123, 139 }, - { "tomato", 255, 99, 71 }, - { "tomato1", 255, 99, 71 }, - { "tomato2", 238, 92, 66 }, - { "tomato3", 205, 79, 57 }, - { "tomato4", 139, 54, 38 }, - { "turquoise", 64, 224, 208 }, - { "turquoise1", 0, 245, 255 }, - { "turquoise2", 0, 229, 238 }, - { "turquoise3", 0, 197, 205 }, - { "turquoise4", 0, 134, 139 }, - { "violet", 238, 130, 238 }, - { "violetred", 208, 32, 144 }, - { "violetred1", 255, 62, 150 }, - { "violetred2", 238, 58, 140 }, - { "violetred3", 205, 50, 120 }, - { "violetred4", 139, 34, 82 }, - { "wheat", 245, 222, 179 }, - { "wheat1", 255, 231, 186 }, - { "wheat2", 238, 216, 174 }, - { "wheat3", 205, 186, 150 }, - { "wheat4", 139, 126, 102 }, - { "white", 255, 255, 255 }, - { "whitesmoke", 245, 245, 245 }, - { "yellow", 255, 255, 0 }, - { "yellow1", 255, 255, 0 }, - { "yellow2", 238, 238, 0 }, - { "yellow3", 205, 205, 0 }, - { "yellow4", 139, 139, 0 }, - { "yellowgreen", 154, 205, 50 } -}; - - -BOOL DLL_CALLCONV -FreeImage_LookupX11Color(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue) { - int i; - - // lookup color - i = FreeImage_LookupNamedColor(szColor, X11ColorMap, sizeof(X11ColorMap)/sizeof(X11ColorMap[0])); - if (i >= 0) { - *nRed = X11ColorMap[i].r; - *nGreen = X11ColorMap[i].g; - *nBlue = X11ColorMap[i].b; - return TRUE; - } - - // not found, try for grey color with attached percent value - if ( (szColor[0] == 'g' || szColor[0] == 'G') && - (szColor[1] == 'r' || szColor[1] == 'R') && - (szColor[2] == 'e' || szColor[2] == 'E' || szColor[2] == 'a' || szColor[2] == 'A' ) && - (szColor[3] == 'y' || szColor[3] == 'Y' ) ) { - - // grey<num>, or gray<num>, num 1...100 - i = strtol(szColor+4, NULL, 10); - *nRed = (BYTE)(255.0/100.0 * i); - *nGreen = *nRed; - *nBlue = *nRed; - - return TRUE; - } - - // not found at all - *nRed = 0; - *nGreen = 0; - *nBlue = 0; - - return FALSE; -} - -// ========================================================== -// SVG Color name lookup - -/** - These are the colors defined in the SVG standard (I haven't checked - the final recommendation for changes) -*/ -static NamedColor SVGColorMap[] = { - { "aliceblue", 240, 248, 255 }, - { "antiquewhite", 250, 235, 215 }, - { "aqua", 0, 255, 255 }, - { "aquamarine", 127, 255, 212 }, - { "azure", 240, 255, 255 }, - { "beige", 245, 245, 220 }, - { "bisque", 255, 228, 196 }, - { "black", 0, 0, 0 }, - { "blanchedalmond", 255, 235, 205 }, - { "blue", 0, 0, 255 }, - { "blueviolet", 138, 43, 226 }, - { "brown", 165, 42, 42 }, - { "burlywood", 222, 184, 135 }, - { "cadetblue", 95, 158, 160 }, - { "chartreuse", 127, 255, 0 }, - { "chocolate", 210, 105, 30 }, - { "coral", 255, 127, 80 }, - { "cornflowerblue", 100, 149, 237 }, - { "cornsilk", 255, 248, 220 }, - { "crimson", 220, 20, 60 }, - { "cyan", 0, 255, 255 }, - { "darkblue", 0, 0, 139 }, - { "darkcyan", 0, 139, 139 }, - { "darkgoldenrod", 184, 134, 11 }, - { "darkgray", 169, 169, 169 }, - { "darkgreen", 0, 100, 0 }, - { "darkgrey", 169, 169, 169 }, - { "darkkhaki", 189, 183, 107 }, - { "darkmagenta", 139, 0, 139 }, - { "darkolivegreen", 85, 107, 47 }, - { "darkorange", 255, 140, 0 }, - { "darkorchid", 153, 50, 204 }, - { "darkred", 139, 0, 0 }, - { "darksalmon", 233, 150, 122 }, - { "darkseagreen", 143, 188, 143 }, - { "darkslateblue", 72, 61, 139 }, - { "darkslategray", 47, 79, 79 }, - { "darkslategrey", 47, 79, 79 }, - { "darkturquoise", 0, 206, 209 }, - { "darkviolet", 148, 0, 211 }, - { "deeppink", 255, 20, 147 }, - { "deepskyblue", 0, 191, 255 }, - { "dimgray", 105, 105, 105 }, - { "dimgrey", 105, 105, 105 }, - { "dodgerblue", 30, 144, 255 }, - { "firebrick", 178, 34, 34 }, - { "floralwhite", 255, 250, 240 }, - { "forestgreen", 34, 139, 34 }, - { "fuchsia", 255, 0, 255 }, - { "gainsboro", 220, 220, 220 }, - { "ghostwhite", 248, 248, 255 }, - { "gold", 255, 215, 0 }, - { "goldenrod", 218, 165, 32 }, - { "gray", 128, 128, 128 }, - { "green", 0, 128, 0 }, - { "greenyellow", 173, 255, 47 }, - { "grey", 128, 128, 128 }, - { "honeydew", 240, 255, 240 }, - { "hotpink", 255, 105, 180 }, - { "indianred", 205, 92, 92 }, - { "indigo", 75, 0, 130 }, - { "ivory", 255, 255, 240 }, - { "khaki", 240, 230, 140 }, - { "lavender", 230, 230, 250 }, - { "lavenderblush", 255, 240, 245 }, - { "lawngreen", 124, 252, 0 }, - { "lemonchiffon", 255, 250, 205 }, - { "lightblue", 173, 216, 230 }, - { "lightcoral", 240, 128, 128 }, - { "lightcyan", 224, 255, 255 }, - { "lightgoldenrodyellow", 250, 250, 210 }, - { "lightgray", 211, 211, 211 }, - { "lightgreen", 144, 238, 144 }, - { "lightgrey", 211, 211, 211 }, - { "lightpink", 255, 182, 193 }, - { "lightsalmon", 255, 160, 122 }, - { "lightseagreen", 32, 178, 170 }, - { "lightskyblue", 135, 206, 250 }, - { "lightslategray", 119, 136, 153 }, - { "lightslategrey", 119, 136, 153 }, - { "lightsteelblue", 176, 196, 222 }, - { "lightyellow", 255, 255, 224 }, - { "lime", 0, 255, 0 }, - { "limegreen", 50, 205, 50 }, - { "linen", 250, 240, 230 }, - { "magenta", 255, 0, 255 }, - { "maroon", 128, 0, 0 }, - { "mediumaquamarine", 102, 205, 170 }, - { "mediumblue", 0, 0, 205 }, - { "mediumorchid", 186, 85, 211 }, - { "mediumpurple", 147, 112, 219 }, - { "mediumseagreen", 60, 179, 113 }, - { "mediumslateblue", 123, 104, 238 }, - { "mediumspringgreen", 0, 250, 154 }, - { "mediumturquoise", 72, 209, 204 }, - { "mediumvioletred", 199, 21, 133 }, - { "midnightblue", 25, 25, 112 }, - { "mintcream", 245, 255, 250 }, - { "mistyrose", 255, 228, 225 }, - { "moccasin", 255, 228, 181 }, - { "navajowhite", 255, 222, 173 }, - { "navy", 0, 0, 128 }, - { "oldlace", 253, 245, 230 }, - { "olive", 128, 128, 0 }, - { "olivedrab", 107, 142, 35 }, - { "orange", 255, 165, 0 }, - { "orangered", 255, 69, 0 }, - { "orchid", 218, 112, 214 }, - { "palegoldenrod", 238, 232, 170 }, - { "palegreen", 152, 251, 152 }, - { "paleturquoise", 175, 238, 238 }, - { "palevioletred", 219, 112, 147 }, - { "papayawhip", 255, 239, 213 }, - { "peachpuff", 255, 218, 185 }, - { "peru", 205, 133, 63 }, - { "pink", 255, 192, 203 }, - { "plum", 221, 160, 221 }, - { "powderblue", 176, 224, 230 }, - { "purple", 128, 0, 128 }, - { "red", 255, 0, 0 }, - { "rosybrown", 188, 143, 143 }, - { "royalblue", 65, 105, 225 }, - { "saddlebrown", 139, 69, 19 }, - { "salmon", 250, 128, 114 }, - { "sandybrown", 244, 164, 96 }, - { "seagreen", 46, 139, 87 }, - { "seashell", 255, 245, 238 }, - { "sienna", 160, 82, 45 }, - { "silver", 192, 192, 192 }, - { "skyblue", 135, 206, 235 }, - { "slateblue", 106, 90, 205 }, - { "slategray", 112, 128, 144 }, - { "slategrey", 112, 128, 144 }, - { "snow", 255, 250, 250 }, - { "springgreen", 0, 255, 127 }, - { "steelblue", 70, 130, 180 }, - { "tan", 210, 180, 140 }, - { "teal", 0, 128, 128 }, - { "thistle", 216, 191, 216 }, - { "tomato", 255, 99, 71 }, - { "turquoise", 64, 224, 208 }, - { "violet", 238, 130, 238 }, - { "wheat", 245, 222, 179 }, - { "white", 255, 255, 255 }, - { "whitesmoke", 245, 245, 245 }, - { "yellow", 255, 255, 0 }, - { "yellowgreen", 154, 205, 50 } -}; - - -BOOL DLL_CALLCONV -FreeImage_LookupSVGColor(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue) { - int i; - - // lookup color - i = FreeImage_LookupNamedColor(szColor, SVGColorMap, sizeof(SVGColorMap)/sizeof(SVGColorMap[0])); - if (i >= 0) { - *nRed = SVGColorMap[i].r; - *nGreen = SVGColorMap[i].g; - *nBlue = SVGColorMap[i].b; - return TRUE; - } - - // not found, try for grey color with attached percent value - if ( (szColor[0] == 'g' || szColor[0] == 'G') && - (szColor[1] == 'r' || szColor[1] == 'R') && - (szColor[2] == 'e' || szColor[2] == 'E' || szColor[2] == 'a' || szColor[2] == 'A' ) && - (szColor[3] == 'y' || szColor[3] == 'Y' ) ) { - - // grey<num>, or gray<num>, num 1...100 - i = strtol(szColor+4, NULL, 10); - *nRed = (BYTE)(255.0/100.0 * i); - *nGreen = *nRed; - *nBlue = *nRed; - return TRUE; - } - - // not found at all - *nRed = 0; - *nGreen = 0; - *nBlue = 0; - - return FALSE; -} - diff --git a/plugins/AdvaImg/src/FreeImage/Conversion.cpp b/plugins/AdvaImg/src/FreeImage/Conversion.cpp deleted file mode 100644 index 815057ad08..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Conversion.cpp +++ /dev/null @@ -1,551 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Jani Kajala (janik@remedy.fi) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// - Carsten Klein (cklein05@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "Quantizers.h" - -// ---------------------------------------------------------- - -#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 CONVERTTO16(from) \ - case 16 : \ - if ((red_mask == FI16_555_RED_MASK) && (green_mask == FI16_555_GREEN_MASK) && (blue_mask == FI16_555_BLUE_MASK)) { \ - FreeImage_ConvertLine##from##To16_555(bits, scanline, FreeImage_GetWidth(dib)); \ - } else { \ - FreeImage_ConvertLine##from##To16_565(bits, scanline, FreeImage_GetWidth(dib)); \ - } \ - break; - -#define CONVERTTO16WITHPALETTE(from) \ - case 16 : \ - if ((red_mask == FI16_555_RED_MASK) && (green_mask == FI16_555_GREEN_MASK) && (blue_mask == FI16_555_BLUE_MASK)) { \ - FreeImage_ConvertLine##from##To16_555(bits, scanline, FreeImage_GetWidth(dib), FreeImage_GetPalette(dib)); \ - } else { \ - FreeImage_ConvertLine##from##To16_565(bits, scanline, FreeImage_GetWidth(dib), FreeImage_GetPalette(dib)); \ - } \ - break; - -// ========================================================== -// Utility functions declared in Utilities.h - -BOOL SwapRedBlue32(FIBITMAP* dib) { - if(FreeImage_GetImageType(dib) != FIT_BITMAP) { - return FALSE; - } - - const unsigned bytesperpixel = FreeImage_GetBPP(dib) / 8; - if(bytesperpixel > 4 || bytesperpixel < 3) { - return FALSE; - } - - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - const unsigned lineSize = FreeImage_GetLine(dib); - - BYTE* line = FreeImage_GetBits(dib); - for(unsigned y = 0; y < height; ++y, line += pitch) { - for(BYTE* pixel = line; pixel < line + lineSize ; pixel += bytesperpixel) { - INPLACESWAP(pixel[0], pixel[2]); - } - } - - return TRUE; -} - -// ---------------------------------------------------------- - -static inline void -assignRGB(WORD r, WORD g, WORD b, WORD* out) { - out[0] = r; - out[1] = g; - out[2] = b; -} - -static inline void -assignRGB(BYTE r, BYTE g, BYTE b, BYTE* out) { - out[FI_RGBA_RED] = r; - out[FI_RGBA_GREEN] = g; - out[FI_RGBA_BLUE] = b; -} - -/** -CMYK -> CMY -> RGB conversion from http://www.easyrgb.com/ - -CMYK to CMY [0-1]: C,M,Y * (1 - K) + K -CMY to RGB [0-1]: (1 - C,M,Y) - -=> R,G,B = (1 - C,M,Y) * (1 - K) -mapped to [0-MAX_VAL]: -(MAX_VAL - C,M,Y) * (MAX_VAL - K) / MAX_VAL -*/ -template <class T> -static inline void -CMYKToRGB(T C, T M, T Y, T K, T* out) { - unsigned max_val = std::numeric_limits<T>::max(); - - unsigned r = (max_val - C) * (max_val - K) / max_val; - unsigned g = (max_val - M) * (max_val - K) / max_val; - unsigned b = (max_val - Y) * (max_val - K) / max_val; - - // clamp values to [0..max_val] - T red = (T)CLAMP(r, (unsigned)0, max_val); - T green = (T)CLAMP(g, (unsigned)0, max_val); - T blue = (T)CLAMP(b, (unsigned)0, max_val); - - assignRGB(red, green, blue, out); -} - -template <class T> -static void -_convertCMYKtoRGBA(unsigned width, unsigned height, BYTE* line_start, unsigned pitch, unsigned samplesperpixel) { - const BOOL hasBlack = (samplesperpixel > 3) ? TRUE : FALSE; - const T MAX_VAL = std::numeric_limits<T>::max(); - - T K = 0; - for(unsigned y = 0; y < height; y++) { - T *line = (T*)line_start; - - for(unsigned x = 0; x < width; x++) { - if(hasBlack) { - K = line[FI_RGBA_ALPHA]; - line[FI_RGBA_ALPHA] = MAX_VAL; // TODO write the first extra channel as alpha! - } - - CMYKToRGB<T>(line[0], line[1], line[2], K, line); - - line += samplesperpixel; - } - line_start += pitch; - } -} - -BOOL -ConvertCMYKtoRGBA(FIBITMAP* dib) { - if(!FreeImage_HasPixels(dib)) { - return FALSE; - } - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - const unsigned bytesperpixel = FreeImage_GetBPP(dib)/8; - - unsigned channelSize = 1; - if (image_type == FIT_RGBA16 || image_type == FIT_RGB16) { - channelSize = sizeof(WORD); - } else if (!(image_type == FIT_BITMAP && (bytesperpixel > 2))) { - return FALSE; - } - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - BYTE *line_start = FreeImage_GetScanLine(dib, 0); - const unsigned pitch = FreeImage_GetPitch(dib); - - unsigned samplesperpixel = FreeImage_GetLine(dib) / width / channelSize; - - if(channelSize == sizeof(WORD)) { - _convertCMYKtoRGBA<WORD>(width, height, line_start, pitch, samplesperpixel); - } else { - _convertCMYKtoRGBA<BYTE>(width, height, line_start, pitch, samplesperpixel); - } - - return TRUE; -} - -// ---------------------------------------------------------- - -/** -CIELab -> XYZ conversion from http://www.easyrgb.com/ -*/ -static void -CIELabToXYZ(float L, float a, float b, float *X, float *Y, float *Z) { - float pow_3; - - // CIELab -> XYZ conversion - // ------------------------ - float var_Y = (L + 16.F ) / 116.F; - float var_X = a / 500.F + var_Y; - float var_Z = var_Y - b / 200.F; - - pow_3 = powf(var_Y, 3); - if(pow_3 > 0.008856F) { - var_Y = pow_3; - } else { - var_Y = ( var_Y - 16.F / 116.F ) / 7.787F; - } - pow_3 = powf(var_X, 3); - if(pow_3 > 0.008856F) { - var_X = pow_3; - } else { - var_X = ( var_X - 16.F / 116.F ) / 7.787F; - } - pow_3 = powf(var_Z, 3); - if(pow_3 > 0.008856F) { - var_Z = pow_3; - } else { - var_Z = ( var_Z - 16.F / 116.F ) / 7.787F; - } - - static const float ref_X = 95.047F; - static const float ref_Y = 100.000F; - static const float ref_Z = 108.883F; - - *X = ref_X * var_X; // ref_X = 95.047 (Observer= 2°, Illuminant= D65) - *Y = ref_Y * var_Y; // ref_Y = 100.000 - *Z = ref_Z * var_Z; // ref_Z = 108.883 -} - -/** -XYZ -> RGB conversion from http://www.easyrgb.com/ -*/ -static void -XYZToRGB(float X, float Y, float Z, float *R, float *G, float *B) { - float var_X = X / 100; // X from 0 to 95.047 (Observer = 2°, Illuminant = D65) - float var_Y = Y / 100; // Y from 0 to 100.000 - float var_Z = Z / 100; // Z from 0 to 108.883 - - float var_R = var_X * 3.2406F + var_Y * -1.5372F + var_Z * -0.4986F; - float var_G = var_X * -0.9689F + var_Y * 1.8758F + var_Z * 0.0415F; - float var_B = var_X * 0.0557F + var_Y * -0.2040F + var_Z * 1.0570F; - - float exponent = 1.F / 2.4F; - - if(var_R > 0.0031308F) { - var_R = 1.055F * powf(var_R, exponent) - 0.055F; - } else { - var_R = 12.92F * var_R; - } - if(var_G > 0.0031308F) { - var_G = 1.055F * powf(var_G, exponent) - 0.055F; - } else { - var_G = 12.92F * var_G; - } - if(var_B > 0.0031308F) { - var_B = 1.055F * powf(var_B, exponent) - 0.055F; - } else { - var_B = 12.92F * var_B; - } - - *R = var_R; - *G = var_G; - *B = var_B; -} - -template<class T> -static void -CIELabToRGB(float L, float a, float b, T *rgb) { - float X, Y, Z; - float R, G, B; - const float max_val = std::numeric_limits<T>::max(); - - CIELabToXYZ(L, a, b, &X, &Y, &Z); - XYZToRGB(X, Y, Z, &R, &G, &B); - - // clamp values to [0..max_val] - T red = (T)CLAMP(R * max_val, 0.0F, max_val); - T green = (T)CLAMP(G * max_val, 0.0F, max_val); - T blue = (T)CLAMP(B * max_val, 0.0F, max_val); - - assignRGB(red, green, blue, rgb); -} - -template<class T> -static void -_convertLABtoRGB(unsigned width, unsigned height, BYTE* line_start, unsigned pitch, unsigned samplesperpixel) { - const unsigned max_val = std::numeric_limits<T>::max(); - const float sL = 100.F / max_val; - const float sa = 256.F / max_val; - const float sb = 256.F / max_val; - - for(unsigned y = 0; y < height; y++) { - T *line = (T*)line_start; - - for(unsigned x = 0; x < width; x++) { - CIELabToRGB(line[0]* sL, line[1]* sa - 128.F, line[2]* sb - 128.F, line); - - line += samplesperpixel; - } - line_start += pitch; - } -} - -BOOL -ConvertLABtoRGB(FIBITMAP* dib) { - if(!FreeImage_HasPixels(dib)) { - return FALSE; - } - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - const unsigned bytesperpixel = FreeImage_GetBPP(dib) / 8; - - unsigned channelSize = 1; - if (image_type == FIT_RGBA16 || image_type == FIT_RGB16) { - channelSize = sizeof(WORD); - } else if (!(image_type == FIT_BITMAP && (bytesperpixel > 2))) { - return FALSE; - } - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - BYTE *line_start = FreeImage_GetScanLine(dib, 0); - const unsigned pitch = FreeImage_GetPitch(dib); - - unsigned samplesperpixel = FreeImage_GetLine(dib) / width / channelSize; - - if(channelSize == 1) { - _convertLABtoRGB<BYTE>(width, height, line_start, pitch, samplesperpixel); - } - else { - _convertLABtoRGB<WORD>(width, height, line_start, pitch, samplesperpixel); - } - - return TRUE; -} - -// ---------------------------------------------------------- - -FIBITMAP* -RemoveAlphaChannel(FIBITMAP* src) { - - if(!FreeImage_HasPixels(src)) { - return NULL; - } - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - switch(image_type) { - case FIT_BITMAP: - if(FreeImage_GetBPP(src) == 32) { - // convert to 24-bit - return FreeImage_ConvertTo24Bits(src); - } - break; - case FIT_RGBA16: - // convert to RGB16 - return FreeImage_ConvertToRGB16(src); - case FIT_RGBAF: - // convert to RGBF - return FreeImage_ConvertToRGBF(src); - default: - // unsupported image type - return NULL; - } - - return NULL; -} - - -// ========================================================== - -FIBITMAP * DLL_CALLCONV -FreeImage_ColorQuantize(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize) { - return FreeImage_ColorQuantizeEx(dib, quantize); -} - -FIBITMAP * DLL_CALLCONV -FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize, int PaletteSize, int ReserveSize, RGBQUAD *ReservePalette) { - if( PaletteSize < 2 ) PaletteSize = 2; - if( PaletteSize > 256 ) PaletteSize = 256; - if( ReserveSize < 0 ) ReserveSize = 0; - if( ReserveSize > PaletteSize ) ReserveSize = PaletteSize; - if (FreeImage_HasPixels(dib)) { - const unsigned bpp = FreeImage_GetBPP(dib); - if((FreeImage_GetImageType(dib) == FIT_BITMAP) && (bpp == 24 || bpp == 32)) { - switch(quantize) { - case FIQ_WUQUANT : - { - try { - WuQuantizer Q (dib); - FIBITMAP *dst = Q.Quantize(PaletteSize, ReserveSize, ReservePalette); - if(dst) { - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, dib); - } - return dst; - } catch (const char *) { - return NULL; - } - break; - } - case FIQ_NNQUANT : - { - if (bpp == 32) { - // 32-bit images not supported by NNQUANT - return NULL; - } - // sampling factor in range 1..30. - // 1 => slower (but better), 30 => faster. Default value is 1 - const int sampling = 1; - - NNQuantizer Q(PaletteSize); - FIBITMAP *dst = Q.Quantize(dib, ReserveSize, ReservePalette, sampling); - if(dst) { - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, dib); - } - return dst; - } - case FIQ_LFPQUANT : - { - LFPQuantizer Q(PaletteSize); - FIBITMAP *dst = Q.Quantize(dib, ReserveSize, ReservePalette); - if(dst) { - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, dib); - } - return dst; - } - } - } - } - - return NULL; -} - -// ========================================================== - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertFromRawBitsEx(BOOL copySource, BYTE *bits, FREE_IMAGE_TYPE type, int width, int height, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown) { - FIBITMAP *dib = NULL; - - if(copySource) { - // allocate a FIBITMAP with internally managed pixel buffer - dib = FreeImage_AllocateT(type, width, height, bpp, red_mask, green_mask, blue_mask); - if(!dib) { - return NULL; - } - // copy user provided pixel buffer into the dib - const unsigned linesize = FreeImage_GetLine(dib); - for(int y = 0; y < height; y++) { - memcpy(FreeImage_GetScanLine(dib, y), bits, linesize); - // next line in user's buffer - bits += pitch; - } - // flip pixels vertically if needed - if(topdown) { - FreeImage_FlipVertical(dib); - } - } - else { - // allocate a FIBITMAP using a wrapper to user provided pixel buffer - dib = FreeImage_AllocateHeaderForBits(bits, pitch, type, width, height, bpp, red_mask, green_mask, blue_mask); - if(!dib) { - return NULL; - } - // flip pixels vertically if needed - if(topdown) { - FreeImage_FlipVertical(dib); - } - } - - return dib; -} - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertFromRawBits(BYTE *bits, int width, int height, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown) { - return FreeImage_ConvertFromRawBitsEx(TRUE /* copySource */, bits, FIT_BITMAP, width, height, pitch, bpp, red_mask, green_mask, blue_mask, topdown); -} - -void DLL_CALLCONV -FreeImage_ConvertToRawBits(BYTE *bits, FIBITMAP *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown) { - if (FreeImage_HasPixels(dib) && (bits != NULL)) { - for (unsigned i = 0; i < FreeImage_GetHeight(dib); ++i) { - BYTE *scanline = FreeImage_GetScanLine(dib, topdown ? (FreeImage_GetHeight(dib) - i - 1) : i); - - if ((bpp == 16) && (FreeImage_GetBPP(dib) == 16)) { - // convert 555 to 565 or vice versa - - if ((red_mask == FI16_555_RED_MASK) && (green_mask == FI16_555_GREEN_MASK) && (blue_mask == FI16_555_BLUE_MASK)) { - if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { - FreeImage_ConvertLine16_565_To16_555(bits, scanline, FreeImage_GetWidth(dib)); - } else { - memcpy(bits, scanline, FreeImage_GetLine(dib)); - } - } else { - if ((FreeImage_GetRedMask(dib) == FI16_555_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_555_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_555_BLUE_MASK)) { - FreeImage_ConvertLine16_555_To16_565(bits, scanline, FreeImage_GetWidth(dib)); - } else { - memcpy(bits, scanline, FreeImage_GetLine(dib)); - } - } - } else if (FreeImage_GetBPP(dib) != bpp) { - switch(FreeImage_GetBPP(dib)) { - case 1 : - switch(bpp) { - CONVERT(1, 8) - CONVERTTO16WITHPALETTE(1) - CONVERTWITHPALETTE(1, 24) - CONVERTWITHPALETTE(1, 32) - } - - break; - - case 4 : - switch(bpp) { - CONVERT(4, 8) - CONVERTTO16WITHPALETTE(4) - CONVERTWITHPALETTE(4, 24) - CONVERTWITHPALETTE(4, 32) - } - - break; - - case 8 : - switch(bpp) { - CONVERTTO16WITHPALETTE(8) - CONVERTWITHPALETTE(8, 24) - CONVERTWITHPALETTE(8, 32) - } - - break; - - case 24 : - switch(bpp) { - CONVERT(24, 8) - CONVERTTO16(24) - CONVERT(24, 32) - } - - break; - - case 32 : - switch(bpp) { - CONVERT(32, 8) - CONVERTTO16(32) - CONVERT(32, 24) - } - - break; - } - } else { - memcpy(bits, scanline, FreeImage_GetLine(dib)); - } - - bits += pitch; - } - } -} diff --git a/plugins/AdvaImg/src/FreeImage/Conversion16_555.cpp b/plugins/AdvaImg/src/FreeImage/Conversion16_555.cpp deleted file mode 100644 index 3eb4c330a5..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Conversion16_555.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Jani Kajala (janik@remedy.fi) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- - -#define RGB555(b, g, r) ((((b) >> 3) << FI16_555_BLUE_SHIFT) | (((g) >> 3) << FI16_555_GREEN_SHIFT) | (((r) >> 3) << FI16_555_RED_SHIFT)) - -// ---------------------------------------------------------- -// internal conversions X to 16 bits (555) -// ---------------------------------------------------------- - -void DLL_CALLCONV -FreeImage_ConvertLine1To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - int index = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0; - - new_bits[cols] = RGB555(palette[index].rgbBlue, palette[index].rgbGreen, palette[index].rgbRed); - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine4To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - WORD *new_bits = (WORD *)target; - BOOL lonibble = FALSE; - int x = 0; - - for (int cols = 0; cols < width_in_pixels; cols++) { - RGBQUAD *grab_palette; - - if (lonibble) { - grab_palette = palette + LOWNIBBLE(source[x++]); - } else { - grab_palette = palette + (HINIBBLE(source[x]) >> 4); - } - - new_bits[cols] = RGB555(grab_palette->rgbBlue, grab_palette->rgbGreen, grab_palette->rgbRed); - - lonibble = !lonibble; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine8To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - RGBQUAD *grab_palette = palette + source[cols]; - - new_bits[cols] = RGB555(grab_palette->rgbBlue, grab_palette->rgbGreen, grab_palette->rgbRed); - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16_565_To16_555(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *src_bits = (WORD *)source; - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - new_bits[cols] = RGB555((((src_bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F, - (((src_bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F, - (((src_bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F); - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine24To16_555(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - new_bits[cols] = RGB555(source[FI_RGBA_BLUE], source[FI_RGBA_GREEN], source[FI_RGBA_RED]); - - source += 3; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine32To16_555(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - new_bits[cols] = RGB555(source[FI_RGBA_BLUE], source[FI_RGBA_GREEN], source[FI_RGBA_RED]); - - source += 4; - } -} - -// ---------------------------------------------------------- -// smart convert X to 16 bits -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertTo16Bits555(FIBITMAP *dib) { - if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) return NULL; - - const int width = FreeImage_GetWidth(dib); - const int height = FreeImage_GetHeight(dib); - const int bpp = FreeImage_GetBPP(dib); - - if(bpp == 16) { - if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { - // RGB 565 - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 16, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine16_565_To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - return new_dib; - } else { - // RGB 555 - return FreeImage_Clone(dib); - } - } - else { - // other bpp cases => convert to RGB 555 - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 16, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - switch (bpp) { - case 1 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - - return new_dib; - } - - case 4 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine4To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - - return new_dib; - } - - case 8 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine8To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - - return new_dib; - } - - case 24 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine24To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - - return new_dib; - } - - case 32 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine32To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - - return new_dib; - } - - default : - // unreachable code ... - FreeImage_Unload(new_dib); - break; - - } - } - - return NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/Conversion16_565.cpp b/plugins/AdvaImg/src/FreeImage/Conversion16_565.cpp deleted file mode 100644 index fd790b92f4..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Conversion16_565.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Jani Kajala (janik@remedy.fi) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// internal conversions X to 16 bits (565) -// ---------------------------------------------------------- - -void DLL_CALLCONV -FreeImage_ConvertLine1To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - int index = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0; - - new_bits[cols] = RGB565(palette[index].rgbBlue, palette[index].rgbGreen, palette[index].rgbRed); - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine4To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - WORD *new_bits = (WORD *)target; - BOOL lonibble = FALSE; - int x = 0; - - for (int cols = 0; cols < width_in_pixels; cols++) { - RGBQUAD *grab_palette; - - if (lonibble) { - grab_palette = palette + LOWNIBBLE(source[x++]); - } else { - grab_palette = palette + (HINIBBLE(source[x]) >> 4); - } - - new_bits[cols] = RGB565(grab_palette->rgbBlue, grab_palette->rgbGreen, grab_palette->rgbRed); - - lonibble = !lonibble; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine8To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - RGBQUAD *grab_palette = palette + source[cols]; - - new_bits[cols] = RGB565(grab_palette->rgbBlue, grab_palette->rgbGreen, grab_palette->rgbRed); - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16_555_To16_565(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *src_bits = (WORD *)source; - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - new_bits[cols] = RGB565((((src_bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F, - (((src_bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F, - (((src_bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine24To16_565(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - new_bits[cols] = RGB565(source[FI_RGBA_BLUE], source[FI_RGBA_GREEN], source[FI_RGBA_RED]); - - source += 3; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine32To16_565(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *new_bits = (WORD *)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - new_bits[cols] = RGB565(source[FI_RGBA_BLUE], source[FI_RGBA_GREEN], source[FI_RGBA_RED]); - - source += 4; - } -} - -// ---------------------------------------------------------- -// smart convert X to 16 bits (565) -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertTo16Bits565(FIBITMAP *dib) { - if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) return NULL; - - const int width = FreeImage_GetWidth(dib); - const int height = FreeImage_GetHeight(dib); - const int bpp = FreeImage_GetBPP(dib); - - if(bpp == 16) { - if ((FreeImage_GetRedMask(dib) == FI16_555_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_555_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_555_BLUE_MASK)) { - // RGB 555 - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 16, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine16_555_To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - return new_dib; - } else { - // RGB 565 - return FreeImage_Clone(dib); - } - } - else { - // other bpp cases => convert to RGB 565 - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 16, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - switch (bpp) { - case 1 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - - return new_dib; - } - - case 4 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine4To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - - return new_dib; - } - - case 8 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine8To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - - return new_dib; - } - - case 24 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine24To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - - return new_dib; - } - - case 32 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine32To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - - return new_dib; - } - - default : - // unreachable code ... - FreeImage_Unload(new_dib); - break; - } - } - - return NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/Conversion24.cpp b/plugins/AdvaImg/src/FreeImage/Conversion24.cpp deleted file mode 100644 index 85ce90417b..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Conversion24.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Dale Larson (dlarson@norsesoft.com) -// - Hervé Drolon (drolon@infonie.fr) -// - Jani Kajala (janik@remedy.fi) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// internal conversions X to 24 bits -// ---------------------------------------------------------- - -void DLL_CALLCONV -FreeImage_ConvertLine1To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - for (int cols = 0; cols < width_in_pixels; cols++) { - BYTE index = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0; - - target[FI_RGBA_BLUE] = palette[index].rgbBlue; - target[FI_RGBA_GREEN] = palette[index].rgbGreen; - target[FI_RGBA_RED] = palette[index].rgbRed; - - target += 3; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine4To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - BOOL low_nibble = FALSE; - int x = 0; - - for (int cols = 0; cols < width_in_pixels; ++cols ) { - if (low_nibble) { - target[FI_RGBA_BLUE] = palette[LOWNIBBLE(source[x])].rgbBlue; - target[FI_RGBA_GREEN] = palette[LOWNIBBLE(source[x])].rgbGreen; - target[FI_RGBA_RED] = palette[LOWNIBBLE(source[x])].rgbRed; - - x++; - } else { - target[FI_RGBA_BLUE] = palette[HINIBBLE(source[x]) >> 4].rgbBlue; - target[FI_RGBA_GREEN] = palette[HINIBBLE(source[x]) >> 4].rgbGreen; - target[FI_RGBA_RED] = palette[HINIBBLE(source[x]) >> 4].rgbRed; - } - - low_nibble = !low_nibble; - - target += 3; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine8To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - for (int cols = 0; cols < width_in_pixels; cols++) { - target[FI_RGBA_BLUE] = palette[source[cols]].rgbBlue; - target[FI_RGBA_GREEN] = palette[source[cols]].rgbGreen; - target[FI_RGBA_RED] = palette[source[cols]].rgbRed; - - target += 3; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16To24_555(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *bits = (WORD *)source; - - for (int cols = 0; cols < width_in_pixels; cols++) { - target[FI_RGBA_RED] = (BYTE)((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); - target[FI_RGBA_GREEN] = (BYTE)((((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F); - target[FI_RGBA_BLUE] = (BYTE)((((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); - - target += 3; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16To24_565(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *bits = (WORD *)source; - - for (int cols = 0; cols < width_in_pixels; cols++) { - target[FI_RGBA_RED] = (BYTE)((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F); - target[FI_RGBA_GREEN] = (BYTE)((((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F); - target[FI_RGBA_BLUE] = (BYTE)((((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F); - - target += 3; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine32To24(BYTE *target, BYTE *source, int width_in_pixels) { - for (int cols = 0; cols < width_in_pixels; cols++) { - target[FI_RGBA_BLUE] = source[FI_RGBA_BLUE]; - target[FI_RGBA_GREEN] = source[FI_RGBA_GREEN]; - target[FI_RGBA_RED] = source[FI_RGBA_RED]; - - target += 3; - source += 4; - } -} - -// ---------------------------------------------------------- -// smart convert X to 24 bits -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertTo24Bits(FIBITMAP *dib) { - if(!FreeImage_HasPixels(dib)) return NULL; - - const unsigned bpp = FreeImage_GetBPP(dib); - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - if((image_type != FIT_BITMAP) && (image_type != FIT_RGB16) && (image_type != FIT_RGBA16)) { - return NULL; - } - - const int width = FreeImage_GetWidth(dib); - const int height = FreeImage_GetHeight(dib); - - if(image_type == FIT_BITMAP) { - if(bpp == 24) { - return FreeImage_Clone(dib); - } - - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - switch(bpp) { - case 1 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To24(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - return new_dib; - } - - case 4 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine4To24(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - return new_dib; - } - - case 8 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine8To24(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - return new_dib; - } - - case 16 : - { - for (int rows = 0; rows < height; rows++) { - if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { - FreeImage_ConvertLine16To24_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } else { - // includes case where all the masks are 0 - FreeImage_ConvertLine16To24_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - } - return new_dib; - } - - case 32 : - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine32To24(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - return new_dib; - } - } - - } else if(image_type == FIT_RGB16) { - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - const unsigned src_pitch = FreeImage_GetPitch(dib); - const unsigned dst_pitch = FreeImage_GetPitch(new_dib); - const BYTE *src_bits = FreeImage_GetBits(dib); - BYTE *dst_bits = FreeImage_GetBits(new_dib); - for (int rows = 0; rows < height; rows++) { - const FIRGB16 *src_pixel = (FIRGB16*)src_bits; - RGBTRIPLE *dst_pixel = (RGBTRIPLE*)dst_bits; - for(int cols = 0; cols < width; cols++) { - dst_pixel[cols].rgbtRed = (BYTE)(src_pixel[cols].red >> 8); - dst_pixel[cols].rgbtGreen = (BYTE)(src_pixel[cols].green >> 8); - dst_pixel[cols].rgbtBlue = (BYTE)(src_pixel[cols].blue >> 8); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - - return new_dib; - - } else if(image_type == FIT_RGBA16) { - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - const unsigned src_pitch = FreeImage_GetPitch(dib); - const unsigned dst_pitch = FreeImage_GetPitch(new_dib); - const BYTE *src_bits = FreeImage_GetBits(dib); - BYTE *dst_bits = FreeImage_GetBits(new_dib); - for (int rows = 0; rows < height; rows++) { - const FIRGBA16 *src_pixel = (FIRGBA16*)src_bits; - RGBTRIPLE *dst_pixel = (RGBTRIPLE*)dst_bits; - for(int cols = 0; cols < width; cols++) { - dst_pixel[cols].rgbtRed = (BYTE)(src_pixel[cols].red >> 8); - dst_pixel[cols].rgbtGreen = (BYTE)(src_pixel[cols].green >> 8); - dst_pixel[cols].rgbtBlue = (BYTE)(src_pixel[cols].blue >> 8); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - - return new_dib; - } - - return NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/Conversion32.cpp b/plugins/AdvaImg/src/FreeImage/Conversion32.cpp deleted file mode 100644 index 0dc31287e6..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Conversion32.cpp +++ /dev/null @@ -1,345 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Jani Kajala (janik@remedy.fi) -// - Detlev Vendt (detlev.vendt@brillit.de) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// internal conversions X to 32 bits -// ---------------------------------------------------------- - -void DLL_CALLCONV -FreeImage_ConvertLine1To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - for (int cols = 0; cols < width_in_pixels; cols++) { - int index = (source[cols>>3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0; - - target[FI_RGBA_BLUE] = palette[index].rgbBlue; - target[FI_RGBA_GREEN] = palette[index].rgbGreen; - target[FI_RGBA_RED] = palette[index].rgbRed; - target[FI_RGBA_ALPHA] = 0xFF; - target += 4; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine4To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - BOOL low_nibble = FALSE; - int x = 0; - - for (int cols = 0 ; cols < width_in_pixels ; ++cols) { - if (low_nibble) { - target[FI_RGBA_BLUE] = palette[LOWNIBBLE(source[x])].rgbBlue; - target[FI_RGBA_GREEN] = palette[LOWNIBBLE(source[x])].rgbGreen; - target[FI_RGBA_RED] = palette[LOWNIBBLE(source[x])].rgbRed; - - x++; - } else { - target[FI_RGBA_BLUE] = palette[HINIBBLE(source[x]) >> 4].rgbBlue; - target[FI_RGBA_GREEN] = palette[HINIBBLE(source[x]) >> 4].rgbGreen; - target[FI_RGBA_RED] = palette[HINIBBLE(source[x]) >> 4].rgbRed; - } - - low_nibble = !low_nibble; - - target[FI_RGBA_ALPHA] = 0xFF; - target += 4; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine8To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - for (int cols = 0; cols < width_in_pixels; cols++) { - target[FI_RGBA_BLUE] = palette[source[cols]].rgbBlue; - target[FI_RGBA_GREEN] = palette[source[cols]].rgbGreen; - target[FI_RGBA_RED] = palette[source[cols]].rgbRed; - target[FI_RGBA_ALPHA] = 0xFF; - target += 4; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16To32_555(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *bits = (WORD *)source; - - for (int cols = 0; cols < width_in_pixels; cols++) { - target[FI_RGBA_RED] = (BYTE)((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); - target[FI_RGBA_GREEN] = (BYTE)((((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F); - target[FI_RGBA_BLUE] = (BYTE)((((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); - target[FI_RGBA_ALPHA] = 0xFF; - target += 4; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16To32_565(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *bits = (WORD *)source; - - for (int cols = 0; cols < width_in_pixels; cols++) { - target[FI_RGBA_RED] = (BYTE)((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F); - target[FI_RGBA_GREEN] = (BYTE)((((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F); - target[FI_RGBA_BLUE] = (BYTE)((((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F); - target[FI_RGBA_ALPHA] = 0xFF; - target += 4; - } -} -/* -void DLL_CALLCONV -FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels) { - for (int cols = 0; cols < width_in_pixels; cols++) { - *(DWORD *)target = (*(DWORD *) source & FI_RGBA_RGB_MASK) | FI_RGBA_ALPHA_MASK; - target += 4; - source += 3; - } -} -*/ -/** -This unoptimized version of the conversion function avoid an undetermined bug with VC++ SP6. -The bug occurs in release mode only, when the image height is equal to 537 -(try e.g. a size of 432x537 to reproduce the bug with the optimized function). -*/ -void DLL_CALLCONV -FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels) { - for (int cols = 0; cols < width_in_pixels; cols++) { - target[FI_RGBA_RED] = source[FI_RGBA_RED]; - target[FI_RGBA_GREEN] = source[FI_RGBA_GREEN]; - target[FI_RGBA_BLUE] = source[FI_RGBA_BLUE]; - target[FI_RGBA_ALPHA] = 0xFF; - target += 4; - source += 3; - } -} - -// ---------------------------------------------------------- - -inline void -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; - - target[FI_RGBA_BLUE] = palette[index].rgbBlue; - target[FI_RGBA_GREEN] = palette[index].rgbGreen; - target[FI_RGBA_RED] = palette[index].rgbRed; - target[FI_RGBA_ALPHA] = (index < transparent_pixels) ? table[index] : 255; - target += 4; - } -} - -inline void -FreeImage_ConvertLine4To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { - BOOL low_nibble = FALSE; - int x = 0; - - for (int cols = 0 ; cols < width_in_pixels ; ++cols) { - if (low_nibble) { - target[FI_RGBA_BLUE] = palette[LOWNIBBLE(source[x])].rgbBlue; - target[FI_RGBA_GREEN] = palette[LOWNIBBLE(source[x])].rgbGreen; - target[FI_RGBA_RED] = palette[LOWNIBBLE(source[x])].rgbRed; - target[FI_RGBA_ALPHA] = (LOWNIBBLE(source[x]) < transparent_pixels) ? table[LOWNIBBLE(source[x])] : 255; - - x++; - } else { - target[FI_RGBA_BLUE] = palette[HINIBBLE(source[x]) >> 4].rgbBlue; - target[FI_RGBA_GREEN] = palette[HINIBBLE(source[x]) >> 4].rgbGreen; - target[FI_RGBA_RED] = palette[HINIBBLE(source[x]) >> 4].rgbRed; - target[FI_RGBA_ALPHA] = (HINIBBLE(source[x] >> 4) < transparent_pixels) ? table[HINIBBLE(source[x]) >> 4] : 255; - } - - low_nibble = !low_nibble; - - target += 4; - } -} - -inline void -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; - target[FI_RGBA_GREEN] = palette[source[cols]].rgbGreen; - target[FI_RGBA_RED] = palette[source[cols]].rgbRed; - target[FI_RGBA_ALPHA] = (source[cols] < transparent_pixels) ? table[source[cols]] : 255; - target += 4; - } -} - -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertTo32Bits(FIBITMAP *dib) { - if(!FreeImage_HasPixels(dib)) return NULL; - - const int bpp = FreeImage_GetBPP(dib); - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - if((image_type != FIT_BITMAP) && (image_type != FIT_RGB16) && (image_type != FIT_RGBA16)) { - return NULL; - } - - const int width = FreeImage_GetWidth(dib); - const int height = FreeImage_GetHeight(dib); - - if(image_type == FIT_BITMAP) { - - if(bpp == 32) { - return FreeImage_Clone(dib); - } - - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - BOOL bIsTransparent = FreeImage_IsTransparent(dib); - - switch(bpp) { - case 1: - { - if(bIsTransparent) { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - } - } else { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - } - - return new_dib; - } - - case 4: - { - if(bIsTransparent) { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine4To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - } - } else { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine4To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - } - - return new_dib; - } - - case 8: - { - if(bIsTransparent) { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine8To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - } - } else { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine8To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - } - - return new_dib; - } - - case 16: - { - for (int rows = 0; rows < height; rows++) { - if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { - FreeImage_ConvertLine16To32_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } else { - // includes case where all the masks are 0 - FreeImage_ConvertLine16To32_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - } - - return new_dib; - } - - case 24: - { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine24To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - - return new_dib; - } - } - - } else if(image_type == FIT_RGB16) { - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - const unsigned src_pitch = FreeImage_GetPitch(dib); - const unsigned dst_pitch = FreeImage_GetPitch(new_dib); - const BYTE *src_bits = FreeImage_GetBits(dib); - BYTE *dst_bits = FreeImage_GetBits(new_dib); - for (int rows = 0; rows < height; rows++) { - const FIRGB16 *src_pixel = (FIRGB16*)src_bits; - RGBQUAD *dst_pixel = (RGBQUAD*)dst_bits; - for(int cols = 0; cols < width; cols++) { - dst_pixel[cols].rgbRed = (BYTE)(src_pixel[cols].red >> 8); - dst_pixel[cols].rgbGreen = (BYTE)(src_pixel[cols].green >> 8); - dst_pixel[cols].rgbBlue = (BYTE)(src_pixel[cols].blue >> 8); - dst_pixel[cols].rgbReserved = (BYTE)0xFF; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - - return new_dib; - - } else if(image_type == FIT_RGBA16) { - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - const unsigned src_pitch = FreeImage_GetPitch(dib); - const unsigned dst_pitch = FreeImage_GetPitch(new_dib); - const BYTE *src_bits = FreeImage_GetBits(dib); - BYTE *dst_bits = FreeImage_GetBits(new_dib); - for (int rows = 0; rows < height; rows++) { - const FIRGBA16 *src_pixel = (FIRGBA16*)src_bits; - RGBQUAD *dst_pixel = (RGBQUAD*)dst_bits; - for(int cols = 0; cols < width; cols++) { - dst_pixel[cols].rgbRed = (BYTE)(src_pixel[cols].red >> 8); - dst_pixel[cols].rgbGreen = (BYTE)(src_pixel[cols].green >> 8); - dst_pixel[cols].rgbBlue = (BYTE)(src_pixel[cols].blue >> 8); - dst_pixel[cols].rgbReserved = (BYTE)(src_pixel[cols].alpha >> 8); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - - return new_dib; - } - - return NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/Conversion4.cpp b/plugins/AdvaImg/src/FreeImage/Conversion4.cpp deleted file mode 100644 index 13048b6d3f..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Conversion4.cpp +++ /dev/null @@ -1,246 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Riley McNiff (rmcniff@marexgroup.com) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// internal conversions X to 4 bits -// ---------------------------------------------------------- - -void DLL_CALLCONV -FreeImage_ConvertLine1To4(BYTE *target, BYTE *source, int width_in_pixels) { - BOOL hinibble = TRUE; - for (int cols = 0; cols < width_in_pixels; cols++){ - if (hinibble == TRUE){ - target[cols >> 1] = ((source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 15 : 0) << 4; - } - else { - target[cols >> 1] |= ((source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 15 : 0); - } - - hinibble = !hinibble; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine8To4(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) { - BOOL hinibble = TRUE; - BYTE index; - - for (int cols = 0; cols < width_in_pixels; cols++){ - index = GREY(palette[source[cols]].rgbRed, palette[source[cols]].rgbGreen, palette[source[cols]].rgbBlue); - if (hinibble) { - target[cols >> 1] = (index & 0xF0); - } else { - target[cols >> 1] |= (index >> 4); - } - - hinibble = !hinibble; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16To4_555(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *bits = (WORD *)source; - BOOL hinibble = TRUE; - - for (int cols = 0; cols < width_in_pixels; cols++) { - if (hinibble) { - target[cols >> 1] = GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F) - & 0xF0; - } else { - target[cols >> 1] |= GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F) - >> 4; - } - - hinibble = !hinibble; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16To4_565(BYTE *target, BYTE *source, int width_in_pixels) { - WORD *bits = (WORD *)source; - BOOL hinibble = TRUE; - - for (int cols = 0; cols < width_in_pixels; cols++) { - if (hinibble) { - target[cols >> 1] = GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F, - (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F) - & 0xF0; - } else { - target[cols >> 1] |= GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F, - (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F) - >> 4; - } - - hinibble = !hinibble; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine24To4(BYTE *target, BYTE *source, int width_in_pixels) { - BOOL hinibble = TRUE; - - for (int cols = 0; cols < width_in_pixels; cols++) { - if (hinibble) { - target[cols >> 1] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) & 0xF0; - } else { - target[cols >> 1] |= GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) >> 4; - } - - source += 3; - hinibble = !hinibble; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine32To4(BYTE *target, BYTE *source, int width_in_pixels) { - BOOL hinibble = TRUE; - - for (int cols = 0; cols < width_in_pixels; cols++) { - if (hinibble) { - target[cols >> 1] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) & 0xF0; - } else { - target[cols >> 1] |= GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) >> 4; - } - - source += 4; - hinibble = !hinibble; - } -} - -// ---------------------------------------------------------- -// smart convert X to 4 bits -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertTo4Bits(FIBITMAP *dib) { - if(!FreeImage_HasPixels(dib)) return NULL; - - const int bpp = FreeImage_GetBPP(dib); - - if(bpp != 4) { - const int width = FreeImage_GetWidth(dib); - const int height = FreeImage_GetHeight(dib); - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 4); - - if(new_dib == NULL) { - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - // Build a greyscale palette (*always* needed for image processing) - - RGBQUAD *new_pal = FreeImage_GetPalette(new_dib); - - for(int i = 0; i < 16; i++) { - new_pal[i].rgbRed = (BYTE)((i << 4) + i); - new_pal[i].rgbGreen = (BYTE)((i << 4) + i); - new_pal[i].rgbBlue = (BYTE)((i << 4) + i); - } - - switch(bpp) { - case 1: - { - if(FreeImage_GetColorType(dib) == FIC_PALETTE) { - - // Copy the palette - - RGBQUAD *old_pal = FreeImage_GetPalette(dib); - memcpy(&new_pal[0], &old_pal[0], sizeof(RGBQUAD)); - memcpy(&new_pal[15], &old_pal[1], sizeof(RGBQUAD)); - - } - else if(FreeImage_GetColorType(dib) == FIC_MINISWHITE) { - - // Reverse the grayscale palette - - for(int i = 0; i < 16; i++) { - new_pal[i].rgbRed = new_pal[i].rgbGreen = new_pal[i].rgbBlue = (BYTE)(255 - ((i << 4) + i)); - } - } - - // Expand and copy the bitmap data - - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - return new_dib; - } - - case 8 : - { - // Expand and copy the bitmap data - - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine8To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - return new_dib; - } - - case 16 : - { - // Expand and copy the bitmap data - - for (int rows = 0; rows < height; rows++) { - if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { - FreeImage_ConvertLine16To4_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } else { - FreeImage_ConvertLine16To4_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - } - - return new_dib; - } - - case 24 : - { - // Expand and copy the bitmap data - - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine24To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - return new_dib; - } - - case 32 : - { - // Expand and copy the bitmap data - - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine32To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - return new_dib; - } - } - } - - return FreeImage_Clone(dib); -} diff --git a/plugins/AdvaImg/src/FreeImage/Conversion8.cpp b/plugins/AdvaImg/src/FreeImage/Conversion8.cpp deleted file mode 100644 index 861e8169ce..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Conversion8.cpp +++ /dev/null @@ -1,305 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Jani Kajala (janik@remedy.fi) -// - Karl-Heinz Bussian (khbussian@moss.de) -// - Carsten Klein (cklein05@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// internal conversions X to 8 bits -// ---------------------------------------------------------- - -void DLL_CALLCONV -FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels) { - for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) - target[cols] = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 255 : 0; -} - -void DLL_CALLCONV -FreeImage_ConvertLine4To8(BYTE *target, BYTE *source, int width_in_pixels) { - unsigned count_new = 0; - unsigned count_org = 0; - BOOL hinibble = TRUE; - - while (count_new < (unsigned)width_in_pixels) { - if (hinibble) { - target[count_new] = (source[count_org] >> 4); - } else { - target[count_new] = (source[count_org] & 0x0F); - count_org++; - } - hinibble = !hinibble; - count_new++; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16To8_555(BYTE *target, BYTE *source, int width_in_pixels) { - const WORD *const bits = (WORD *)source; - for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) { - target[cols] = GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine16To8_565(BYTE *target, BYTE *source, int width_in_pixels) { - const WORD *const bits = (WORD *)source; - for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) { - target[cols] = GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F, - (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F, - (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F); - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine24To8(BYTE *target, BYTE *source, int width_in_pixels) { - for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) { - target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]); - source += 3; - } -} - -void DLL_CALLCONV -FreeImage_ConvertLine32To8(BYTE *target, BYTE *source, int width_in_pixels) { - for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) { - target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]); - source += 4; - } -} - -// ---------------------------------------------------------- -// smart convert X to 8 bits -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertTo8Bits(FIBITMAP *dib) { - if (!FreeImage_HasPixels(dib)) { - return NULL; - } - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - if (image_type != FIT_BITMAP && image_type != FIT_UINT16) { - return NULL; - } - - const unsigned bpp = FreeImage_GetBPP(dib); - - if (bpp != 8) { - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - - // Allocate a destination image - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8); - if (new_dib == NULL) { - return NULL; - } - - // Copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - // Palette of destination image has already been initialized - RGBQUAD *new_pal = FreeImage_GetPalette(new_dib); - - const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); - - if (image_type == FIT_BITMAP) { - - switch(bpp) { - case 1: - { - if (color_type == FIC_PALETTE) { - // Copy the palette - RGBQUAD *old_pal = FreeImage_GetPalette(dib); - new_pal[0] = old_pal[0]; - new_pal[255] = old_pal[1]; - - } else if (color_type == FIC_MINISWHITE) { - // Create a reverse grayscale palette - CREATE_GREYSCALE_PALETTE_REVERSE(new_pal, 256); - } - - // Expand and copy the bitmap data - for (unsigned rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - return new_dib; - } - - case 4 : - { - if (color_type == FIC_PALETTE) { - // Copy the palette - memcpy(new_pal, FreeImage_GetPalette(dib), 16 * sizeof(RGBQUAD)); - } - - // Expand and copy the bitmap data - for (unsigned rows = 0; rows < height; rows++) { - FreeImage_ConvertLine4To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - return new_dib; - } - - case 16 : - { - // Expand and copy the bitmap data - if (IS_FORMAT_RGB565(dib)) { - for (unsigned rows = 0; rows < height; rows++) { - FreeImage_ConvertLine16To8_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - } else { - for (unsigned rows = 0; rows < height; rows++) { - FreeImage_ConvertLine16To8_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - } - return new_dib; - } - - case 24 : - { - // Expand and copy the bitmap data - for (unsigned rows = 0; rows < height; rows++) { - FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - return new_dib; - } - - case 32 : - { - // Expand and copy the bitmap data - for (unsigned rows = 0; rows < height; rows++) { - FreeImage_ConvertLine32To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); - } - return new_dib; - } - } - - } else if (image_type == FIT_UINT16) { - - const unsigned src_pitch = FreeImage_GetPitch(dib); - const unsigned dst_pitch = FreeImage_GetPitch(new_dib); - const BYTE *src_bits = FreeImage_GetBits(dib); - BYTE *dst_bits = FreeImage_GetBits(new_dib); - - for (unsigned rows = 0; rows < height; rows++) { - const WORD *const src_pixel = (WORD*)src_bits; - BYTE *dst_pixel = (BYTE*)dst_bits; - for(unsigned cols = 0; cols < width; cols++) { - dst_pixel[cols] = (BYTE)(src_pixel[cols] >> 8); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - return new_dib; - } - - } // bpp != 8 - - return FreeImage_Clone(dib); -} - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToGreyscale(FIBITMAP *dib) { - if (!FreeImage_HasPixels(dib)) { - return NULL; - } - - const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); - - if (color_type == FIC_PALETTE || color_type == FIC_MINISWHITE) { - - const unsigned bpp = FreeImage_GetBPP(dib); - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8); - if (new_dib == NULL) { - return NULL; - } - - // Copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - // Create a greyscale palette - BYTE grey_pal[256]; - const RGBQUAD *pal = FreeImage_GetPalette(dib); - const unsigned size = CalculateUsedPaletteEntries(bpp); - for (unsigned i = 0; i < size; i++) { - grey_pal[i] = GREY(pal->rgbRed, pal->rgbGreen, pal->rgbBlue); - pal++; - } - - const BYTE *src_bits = FreeImage_GetBits(dib); - BYTE *dst_bits = FreeImage_GetBits(new_dib); - - const unsigned src_pitch = FreeImage_GetPitch(dib); - const unsigned dst_pitch = FreeImage_GetPitch(new_dib); - - switch(bpp) { - case 1: - { - for (unsigned y = 0; y < height; y++) { - for (unsigned x = 0; x < width; x++) { - const unsigned pixel = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0; - dst_bits[x] = grey_pal[pixel]; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case 4: - { - for (unsigned y = 0; y < height; y++) { - for (unsigned x = 0; x < width; x++) { - const unsigned pixel = x & 0x01 ? src_bits[x >> 1] & 0x0F : src_bits[x >> 1] >> 4; - dst_bits[x] = grey_pal[pixel]; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case 8: - { - for (unsigned y = 0; y < height; y++) { - for (unsigned x = 0; x < width; x++) { - dst_bits[x] = grey_pal[src_bits[x]]; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - } - return new_dib; - } - - // Convert the bitmap to 8-bit greyscale - return FreeImage_ConvertTo8Bits(dib); -} diff --git a/plugins/AdvaImg/src/FreeImage/ConversionFloat.cpp b/plugins/AdvaImg/src/FreeImage/ConversionFloat.cpp deleted file mode 100644 index 6a01d7f0af..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ConversionFloat.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// smart convert X to Float -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToFloat(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // allow conversion from 8-bit - if((FreeImage_GetBPP(dib) == 8) && (FreeImage_GetColorType(dib) == FIC_MINISBLACK)) { - src = dib; - } else { - src = FreeImage_ConvertToGreyscale(dib); - if(!src) return NULL; - } - break; - } - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - case FIT_RGBF: - case FIT_RGBAF: - src = dib; - break; - case FIT_FLOAT: - // float type : clone the src - return FreeImage_Clone(dib); - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_FLOAT, width, height); - if(!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to float - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - switch(src_type) { - case FIT_BITMAP: - { - for(unsigned y = 0; y < height; y++) { - const BYTE *src_pixel = (BYTE*)src_bits; - float *dst_pixel = (float*)dst_bits; - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x] = (float)(src_pixel[x]) / 255; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_UINT16: - { - for(unsigned y = 0; y < height; y++) { - const WORD *src_pixel = (WORD*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x] = (float)(src_pixel[x]) / 65535; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGB16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGB16 *src_pixel = (FIRGB16*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue) / 65535.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBA16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBA16 *src_pixel = (FIRGBA16*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue) / 65535.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBF: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBF *src_pixel = (FIRGBF*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert (assume pixel values are in the range [0..1]) - dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); - dst_pixel[x] = CLAMP(dst_pixel[x], 0.0F, 1.0F); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBAF: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBAF *src_pixel = (FIRGBAF*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert (assume pixel values are in the range [0..1]) - dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); - dst_pixel[x] = CLAMP(dst_pixel[x], 0.0F, 1.0F); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/AdvaImg/src/FreeImage/ConversionRGB16.cpp b/plugins/AdvaImg/src/FreeImage/ConversionRGB16.cpp deleted file mode 100644 index 156a91b85b..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ConversionRGB16.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// smart convert X to RGB16 -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToRGB16(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // convert to 24-bit if needed - if((FreeImage_GetBPP(dib) == 24) || (FreeImage_GetBPP(dib) == 32)) { - src = dib; - } else { - src = FreeImage_ConvertTo24Bits(dib); - if(!src) return NULL; - } - break; - } - case FIT_UINT16: - // allow conversion from unsigned 16-bit - src = dib; - break; - case FIT_RGB16: - // RGB16 type : clone the src - return FreeImage_Clone(dib); - break; - case FIT_RGBA16: - // allow conversion from 64-bit RGBA (ignore the alpha channel) - src = dib; - break; - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_RGB16, width, height); - if(!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to RGB16 - - switch(src_type) { - case FIT_BITMAP: - { - // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned y = 0; y < height; y++) { - const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y); - FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - dst_bits[x].red = src_bits[FI_RGBA_RED] << 8; - dst_bits[x].green = src_bits[FI_RGBA_GREEN] << 8; - dst_bits[x].blue = src_bits[FI_RGBA_BLUE] << 8; - src_bits += bytespp; - } - } - } - break; - - case FIT_UINT16: - { - for(unsigned y = 0; y < height; y++) { - const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y); - FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert by copying greyscale channel to each R, G, B channels - dst_bits[x].red = src_bits[x]; - dst_bits[x].green = src_bits[x]; - dst_bits[x].blue = src_bits[x]; - } - } - } - break; - - case FIT_RGBA16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y); - FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert and skip alpha channel - dst_bits[x].red = src_bits[x].red; - dst_bits[x].green = src_bits[x].green; - dst_bits[x].blue = src_bits[x].blue; - } - } - } - break; - - default: - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/AdvaImg/src/FreeImage/ConversionRGBA16.cpp b/plugins/AdvaImg/src/FreeImage/ConversionRGBA16.cpp deleted file mode 100644 index 600d8ea1e6..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ConversionRGBA16.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// smart convert X to RGBA16 -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToRGBA16(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // convert to 32-bit if needed - if(FreeImage_GetBPP(dib) == 32) { - src = dib; - } else { - src = FreeImage_ConvertTo32Bits(dib); - if(!src) return NULL; - } - break; - } - case FIT_UINT16: - // allow conversion from unsigned 16-bit - src = dib; - break; - case FIT_RGB16: - // allow conversion from 48-bit RGB - src = dib; - break; - case FIT_RGBA16: - // RGBA16 type : clone the src - return FreeImage_Clone(dib); - break; - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_RGBA16, width, height); - if(!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to RGBA16 - - switch(src_type) { - case FIT_BITMAP: - { - // Calculate the number of bytes per pixel (4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned y = 0; y < height; y++) { - const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y); - FIRGBA16 *dst_bits = (FIRGBA16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - dst_bits[x].red = src_bits[FI_RGBA_RED] << 8; - dst_bits[x].green = src_bits[FI_RGBA_GREEN] << 8; - dst_bits[x].blue = src_bits[FI_RGBA_BLUE] << 8; - dst_bits[x].alpha = src_bits[FI_RGBA_ALPHA] << 8; - src_bits += bytespp; - } - } - } - break; - - case FIT_UINT16: - { - for(unsigned y = 0; y < height; y++) { - const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y); - FIRGBA16 *dst_bits = (FIRGBA16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert by copying greyscale channel to each R, G, B channels - dst_bits[x].red = src_bits[x]; - dst_bits[x].green = src_bits[x]; - dst_bits[x].blue = src_bits[x]; - dst_bits[x].alpha = 0xFFFF; - } - } - } - break; - - case FIT_RGB16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGB16 *src_bits = (FIRGB16*)FreeImage_GetScanLine(src, y); - FIRGBA16 *dst_bits = (FIRGBA16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert pixels directly, while adding a "dummy" alpha of 1.0 - dst_bits[x].red = src_bits[x].red; - dst_bits[x].green = src_bits[x].green; - dst_bits[x].blue = src_bits[x].blue; - dst_bits[x].alpha = 0xFFFF; - } - } - } - break; - - default: - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/AdvaImg/src/FreeImage/ConversionRGBAF.cpp b/plugins/AdvaImg/src/FreeImage/ConversionRGBAF.cpp deleted file mode 100644 index 2ba2b32b42..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ConversionRGBAF.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Tanner Helland (tannerhelland@users.sf.net) -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// smart convert X to RGBAF -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToRGBAF(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // allow conversion from 32-bit - const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); - if(color_type != FIC_RGBALPHA) { - src = FreeImage_ConvertTo32Bits(dib); - if(!src) return NULL; - } else { - src = dib; - } - break; - } - case FIT_UINT16: - // allow conversion from 16-bit - src = dib; - break; - case FIT_RGB16: - // allow conversion from 48-bit RGB - src = dib; - break; - case FIT_RGBA16: - // allow conversion from 64-bit RGBA - src = dib; - break; - case FIT_FLOAT: - // allow conversion from 32-bit float - src = dib; - break; - case FIT_RGBF: - // allow conversion from 96-bit RGBF - src = dib; - break; - case FIT_RGBAF: - // RGBAF type : clone the src - return FreeImage_Clone(dib); - break; - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_RGBAF, width, height); - if(!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to RGBAF - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - switch(src_type) { - case FIT_BITMAP: - { - // calculate the number of bytes per pixel (4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const BYTE *src_pixel = (BYTE*)src_bits; - FIRGBAF *dst_pixel = (FIRGBAF*)dst_bits; - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel->red = (float)(src_pixel[FI_RGBA_RED]) / 255.0F; - dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255.0F; - dst_pixel->blue = (float)(src_pixel[FI_RGBA_BLUE]) / 255.0F; - dst_pixel->alpha = (float)(src_pixel[FI_RGBA_ALPHA]) / 255.0F; - - src_pixel += bytespp; - dst_pixel++; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_UINT16: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const WORD *src_pixel = (WORD*)src_bits; - FIRGBAF *dst_pixel = (FIRGBAF*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - const float dst_value = (float)src_pixel[x] / 65535.0F; - dst_pixel[x].red = dst_value; - dst_pixel[x].green = dst_value; - dst_pixel[x].blue = dst_value; - dst_pixel[x].alpha = 1.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGB16: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const FIRGB16 *src_pixel = (FIRGB16*)src_bits; - FIRGBAF *dst_pixel = (FIRGBAF*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x].red = (float)(src_pixel[x].red) / 65535.0F; - dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; - dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; - dst_pixel[x].alpha = 1.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBA16: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const FIRGBA16 *src_pixel = (FIRGBA16*)src_bits; - FIRGBAF *dst_pixel = (FIRGBAF*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x].red = (float)(src_pixel[x].red) / 65535.0F; - dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; - dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; - dst_pixel[x].alpha = (float)(src_pixel[x].alpha) / 65535.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_FLOAT: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const float *src_pixel = (float*)src_bits; - FIRGBAF *dst_pixel = (FIRGBAF*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert by copying greyscale channel to each R, G, B channels - // assume float values are in [0..1] - const float value = CLAMP(src_pixel[x], 0.0F, 1.0F); - dst_pixel[x].red = value; - dst_pixel[x].green = value; - dst_pixel[x].blue = value; - dst_pixel[x].alpha = 1.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBF: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const FIRGBF *src_pixel = (FIRGBF*)src_bits; - FIRGBAF *dst_pixel = (FIRGBAF*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert pixels directly, while adding a "dummy" alpha of 1.0 - dst_pixel[x].red = CLAMP(src_pixel[x].red, 0.0F, 1.0F); - dst_pixel[x].green = CLAMP(src_pixel[x].green, 0.0F, 1.0F); - dst_pixel[x].blue = CLAMP(src_pixel[x].blue, 0.0F, 1.0F); - dst_pixel[x].alpha = 1.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/AdvaImg/src/FreeImage/ConversionRGBF.cpp b/plugins/AdvaImg/src/FreeImage/ConversionRGBF.cpp deleted file mode 100644 index a30b36532e..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ConversionRGBF.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// smart convert X to RGBF -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToRGBF(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // allow conversion from 24- and 32-bit - const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); - if((color_type != FIC_RGB) && (color_type != FIC_RGBALPHA)) { - src = FreeImage_ConvertTo24Bits(dib); - if(!src) return NULL; - } else { - src = dib; - } - break; - } - case FIT_UINT16: - // allow conversion from 16-bit - src = dib; - break; - case FIT_RGB16: - // allow conversion from 48-bit RGB - src = dib; - break; - case FIT_RGBA16: - // allow conversion from 64-bit RGBA (ignore the alpha channel) - src = dib; - break; - case FIT_FLOAT: - // allow conversion from 32-bit float - src = dib; - break; - case FIT_RGBAF: - // allow conversion from 128-bit RGBAF - src = dib; - break; - case FIT_RGBF: - // RGBF type : clone the src - return FreeImage_Clone(dib); - break; - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_RGBF, width, height); - if(!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to RGBF - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - switch(src_type) { - case FIT_BITMAP: - { - // calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const BYTE *src_pixel = (BYTE*)src_bits; - FIRGBF *dst_pixel = (FIRGBF*)dst_bits; - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel->red = (float)(src_pixel[FI_RGBA_RED]) / 255.0F; - dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255.0F; - dst_pixel->blue = (float)(src_pixel[FI_RGBA_BLUE]) / 255.0F; - - src_pixel += bytespp; - dst_pixel ++; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_UINT16: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const WORD *src_pixel = (WORD*)src_bits; - FIRGBF *dst_pixel = (FIRGBF*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - const float dst_value = (float)src_pixel[x] / 65535.0F; - dst_pixel[x].red = dst_value; - dst_pixel[x].green = dst_value; - dst_pixel[x].blue = dst_value; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGB16: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const FIRGB16 *src_pixel = (FIRGB16*) src_bits; - FIRGBF *dst_pixel = (FIRGBF*) dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x].red = (float)(src_pixel[x].red) / 65535.0F; - dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; - dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBA16: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const FIRGBA16 *src_pixel = (FIRGBA16*) src_bits; - FIRGBF *dst_pixel = (FIRGBF*) dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x].red = (float)(src_pixel[x].red) / 65535.0F; - dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; - dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_FLOAT: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const float *src_pixel = (float*) src_bits; - FIRGBF *dst_pixel = (FIRGBF*) dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert by copying greyscale channel to each R, G, B channels - // assume float values are in [0..1] - const float value = CLAMP(src_pixel[x], 0.0F, 1.0F); - dst_pixel[x].red = value; - dst_pixel[x].green = value; - dst_pixel[x].blue = value; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBAF: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const FIRGBAF *src_pixel = (FIRGBAF*) src_bits; - FIRGBF *dst_pixel = (FIRGBF*) dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and skip alpha channel - dst_pixel[x].red = CLAMP(src_pixel[x].red, 0.0F, 1.0F); - dst_pixel[x].green = CLAMP(src_pixel[x].green, 0.0F, 1.0F); - dst_pixel[x].blue = CLAMP(src_pixel[x].blue, 0.0F, 1.0F); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/AdvaImg/src/FreeImage/ConversionType.cpp b/plugins/AdvaImg/src/FreeImage/ConversionType.cpp deleted file mode 100644 index 09286e9a99..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ConversionType.cpp +++ /dev/null @@ -1,699 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Tanner Helland (tannerhelland@users.sf.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- - -/** Convert a greyscale image of type Tsrc to type Tdst. - Conversion is done using standard C language casting convention. -*/ -template<class Tdst, class Tsrc> -class CONVERT_TYPE -{ -public: - FIBITMAP* convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type); -}; - -template<class Tdst, class Tsrc> FIBITMAP* -CONVERT_TYPE<Tdst, Tsrc>::convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type) { - - FIBITMAP *dst = NULL; - - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - unsigned bpp = FreeImage_GetBPP(src); - - // allocate dst image - - dst = FreeImage_AllocateT(dst_type, width, height, bpp, - FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src)); - if(!dst) return NULL; - - // convert from src_type to dst_type - - for(unsigned y = 0; y < height; y++) { - const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); - Tdst *dst_bits = reinterpret_cast<Tdst*>(FreeImage_GetScanLine(dst, y)); - - for(unsigned x = 0; x < width; x++) { - *dst_bits++ = static_cast<Tdst>(*src_bits++); - } - } - - return dst; -} - - -/** Convert a greyscale image of type Tsrc to a 8-bit grayscale dib. - Conversion is done using either a linear scaling from [min, max] to [0, 255] - or a rounding from src_pixel to (BYTE) MIN(255, MAX(0, q)) where int q = int(src_pixel + 0.5); -*/ -template<class Tsrc> -class CONVERT_TO_BYTE -{ -public: - FIBITMAP* convert(FIBITMAP *src, BOOL scale_linear); -}; - -template<class Tsrc> FIBITMAP* -CONVERT_TO_BYTE<Tsrc>::convert(FIBITMAP *src, BOOL scale_linear) { - FIBITMAP *dst = NULL; - unsigned x, y; - - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - - // allocate a 8-bit dib - - dst = FreeImage_AllocateT(FIT_BITMAP, width, height, 8, 0, 0, 0); - if(!dst) return NULL; - - // build a greyscale palette - RGBQUAD *pal = FreeImage_GetPalette(dst); - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = (BYTE)i; - pal[i].rgbGreen = (BYTE)i; - pal[i].rgbBlue = (BYTE)i; - } - - // convert the src image to dst - // (FIBITMAP are stored upside down) - if(scale_linear) { - Tsrc max, min; - double scale; - - // find the min and max value of the image - Tsrc l_min, l_max; - min = 255, max = 0; - for(y = 0; y < height; y++) { - Tsrc *bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); - MAXMIN(bits, width, l_max, l_min); - if(l_max > max) max = l_max; - if(l_min < min) min = l_min; - } - if(max == min) { - max = 255; min = 0; - } - - // compute the scaling factor - scale = 255 / (double)(max - min); - - // scale to 8-bit - for(y = 0; y < height; y++) { - Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); - BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - for(x = 0; x < width; x++) { - dst_bits[x] = (BYTE)( scale * (src_bits[x] - min) + 0.5); - } - } - } else { - for(y = 0; y < height; y++) { - Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); - BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - for(x = 0; x < width; x++) { - // rounding - int q = int(src_bits[x] + 0.5); - dst_bits[x] = (BYTE) MIN(255, MAX(0, q)); - } - } - } - - return dst; -} - -/** Convert a greyscale image of type Tsrc to a FICOMPLEX dib. -*/ -template<class Tsrc> -class CONVERT_TO_COMPLEX -{ -public: - FIBITMAP* convert(FIBITMAP *src); -}; - -template<class Tsrc> FIBITMAP* -CONVERT_TO_COMPLEX<Tsrc>::convert(FIBITMAP *src) { - FIBITMAP *dst = NULL; - - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - - // allocate dst image - - dst = FreeImage_AllocateT(FIT_COMPLEX, width, height); - if(!dst) return NULL; - - // convert from src_type to FIT_COMPLEX - - for(unsigned y = 0; y < height; y++) { - const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); - FICOMPLEX *dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y); - - for(unsigned x = 0; x < width; x++) { - dst_bits[x].r = (double)src_bits[x]; - dst_bits[x].i = 0; - } - } - - return dst; -} - -// ---------------------------------------------------------- - -// Convert from type BYTE to type X -CONVERT_TYPE<unsigned short, BYTE> convertByteToUShort; -CONVERT_TYPE<short, BYTE> convertByteToShort; -CONVERT_TYPE<DWORD, BYTE> convertByteToULong; -CONVERT_TYPE<LONG, BYTE> convertByteToLong; -CONVERT_TYPE<float, BYTE> convertByteToFloat; -CONVERT_TYPE<double, BYTE> convertByteToDouble; - -// Convert from type X to type BYTE -CONVERT_TO_BYTE<unsigned short> convertUShortToByte; -CONVERT_TO_BYTE<short> convertShortToByte; -CONVERT_TO_BYTE<DWORD> convertULongToByte; -CONVERT_TO_BYTE<LONG> convertLongToByte; -CONVERT_TO_BYTE<float> convertFloatToByte; -CONVERT_TO_BYTE<double> convertDoubleToByte; - -// Convert from type X to type float -CONVERT_TYPE<float, unsigned short> convertUShortToFloat; -CONVERT_TYPE<float, short> convertShortToFloat; -CONVERT_TYPE<float, DWORD> convertULongToFloat; -CONVERT_TYPE<float, LONG> convertLongToFloat; - -// Convert from type X to type double -CONVERT_TYPE<double, unsigned short> convertUShortToDouble; -CONVERT_TYPE<double, short> convertShortToDouble; -CONVERT_TYPE<double, DWORD> convertULongToDouble; -CONVERT_TYPE<double, LONG> convertLongToDouble; -CONVERT_TYPE<double, float> convertFloatToDouble; - -// Convert from type X to type FICOMPLEX -CONVERT_TO_COMPLEX<BYTE> convertByteToComplex; -CONVERT_TO_COMPLEX<unsigned short> convertUShortToComplex; -CONVERT_TO_COMPLEX<short> convertShortToComplex; -CONVERT_TO_COMPLEX<DWORD> convertULongToComplex; -CONVERT_TO_COMPLEX<LONG> convertLongToComplex; -CONVERT_TO_COMPLEX<float> convertFloatToComplex; -CONVERT_TO_COMPLEX<double> convertDoubleToComplex; - -// ---------------------------------------------------------- - -// ---------------------------------------------------------- -// smart convert X to standard FIBITMAP -// ---------------------------------------------------------- - -/** Convert image of any type to a standard 8-bit greyscale image. -For standard images, a clone of the input image is returned. -When the scale_linear parameter is TRUE, conversion is done by scaling linearly -each pixel to an integer value between [0..255]. When it is FALSE, conversion is done -by rounding each float pixel to an integer between [0..255]. -For complex images, the magnitude is extracted as a double image, then converted according to the scale parameter. -@param image Image to convert -@param scale_linear Linear scaling / rounding switch -*/ -FIBITMAP* DLL_CALLCONV -FreeImage_ConvertToStandardType(FIBITMAP *src, BOOL scale_linear) { - FIBITMAP *dst = NULL; - - if(!src) return NULL; - - // convert from src_type to FIT_BITMAP - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src); - - switch(src_type) { - case FIT_BITMAP: // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit - dst = FreeImage_Clone(src); - break; - case FIT_UINT16: // array of unsigned short: unsigned 16-bit - dst = convertUShortToByte.convert(src, scale_linear); - break; - case FIT_INT16: // array of short: signed 16-bit - dst = convertShortToByte.convert(src, scale_linear); - break; - case FIT_UINT32: // array of unsigned long: unsigned 32-bit - dst = convertULongToByte.convert(src, scale_linear); - break; - case FIT_INT32: // array of long: signed 32-bit - dst = convertLongToByte.convert(src, scale_linear); - break; - case FIT_FLOAT: // array of float: 32-bit - dst = convertFloatToByte.convert(src, scale_linear); - break; - case FIT_DOUBLE: // array of double: 64-bit - dst = convertDoubleToByte.convert(src, scale_linear); - break; - case FIT_COMPLEX: // array of FICOMPLEX: 2 x 64-bit - { - // Convert to type FIT_DOUBLE - FIBITMAP *dib_double = FreeImage_GetComplexChannel(src, FICC_MAG); - if(dib_double) { - // Convert to a standard bitmap (linear scaling) - dst = convertDoubleToByte.convert(dib_double, scale_linear); - // Free image of type FIT_DOUBLE - FreeImage_Unload(dib_double); - } - } - break; - case FIT_RGB16: // 48-bit RGB image: 3 x 16-bit - break; - case FIT_RGBA16: // 64-bit RGBA image: 4 x 16-bit - break; - case FIT_RGBF: // 96-bit RGB float image: 3 x 32-bit IEEE floating point - break; - case FIT_RGBAF: // 128-bit RGBA float image: 4 x 32-bit IEEE floating point - break; - } - - if(NULL == dst) { - FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, FIT_BITMAP); - } else { - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - } - - return dst; -} - - - -// ---------------------------------------------------------- -// smart convert X to Y -// ---------------------------------------------------------- - -FIBITMAP* DLL_CALLCONV -FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_linear) { - FIBITMAP *dst = NULL; - - if(!FreeImage_HasPixels(src)) return NULL; - - // convert from src_type to dst_type - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src); - - if(src_type == dst_type) { - return FreeImage_Clone(src); - } - - const unsigned src_bpp = FreeImage_GetBPP(src); - - switch(src_type) { - case FIT_BITMAP: - switch(dst_type) { - case FIT_UINT16: - dst = FreeImage_ConvertToUINT16(src); - break; - case FIT_INT16: - dst = (src_bpp == 8) ? convertByteToShort.convert(src, dst_type) : NULL; - break; - case FIT_UINT32: - dst = (src_bpp == 8) ? convertByteToULong.convert(src, dst_type) : NULL; - break; - case FIT_INT32: - dst = (src_bpp == 8) ? convertByteToLong.convert(src, dst_type) : NULL; - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - dst = (src_bpp == 8) ? convertByteToDouble.convert(src, dst_type) : NULL; - break; - case FIT_COMPLEX: - dst = (src_bpp == 8) ? convertByteToComplex.convert(src) : NULL; - break; - case FIT_RGB16: - dst = FreeImage_ConvertToRGB16(src); - break; - case FIT_RGBA16: - dst = FreeImage_ConvertToRGBA16(src); - break; - case FIT_RGBF: - dst = FreeImage_ConvertToRGBF(src); - break; - case FIT_RGBAF: - dst = FreeImage_ConvertToRGBAF(src); - break; - } - break; - case FIT_UINT16: - switch(dst_type) { - case FIT_BITMAP: - dst = FreeImage_ConvertToStandardType(src, scale_linear); - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - dst = convertUShortToDouble.convert(src, dst_type); - break; - case FIT_COMPLEX: - dst = convertUShortToComplex.convert(src); - break; - case FIT_RGB16: - dst = FreeImage_ConvertToRGB16(src); - break; - case FIT_RGBA16: - dst = FreeImage_ConvertToRGBA16(src); - break; - case FIT_RGBF: - dst = FreeImage_ConvertToRGBF(src); - break; - case FIT_RGBAF: - dst = FreeImage_ConvertToRGBAF(src); - break; - } - break; - case FIT_INT16: - switch(dst_type) { - case FIT_BITMAP: - dst = FreeImage_ConvertToStandardType(src, scale_linear); - break; - case FIT_UINT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = convertShortToFloat.convert(src, dst_type); - break; - case FIT_DOUBLE: - dst = convertShortToDouble.convert(src, dst_type); - break; - case FIT_COMPLEX: - dst = convertShortToComplex.convert(src); - break; - case FIT_RGB16: - break; - case FIT_RGBA16: - break; - case FIT_RGBF: - break; - case FIT_RGBAF: - break; - } - break; - case FIT_UINT32: - switch(dst_type) { - case FIT_BITMAP: - dst = FreeImage_ConvertToStandardType(src, scale_linear); - break; - case FIT_UINT16: - break; - case FIT_INT16: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = convertULongToFloat.convert(src, dst_type); - break; - case FIT_DOUBLE: - dst = convertULongToDouble.convert(src, dst_type); - break; - case FIT_COMPLEX: - dst = convertULongToComplex.convert(src); - break; - case FIT_RGB16: - break; - case FIT_RGBA16: - break; - case FIT_RGBF: - break; - case FIT_RGBAF: - break; - } - break; - case FIT_INT32: - switch(dst_type) { - case FIT_BITMAP: - dst = FreeImage_ConvertToStandardType(src, scale_linear); - break; - case FIT_UINT16: - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_FLOAT: - dst = convertLongToFloat.convert(src, dst_type); - break; - case FIT_DOUBLE: - dst = convertLongToDouble.convert(src, dst_type); - break; - case FIT_COMPLEX: - dst = convertLongToComplex.convert(src); - break; - case FIT_RGB16: - break; - case FIT_RGBA16: - break; - case FIT_RGBF: - break; - case FIT_RGBAF: - break; - } - break; - case FIT_FLOAT: - switch(dst_type) { - case FIT_BITMAP: - dst = FreeImage_ConvertToStandardType(src, scale_linear); - break; - case FIT_UINT16: - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_DOUBLE: - dst = convertFloatToDouble.convert(src, dst_type); - break; - case FIT_COMPLEX: - dst = convertFloatToComplex.convert(src); - break; - case FIT_RGB16: - break; - case FIT_RGBA16: - break; - case FIT_RGBF: - dst = FreeImage_ConvertToRGBF(src); - break; - case FIT_RGBAF: - dst = FreeImage_ConvertToRGBAF(src); - break; - } - break; - case FIT_DOUBLE: - switch(dst_type) { - case FIT_BITMAP: - dst = FreeImage_ConvertToStandardType(src, scale_linear); - break; - case FIT_UINT16: - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - break; - case FIT_COMPLEX: - dst = convertDoubleToComplex.convert(src); - break; - case FIT_RGB16: - break; - case FIT_RGBA16: - break; - case FIT_RGBF: - break; - case FIT_RGBAF: - break; - } - break; - case FIT_COMPLEX: - switch(dst_type) { - case FIT_BITMAP: - break; - case FIT_UINT16: - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - break; - case FIT_DOUBLE: - break; - case FIT_RGB16: - break; - case FIT_RGBA16: - break; - case FIT_RGBF: - break; - case FIT_RGBAF: - break; - } - break; - case FIT_RGB16: - switch(dst_type) { - case FIT_BITMAP: - dst = FreeImage_ConvertTo24Bits(src); - break; - case FIT_UINT16: - dst = FreeImage_ConvertToUINT16(src); - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - break; - case FIT_COMPLEX: - break; - case FIT_RGBA16: - dst = FreeImage_ConvertToRGBA16(src); - break; - case FIT_RGBF: - dst = FreeImage_ConvertToRGBF(src); - break; - case FIT_RGBAF: - dst = FreeImage_ConvertToRGBAF(src); - break; - } - break; - case FIT_RGBA16: - switch(dst_type) { - case FIT_BITMAP: - dst = FreeImage_ConvertTo32Bits(src); - break; - case FIT_UINT16: - dst = FreeImage_ConvertToUINT16(src); - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - break; - case FIT_COMPLEX: - break; - case FIT_RGB16: - dst = FreeImage_ConvertToRGB16(src); - break; - case FIT_RGBF: - dst = FreeImage_ConvertToRGBF(src); - break; - case FIT_RGBAF: - dst = FreeImage_ConvertToRGBAF(src); - break; - } - break; - case FIT_RGBF: - switch(dst_type) { - case FIT_BITMAP: - break; - case FIT_UINT16: - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - break; - case FIT_COMPLEX: - break; - case FIT_RGB16: - break; - case FIT_RGBA16: - break; - case FIT_RGBAF: - dst = FreeImage_ConvertToRGBAF(src); - break; - } - break; - case FIT_RGBAF: - switch(dst_type) { - case FIT_BITMAP: - break; - case FIT_UINT16: - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - break; - case FIT_COMPLEX: - break; - case FIT_RGB16: - break; - case FIT_RGBA16: - break; - case FIT_RGBF: - dst = FreeImage_ConvertToRGBF(src); - break; - } - break; - } - - if(NULL == dst) { - FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, dst_type); - } else { - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - } - - return dst; -} diff --git a/plugins/AdvaImg/src/FreeImage/ConversionUINT16.cpp b/plugins/AdvaImg/src/FreeImage/ConversionUINT16.cpp deleted file mode 100644 index 2de0f05ccc..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ConversionUINT16.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// smart convert X to UINT16 -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToUINT16(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // convert to greyscale if needed - if((FreeImage_GetBPP(dib) == 8) && (FreeImage_GetColorType(dib) == FIC_MINISBLACK)) { - src = dib; - } else { - src = FreeImage_ConvertToGreyscale(dib); - if(!src) return NULL; - } - break; - } - case FIT_UINT16: - // UINT16 type : clone the src - return FreeImage_Clone(dib); - break; - case FIT_RGB16: - // allow conversion from 48-bit RGB - src = dib; - break; - case FIT_RGBA16: - // allow conversion from 64-bit RGBA (ignore the alpha channel) - src = dib; - break; - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_UINT16, width, height); - if(!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to UINT16 - - switch(src_type) { - case FIT_BITMAP: - { - for(unsigned y = 0; y < height; y++) { - const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y); - WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - dst_bits[x] = src_bits[x] << 8; - } - } - } - break; - - case FIT_RGB16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGB16 *src_bits = (FIRGB16*)FreeImage_GetScanLine(src, y); - WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert to grey - dst_bits[x] = (WORD)LUMA_REC709(src_bits[x].red, src_bits[x].green, src_bits[x].blue); - } - } - } - break; - - case FIT_RGBA16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y); - WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert to grey - dst_bits[x] = (WORD)LUMA_REC709(src_bits[x].red, src_bits[x].green, src_bits[x].blue); - } - } - } - break; - - default: - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/AdvaImg/src/FreeImage/FreeImage.cpp b/plugins/AdvaImg/src/FreeImage/FreeImage.cpp deleted file mode 100644 index ac53449a14..0000000000 --- a/plugins/AdvaImg/src/FreeImage/FreeImage.cpp +++ /dev/null @@ -1,226 +0,0 @@ -// ========================================================== -// FreeImage implementation -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Karl-Heinz Bussian (khbussian@moss.de) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - - -#ifdef _WIN32 -#include <windows.h> -#endif - -#include "FreeImage.h" -#include "Utilities.h" - -//---------------------------------------------------------------------- - -static const char *s_copyright = "This program uses FreeImage, a free, open source image library supporting all common bitmap formats. See http://freeimage.sourceforge.net for details"; - -//---------------------------------------------------------------------- - -#if defined(_WIN32) && !defined(__MINGW32__) -#ifndef FREEIMAGE_LIB - -BOOL APIENTRY -DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { - switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH : - FreeImage_Initialise(FALSE); - break; - - case DLL_PROCESS_DETACH : - FreeImage_DeInitialise(); - break; - - case DLL_THREAD_ATTACH : - case DLL_THREAD_DETACH : - break; - } - - return TRUE; -} - -#endif // FREEIMAGE_LIB - -#else // !_WIN32 -#ifndef FREEIMAGE_LIB - -void FreeImage_SO_Initialise() __attribute__((constructor)); -void FreeImage_SO_DeInitialise() __attribute__((destructor)); - -void FreeImage_SO_Initialise() { - FreeImage_Initialise(FALSE); -} - -void FreeImage_SO_DeInitialise() { - FreeImage_DeInitialise(); -} -#endif // FREEIMAGE_LIB - -#endif // _WIN32 - -//---------------------------------------------------------------------- - -const char * DLL_CALLCONV -FreeImage_GetVersion() { - static char s_version[16]; - sprintf(s_version, "%d.%d.%d", FREEIMAGE_MAJOR_VERSION, FREEIMAGE_MINOR_VERSION, FREEIMAGE_RELEASE_SERIAL); - return s_version; -} - -const char * DLL_CALLCONV -FreeImage_GetCopyrightMessage() { - return s_copyright; -} - -//---------------------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_IsLittleEndian() { - union { - DWORD i; - BYTE c[4]; - } u; - u.i = 1; - return (u.c[0] != 0); -} - -//---------------------------------------------------------------------- - -static FreeImage_OutputMessageFunction freeimage_outputmessage_proc = NULL; -static FreeImage_OutputMessageFunctionStdCall freeimage_outputmessagestdcall_proc = NULL; - -void DLL_CALLCONV -FreeImage_SetOutputMessage(FreeImage_OutputMessageFunction omf) { - freeimage_outputmessage_proc = omf; -} - -void DLL_CALLCONV -FreeImage_SetOutputMessageStdCall(FreeImage_OutputMessageFunctionStdCall omf) { - freeimage_outputmessagestdcall_proc = omf; -} - -void DLL_CALLCONV -FreeImage_OutputMessageProc(int fif, const char *fmt, ...) { - const int MSG_SIZE = 512; // 512 bytes should be more than enough for a short message - - if ((fmt != NULL) && ((freeimage_outputmessage_proc != NULL) || (freeimage_outputmessagestdcall_proc != NULL))) { - char message[MSG_SIZE]; - memset(message, 0, MSG_SIZE); - - // initialize the optional parameter list - - va_list arg; - va_start(arg, fmt); - - // check the length of the format string - - int str_length = (int)( (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt) ); - - // parse the format string and put the result in 'message' - - for (int i = 0, j = 0; i < str_length; ++i) { - if (fmt[i] == '%') { - if (i + 1 < str_length) { - switch(tolower(fmt[i + 1])) { - case '%' : - message[j++] = '%'; - break; - - case 'o' : // octal numbers - { - char tmp[16]; - - _itoa(va_arg(arg, int), tmp, 8); - - strcat(message, tmp); - - j += (int)strlen(tmp); - - ++i; - - break; - } - - case 'i' : // decimal numbers - case 'd' : - { - char tmp[16]; - - _itoa(va_arg(arg, int), tmp, 10); - - strcat(message, tmp); - - j += (int)strlen(tmp); - - ++i; - - break; - } - - case 'x' : // hexadecimal numbers - { - char tmp[16]; - - _itoa(va_arg(arg, int), tmp, 16); - - strcat(message, tmp); - - j += (int)strlen(tmp); - - ++i; - - break; - } - - case 's' : // strings - { - char *tmp = va_arg(arg, char*); - - strcat(message, tmp); - - j += (int)strlen(tmp); - - ++i; - - break; - } - }; - } else { - message[j++] = fmt[i]; - } - } else { - message[j++] = fmt[i]; - }; - } - - // deinitialize the optional parameter list - - va_end(arg); - - // output the message to the user program - - if (freeimage_outputmessage_proc != NULL) - freeimage_outputmessage_proc((FREE_IMAGE_FORMAT)fif, message); - - if (freeimage_outputmessagestdcall_proc != NULL) - freeimage_outputmessagestdcall_proc((FREE_IMAGE_FORMAT)fif, message); - } -} diff --git a/plugins/AdvaImg/src/FreeImage/FreeImageIO.cpp b/plugins/AdvaImg/src/FreeImage/FreeImageIO.cpp deleted file mode 100644 index 83394f049c..0000000000 --- a/plugins/AdvaImg/src/FreeImage/FreeImageIO.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// ========================================================== -// Input/Output functions -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "FreeImageIO.h" - -// ===================================================================== -// File IO functions -// ===================================================================== - -unsigned DLL_CALLCONV -_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) { - return (unsigned)fread(buffer, size, count, (FILE *)handle); -} - -unsigned DLL_CALLCONV -_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) { - return (unsigned)fwrite(buffer, size, count, (FILE *)handle); -} - -int DLL_CALLCONV -_SeekProc(fi_handle handle, long offset, int origin) { - return fseek((FILE *)handle, offset, origin); -} - -long DLL_CALLCONV -_TellProc(fi_handle handle) { - return ftell((FILE *)handle); -} - -// ---------------------------------------------------------- - -void -SetDefaultIO(FreeImageIO *io) { - io->read_proc = _ReadProc; - io->seek_proc = _SeekProc; - io->tell_proc = _TellProc; - io->write_proc = _WriteProc; -} - -// ===================================================================== -// Memory IO functions -// ===================================================================== - -unsigned DLL_CALLCONV -_MemoryReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) { - unsigned x; - - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data); - - for(x = 0; x < count; x++) { - long remaining_bytes = mem_header->file_length - mem_header->current_position; - //if there isn't size bytes left to read, set pos to eof and return a short count - if( remaining_bytes < (long)size ) { - if(remaining_bytes > 0) { - memcpy( buffer, (char *)mem_header->data + mem_header->current_position, remaining_bytes ); - } - mem_header->current_position = mem_header->file_length; - break; - } - //copy size bytes count times - memcpy( buffer, (char *)mem_header->data + mem_header->current_position, size ); - mem_header->current_position += size; - buffer = (char *)buffer + size; - } - return x; -} - -unsigned DLL_CALLCONV -_MemoryWriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) { - void *newdata; - long newdatalen; - - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data); - - //double the data block size if we need to - while( (mem_header->current_position + (long)(size * count)) >= mem_header->data_length ) { - //if we are at or above 1G, we cant double without going negative - if( mem_header->data_length & 0x40000000 ) { - //max 2G - if( mem_header->data_length == 0x7FFFFFFF ) { - return 0; - } - newdatalen = 0x7FFFFFFF; - } else if( mem_header->data_length == 0 ) { - //default to 4K if nothing yet - newdatalen = 4096; - } else { - //double size - newdatalen = mem_header->data_length << 1; - } - newdata = realloc( mem_header->data, newdatalen ); - if( !newdata ) { - return 0; - } - mem_header->data = newdata; - mem_header->data_length = newdatalen; - } - memcpy( (char *)mem_header->data + mem_header->current_position, buffer, size * count ); - mem_header->current_position += size * count; - if( mem_header->current_position > mem_header->file_length ) { - mem_header->file_length = mem_header->current_position; - } - return count; -} - -int DLL_CALLCONV -_MemorySeekProc(fi_handle handle, long offset, int origin) { - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data); - - // you can use _MemorySeekProc to reposition the pointer anywhere in a file - // the pointer can also be positioned beyond the end of the file - - switch(origin) { //0 to filelen-1 are 'inside' the file - default: - case SEEK_SET: //can fseek() to 0-7FFFFFFF always - if( offset >= 0 ) { - mem_header->current_position = offset; - return 0; - } - break; - - case SEEK_CUR: - if( mem_header->current_position + offset >= 0 ) { - mem_header->current_position += offset; - return 0; - } - break; - - case SEEK_END: - if( mem_header->file_length + offset >= 0 ) { - mem_header->current_position = mem_header->file_length + offset; - return 0; - } - break; - } - - return -1; -} - -long DLL_CALLCONV -_MemoryTellProc(fi_handle handle) { - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data); - - return mem_header->current_position; -} - -// ---------------------------------------------------------- - -void -SetMemoryIO(FreeImageIO *io) { - io->read_proc = _MemoryReadProc; - io->seek_proc = _MemorySeekProc; - io->tell_proc = _MemoryTellProc; - io->write_proc = _MemoryWriteProc; -} diff --git a/plugins/AdvaImg/src/FreeImage/GetType.cpp b/plugins/AdvaImg/src/FreeImage/GetType.cpp deleted file mode 100644 index 0ac15fc2e6..0000000000 --- a/plugins/AdvaImg/src/FreeImage/GetType.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// ========================================================== -// GetType -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#include "FreeImage.h" -#include "Utilities.h" -#include "FreeImageIO.h" -#include "Plugin.h" - -// ---------------------------------------------------------- - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size) { - if (handle != NULL) { - int fif_count = FreeImage_GetFIFCount(); - - for (int i = 0; i < fif_count; ++i) { - FREE_IMAGE_FORMAT fif = (FREE_IMAGE_FORMAT)i; - if (FreeImage_Validate(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) - if (FreeImage_Validate(FIF_RAW, io, handle)) { - return FIF_RAW; - } - } - return fif; - } - } - } - - return FIF_UNKNOWN; -} - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_GetFileType(const char *filename, int size) { - FreeImageIO io; - SetDefaultIO(&io); - - FILE *handle = fopen(filename, "rb"); - - if (handle != NULL) { - FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)handle, size); - - fclose(handle); - - return format; - } - - return FIF_UNKNOWN; -} - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_GetFileTypeU(const wchar_t *filename, int size) { -#ifdef _WIN32 - FreeImageIO io; - SetDefaultIO(&io); - FILE *handle = _wfopen(filename, L"rb"); - - if (handle != NULL) { - FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)handle, size); - - fclose(handle); - - return format; - } -#endif - return FIF_UNKNOWN; -} - diff --git a/plugins/AdvaImg/src/FreeImage/Halftoning.cpp b/plugins/AdvaImg/src/FreeImage/Halftoning.cpp deleted file mode 100644 index bc9076c501..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Halftoning.cpp +++ /dev/null @@ -1,474 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// Thresholding and halftoning functions -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Dennis Lim (dlkj@users.sourceforge.net) -// - Thomas Chmielewski (Chmielewski.Thomas@oce.de) -// -// Main reference : Ulichney, R., Digital Halftoning, The MIT Press, Cambridge, MA, 1987 -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -static const int WHITE = 255; -static const int BLACK = 0; - -// Floyd & Steinberg error diffusion dithering -// This algorithm use the following filter -// * 7 -// 3 5 1 (1/16) -static FIBITMAP* FloydSteinberg(FIBITMAP *dib) { - -#define RAND(RN) (((seed = 1103515245 * seed + 12345) >> 12) % (RN)) -#define INITERR(X, Y) (((int) X) - (((int) Y) ? WHITE : BLACK) + ((WHITE/2)-((int)X)) / 2) - - int seed = 0; - int x, y, p, pixel, threshold, error; - int width, height, pitch; - BYTE *bits, *new_bits; - FIBITMAP *new_dib = NULL; - - // allocate a 8-bit DIB - width = FreeImage_GetWidth(dib); - height = FreeImage_GetHeight(dib); - pitch = FreeImage_GetPitch(dib); - new_dib = FreeImage_Allocate(width, height, 8); - if(NULL == new_dib) return NULL; - - // allocate space for error arrays - int *lerr = (int*)malloc (width * sizeof(int)); - int *cerr = (int*)malloc (width * sizeof(int)); - memset(lerr, 0, width * sizeof(int)); - memset(cerr, 0, width * sizeof(int)); - - // left border - error = 0; - for(y = 0; y < height; y++) { - bits = FreeImage_GetScanLine(dib, y); - new_bits = FreeImage_GetScanLine(new_dib, y); - - threshold = (WHITE / 2 + RAND(129) - 64); - pixel = bits[0] + error; - p = (pixel > threshold) ? WHITE : BLACK; - error = pixel - p; - new_bits[0] = (BYTE)p; - } - // right border - error = 0; - for(y = 0; y < height; y++) { - bits = FreeImage_GetScanLine(dib, y); - new_bits = FreeImage_GetScanLine(new_dib, y); - - threshold = (WHITE / 2 + RAND(129) - 64); - pixel = bits[width-1] + error; - p = (pixel > threshold) ? WHITE : BLACK; - error = pixel - p; - new_bits[width-1] = (BYTE)p; - } - // top border - bits = FreeImage_GetBits(dib); - new_bits = FreeImage_GetBits(new_dib); - error = 0; - for(x = 0; x < width; x++) { - threshold = (WHITE / 2 + RAND(129) - 64); - pixel = bits[x] + error; - p = (pixel > threshold) ? WHITE : BLACK; - error = pixel - p; - new_bits[x] = (BYTE)p; - lerr[x] = INITERR(bits[x], p); - } - - // interior bits - for(y = 1; y < height; y++) { - // scan left to right - bits = FreeImage_GetScanLine(dib, y); - new_bits = FreeImage_GetScanLine(new_dib, y); - - cerr[0] = INITERR(bits[0], new_bits[0]); - for(x = 1; x < width - 1; x++) { - error = (lerr[x-1] + 5 * lerr[x] + 3 * lerr[x+1] + 7 * cerr[x-1]) / 16; - pixel = bits[x] + error; - if(pixel > (WHITE / 2)) { - new_bits[x] = WHITE; - cerr[x] = pixel - WHITE; - } else { - new_bits[x] = BLACK; - cerr[x] = pixel - BLACK; - } - } - // set errors for ends of the row - cerr[0] = INITERR (bits[0], new_bits[0]); - cerr[width - 1] = INITERR (bits[width - 1], new_bits[width - 1]); - - // swap error buffers - int *terr = lerr; lerr = cerr; cerr = terr; - } - - free(lerr); - free(cerr); - - return new_dib; -} - -// ========================================================== -// Bayer ordered dispersed dot dithering -// - -// Function taken from "Ordered Dithering, Stephen Hawley, Graphics Gems, Academic Press, 1990" -// This function is used to generate a Bayer dithering matrice whose dimension are 2^size by 2^size -// -static int dithervalue(int x, int y, int size) { - int d = 0; - /* - * calculate the dither value at a particular - * (x, y) over the size of the matrix. - */ - while (size-->0) { - /* Think of d as the density. At every iteration, - * d is shifted left one and a new bit is put in the - * low bit based on x and y. If x is odd and y is even, - * or x is even and y is odd, a bit is put in. This - * generates the checkerboard seen in dithering. - * This quantity is shifted left again and the low bit of - * y is added in. - * This whole thing interleaves a checkerboard bit pattern - * and y's bits, which is the value you want. - */ - d = (d <<1 | (x&1 ^ y&1))<<1 | y&1; - x >>= 1; - y >>= 1; - } - return d; -} - -// Ordered dithering with a Bayer matrix of size 2^order by 2^order -// -static FIBITMAP* OrderedDispersedDot(FIBITMAP *dib, int order) { - int x, y; - int width, height; - BYTE *bits, *new_bits; - FIBITMAP *new_dib = NULL; - - // allocate a 8-bit DIB - width = FreeImage_GetWidth(dib); - height = FreeImage_GetHeight(dib); - new_dib = FreeImage_Allocate(width, height, 8); - if(NULL == new_dib) return NULL; - - // build the dithering matrix - int l = (1 << order); // square of dither matrix order; the dimensions of the matrix - BYTE *matrix = (BYTE*)malloc(l*l * sizeof(BYTE)); - for(int i = 0; i < l*l; i++) { - // according to "Purdue University: Digital Image Processing Laboratory: Image Halftoning, April 30th, 2006 - matrix[i] = (BYTE)( 255 * (((double)dithervalue(i / l, i % l, order) + 0.5) / (l*l)) ); - } - - // perform the dithering - for(y = 0; y < height; y++) { - // scan left to right - bits = FreeImage_GetScanLine(dib, y); - new_bits = FreeImage_GetScanLine(new_dib, y); - for(x = 0; x < width; x++) { - if(bits[x] > matrix[(x % l) + l * (y % l)]) { - new_bits[x] = WHITE; - } else { - new_bits[x] = BLACK; - } - } - } - - free(matrix); - - return new_dib; -} - -// ========================================================== -// Ordered clustered dot dithering -// - -// NB : The predefined dither matrices are the same as matrices used in -// the Netpbm package (http://netpbm.sourceforge.net) and are defined in Ulichney's book. -// See also : The newsprint web site at http://www.cl.cam.ac.uk/~and1000/newsprint/ -// for more technical info on this dithering technique -// -static FIBITMAP* OrderedClusteredDot(FIBITMAP *dib, int order) { - // Order-3 clustered dithering matrix. - int cluster3[] = { - 9,11,10, 8, 6, 7, - 12,17,16, 5, 0, 1, - 13,14,15, 4, 3, 2, - 8, 6, 7, 9,11,10, - 5, 0, 1,12,17,16, - 4, 3, 2,13,14,15 - }; - - // Order-4 clustered dithering matrix. - int cluster4[] = { - 18,20,19,16,13,11,12,15, - 27,28,29,22, 4, 3, 2, 9, - 26,31,30,21, 5, 0, 1,10, - 23,25,24,17, 8, 6, 7,14, - 13,11,12,15,18,20,19,16, - 4, 3, 2, 9,27,28,29,22, - 5, 0, 1,10,26,31,30,21, - 8, 6, 7,14,23,25,24,17 - }; - - // Order-8 clustered dithering matrix. - int cluster8[] = { - 64, 69, 77, 87, 86, 76, 68, 67, 63, 58, 50, 40, 41, 51, 59, 60, - 70, 94,100,109,108, 99, 93, 75, 57, 33, 27, 18, 19, 28, 34, 52, - 78,101,114,116,115,112, 98, 83, 49, 26, 13, 11, 12, 15, 29, 44, - 88,110,123,124,125,118,107, 85, 39, 17, 4, 3, 2, 9, 20, 42, - 89,111,122,127,126,117,106, 84, 38, 16, 5, 0, 1, 10, 21, 43, - 79,102,119,121,120,113, 97, 82, 48, 25, 8, 6, 7, 14, 30, 45, - 71, 95,103,104,105, 96, 92, 74, 56, 32, 24, 23, 22, 31, 35, 53, - 65, 72, 80, 90, 91, 81, 73, 66, 62, 55, 47, 37, 36, 46, 54, 61, - 63, 58, 50, 40, 41, 51, 59, 60, 64, 69, 77, 87, 86, 76, 68, 67, - 57, 33, 27, 18, 19, 28, 34, 52, 70, 94,100,109,108, 99, 93, 75, - 49, 26, 13, 11, 12, 15, 29, 44, 78,101,114,116,115,112, 98, 83, - 39, 17, 4, 3, 2, 9, 20, 42, 88,110,123,124,125,118,107, 85, - 38, 16, 5, 0, 1, 10, 21, 43, 89,111,122,127,126,117,106, 84, - 48, 25, 8, 6, 7, 14, 30, 45, 79,102,119,121,120,113, 97, 82, - 56, 32, 24, 23, 22, 31, 35, 53, 71, 95,103,104,105, 96, 92, 74, - 62, 55, 47, 37, 36, 46, 54, 61, 65, 72, 80, 90, 91, 81, 73, 66 - }; - - int x, y, pixel; - int width, height; - BYTE *bits, *new_bits; - FIBITMAP *new_dib = NULL; - - // allocate a 8-bit DIB - width = FreeImage_GetWidth(dib); - height = FreeImage_GetHeight(dib); - new_dib = FreeImage_Allocate(width, height, 8); - if(NULL == new_dib) return NULL; - - // select the dithering matrix - int *matrix = NULL; - switch(order) { - case 3: - matrix = &cluster3[0]; - break; - case 4: - matrix = &cluster4[0]; - break; - case 8: - matrix = &cluster8[0]; - break; - default: - return NULL; - } - - // scale the dithering matrix - int l = 2 * order; - int scale = 256 / (l * order); - for(y = 0; y < l; y++) { - for(x = 0; x < l; x++) { - matrix[y*l + x] *= scale; - } - } - - // perform the dithering - for(y = 0; y < height; y++) { - // scan left to right - bits = FreeImage_GetScanLine(dib, y); - new_bits = FreeImage_GetScanLine(new_dib, y); - for(x = 0; x < width; x++) { - pixel = bits[x]; - if(pixel >= matrix[(y % l) + l * (x % l)]) { - new_bits[x] = WHITE; - } else { - new_bits[x] = BLACK; - } - } - } - - return new_dib; -} - - -// ========================================================== -// Halftoning function -// -FIBITMAP * DLL_CALLCONV -FreeImage_Dither(FIBITMAP *dib, FREE_IMAGE_DITHER algorithm) { - FIBITMAP *input = NULL, *dib8 = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - const unsigned bpp = FreeImage_GetBPP(dib); - - if(bpp == 1) { - // Just clone the dib and adjust the palette if needed - FIBITMAP *new_dib = FreeImage_Clone(dib); - if(NULL == new_dib) return NULL; - if(FreeImage_GetColorType(new_dib) == FIC_PALETTE) { - // Build a monochrome palette - RGBQUAD *pal = FreeImage_GetPalette(new_dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - } - return new_dib; - } - - // Convert the input dib to a 8-bit greyscale dib - // - switch(bpp) { - case 8: - if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) { - input = dib; - } else { - input = FreeImage_ConvertToGreyscale(dib); - } - break; - case 4: - case 16: - case 24: - case 32: - input = FreeImage_ConvertToGreyscale(dib); - break; - } - if(NULL == input) return NULL; - - // Apply the dithering algorithm - switch(algorithm) { - case FID_FS: - dib8 = FloydSteinberg(input); - break; - case FID_BAYER4x4: - dib8 = OrderedDispersedDot(input, 2); - break; - case FID_BAYER8x8: - dib8 = OrderedDispersedDot(input, 3); - break; - case FID_BAYER16x16: - dib8 = OrderedDispersedDot(input, 4); - break; - case FID_CLUSTER6x6: - dib8 = OrderedClusteredDot(input, 3); - break; - case FID_CLUSTER8x8: - dib8 = OrderedClusteredDot(input, 4); - break; - case FID_CLUSTER16x16: - dib8 = OrderedClusteredDot(input, 8); - break; - } - if(input != dib) { - FreeImage_Unload(input); - } - - // Build a greyscale palette (needed by threshold) - RGBQUAD *grey_pal = FreeImage_GetPalette(dib8); - for(int i = 0; i < 256; i++) { - grey_pal[i].rgbRed = (BYTE)i; - grey_pal[i].rgbGreen = (BYTE)i; - grey_pal[i].rgbBlue = (BYTE)i; - } - - // Convert to 1-bit - FIBITMAP *new_dib = FreeImage_Threshold(dib8, 128); - FreeImage_Unload(dib8); - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - return new_dib; -} - -// ========================================================== -// Thresholding function -// -FIBITMAP * DLL_CALLCONV -FreeImage_Threshold(FIBITMAP *dib, BYTE T) { - FIBITMAP *dib8 = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - const unsigned bpp = FreeImage_GetBPP(dib); - - if(bpp == 1) { - // Just clone the dib and adjust the palette if needed - FIBITMAP *new_dib = FreeImage_Clone(dib); - if(NULL == new_dib) return NULL; - if(FreeImage_GetColorType(new_dib) == FIC_PALETTE) { - // Build a monochrome palette - RGBQUAD *pal = FreeImage_GetPalette(new_dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - } - return new_dib; - } - - // Convert the input dib to a 8-bit greyscale dib - // - switch(bpp) { - case 8: - if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) { - dib8 = dib; - } else { - dib8 = FreeImage_ConvertToGreyscale(dib); - } - break; - case 4: - case 16: - case 24: - case 32: - dib8 = FreeImage_ConvertToGreyscale(dib); - break; - } - if(NULL == dib8) return NULL; - - // Allocate a new 1-bit DIB - int width = FreeImage_GetWidth(dib); - int height = FreeImage_GetHeight(dib); - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 1); - if(NULL == new_dib) return NULL; - // Build a monochrome palette - RGBQUAD *pal = FreeImage_GetPalette(new_dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - - // Perform the thresholding - // - for(int y = 0; y < height; y++) { - BYTE *bits8 = FreeImage_GetScanLine(dib8, y); - BYTE *bits1 = FreeImage_GetScanLine(new_dib, y); - for(int x = 0; x < width; x++) { - if(bits8[x] < T) { - // Set bit(x, y) to 0 - bits1[x >> 3] &= (0xFF7F >> (x & 0x7)); - } else { - // Set bit(x, y) to 1 - bits1[x >> 3] |= (0x80 >> (x & 0x7)); - } - } - } - if(dib8 != dib) { - FreeImage_Unload(dib8); - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(new_dib, dib); - - return new_dib; -} - diff --git a/plugins/AdvaImg/src/FreeImage/J2KHelper.cpp b/plugins/AdvaImg/src/FreeImage/J2KHelper.cpp deleted file mode 100644 index 49bf9290d4..0000000000 --- a/plugins/AdvaImg/src/FreeImage/J2KHelper.cpp +++ /dev/null @@ -1,591 +0,0 @@ -// ========================================================== -// JPEG2000 helpers -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "../LibOpenJPEG/openjpeg.h" -#include "J2KHelper.h" - -// -------------------------------------------------------------------------- - -static OPJ_UINT64 -_LengthProc(J2KFIO_t *fio) { - long start_pos = fio->io->tell_proc(fio->handle); - fio->io->seek_proc(fio->handle, 0, SEEK_END); - unsigned file_length = fio->io->tell_proc(fio->handle) - start_pos; - fio->io->seek_proc(fio->handle, start_pos, SEEK_SET); - return (OPJ_UINT64)file_length; -} - -static OPJ_SIZE_T -_ReadProc(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { - J2KFIO_t *fio = (J2KFIO_t*)p_user_data; - OPJ_SIZE_T l_nb_read = fio->io->read_proc(p_buffer, 1, (unsigned)p_nb_bytes, fio->handle); - return l_nb_read ? l_nb_read : (OPJ_SIZE_T)-1; -} - -static OPJ_SIZE_T -_WriteProc(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { - J2KFIO_t *fio = (J2KFIO_t*)p_user_data; - return fio->io->write_proc(p_buffer, 1, (unsigned)p_nb_bytes, fio->handle); -} - -static OPJ_OFF_T -_SkipProc(OPJ_OFF_T p_nb_bytes, void *p_user_data) { - J2KFIO_t *fio = (J2KFIO_t*)p_user_data; - if( fio->io->seek_proc(fio->handle, (long)p_nb_bytes, SEEK_CUR) ) { - return -1; - } - return p_nb_bytes; -} - -static OPJ_BOOL -_SeekProc(OPJ_OFF_T p_nb_bytes, FILE * p_user_data) { - J2KFIO_t *fio = (J2KFIO_t*)p_user_data; - if( fio->io->seek_proc(fio->handle, (long)p_nb_bytes, SEEK_SET) ) { - return OPJ_FALSE; - } - return OPJ_TRUE; -} - -// -------------------------------------------------------------------------- - -J2KFIO_t* -opj_freeimage_stream_create(FreeImageIO *io, fi_handle handle, BOOL bRead) { - if(!handle) { - return NULL; - } - J2KFIO_t *fio = (J2KFIO_t*)malloc(sizeof(J2KFIO_t)); - if(fio) { - fio->io = io; - fio->handle = handle; - - opj_stream_t *l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, bRead ? OPJ_TRUE : OPJ_FALSE); - if (l_stream) { - opj_stream_set_user_data(l_stream, fio, NULL); - opj_stream_set_user_data_length(l_stream, _LengthProc(fio)); - opj_stream_set_read_function(l_stream, (opj_stream_read_fn)_ReadProc); - opj_stream_set_write_function(l_stream, (opj_stream_write_fn)_WriteProc); - opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn)_SkipProc); - opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn)_SeekProc); - fio->stream = l_stream; - return fio; - } else { - free(fio); - } - } - - return NULL; -} - -void -opj_freeimage_stream_destroy(J2KFIO_t* fio) { - if(fio) { - if(fio->stream) { - opj_stream_destroy(fio->stream); - } - free(fio); - } -} - -// -------------------------------------------------------------------------- - -/** -Divide an integer by a power of 2 and round upwards -@return Returns a divided by 2^b -*/ -static int int_ceildivpow2(int a, int b) { - return (a + (1 << b) - 1) >> b; -} - -/** -Convert a OpenJPEG image to a FIBITMAP -@param format_id Plugin ID -@param image OpenJPEG image -@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP -@return Returns the converted image if successful, returns NULL otherwise -*/ -FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image, BOOL header_only) { - FIBITMAP *dib = NULL; - - try { - // compute image width and height - - //int w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx); - int wr = image->comps[0].w; - int wrr = int_ceildivpow2(image->comps[0].w, image->comps[0].factor); - - //int h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy); - //int hr = image->comps[0].h; - int hrr = int_ceildivpow2(image->comps[0].h, image->comps[0].factor); - - // check the number of components - - int numcomps = image->numcomps; - - BOOL bIsValid = TRUE; - for(int c = 0; c < numcomps - 1; c++) { - if( (image->comps[c].dx == image->comps[c+1].dx) && - (image->comps[c].dy == image->comps[c+1].dy) && - (image->comps[c].prec == image->comps[c+1].prec) ) { - continue; - } else { - bIsValid = FALSE; - break; - } - } - bIsValid &= ((numcomps == 1) || (numcomps == 3) || (numcomps == 4)); - if(!bIsValid) { - if(numcomps) { - FreeImage_OutputMessageProc(format_id, "Warning: image contains %d greyscale components. Only the first will be loaded.\n", numcomps); - numcomps = 1; - } else { - // unknown type - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - } - - // create a new DIB - - if(image->comps[0].prec <= 8) { - switch(numcomps) { - case 1: - dib = FreeImage_AllocateHeader(header_only, wrr, hrr, 8); - break; - case 3: - dib = FreeImage_AllocateHeader(header_only, wrr, hrr, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - break; - case 4: - dib = FreeImage_AllocateHeader(header_only, wrr, hrr, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - break; - } - } else if(image->comps[0].prec <= 16) { - switch(numcomps) { - case 1: - dib = FreeImage_AllocateHeaderT(header_only, FIT_UINT16, wrr, hrr); - break; - case 3: - dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, wrr, hrr); - break; - case 4: - dib = FreeImage_AllocateHeaderT(header_only, FIT_RGBA16, wrr, hrr); - break; - } - } else { - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // "header only" FIBITMAP ? - if(header_only) { - return dib; - } - - if(image->comps[0].prec <= 8) { - if(numcomps == 1) { - // 8-bit greyscale - // ---------------------------------------------------------- - - // build a greyscale palette - - RGBQUAD *pal = FreeImage_GetPalette(dib); - for (int i = 0; i < 256; i++) { - pal[i].rgbRed = (BYTE)i; - pal[i].rgbGreen = (BYTE)i; - pal[i].rgbBlue = (BYTE)i; - } - - // load pixel data - - unsigned pixel_count = 0; - - for(int y = 0; y < hrr; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y); - - for(int x = 0; x < wrr; x++) { - const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr; - - int index = image->comps[0].data[pixel_pos]; - index += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); - - bits[x] = (BYTE)index; - - pixel_count++; - } - } - } - else if(numcomps == 3) { - - // 24-bit RGB - // ---------------------------------------------------------- - - // load pixel data - - unsigned pixel_count = 0; - - for(int y = 0; y < hrr; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y); - - for(int x = 0; x < wrr; x++) { - const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr; - - int r = image->comps[0].data[pixel_pos]; - r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); - - int g = image->comps[1].data[pixel_pos]; - g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); - - int b = image->comps[2].data[pixel_pos]; - b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); - - bits[FI_RGBA_RED] = (BYTE)r; - bits[FI_RGBA_GREEN] = (BYTE)g; - bits[FI_RGBA_BLUE] = (BYTE)b; - bits += 3; - - pixel_count++; - } - } - } - else if(numcomps == 4) { - - // 32-bit RGBA - // ---------------------------------------------------------- - - // load pixel data - - unsigned pixel_count = 0; - - for(int y = 0; y < hrr; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y); - - for(int x = 0; x < wrr; x++) { - const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr; - - int r = image->comps[0].data[pixel_pos]; - r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); - - int g = image->comps[1].data[pixel_pos]; - g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); - - int b = image->comps[2].data[pixel_pos]; - b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); - - int a = image->comps[3].data[pixel_pos]; - a += (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0); - - bits[FI_RGBA_RED] = (BYTE)r; - bits[FI_RGBA_GREEN] = (BYTE)g; - bits[FI_RGBA_BLUE] = (BYTE)b; - bits[FI_RGBA_ALPHA] = (BYTE)a; - bits += 4; - - pixel_count++; - } - } - } - } - else if(image->comps[0].prec <= 16) { - if(numcomps == 1) { - // 16-bit greyscale - // ---------------------------------------------------------- - - // load pixel data - - unsigned pixel_count = 0; - - for(int y = 0; y < hrr; y++) { - WORD *bits = (WORD*)FreeImage_GetScanLine(dib, hrr - 1 - y); - - for(int x = 0; x < wrr; x++) { - const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr; - - int index = image->comps[0].data[pixel_pos]; - index += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); - - bits[x] = (WORD)index; - - pixel_count++; - } - } - } - else if(numcomps == 3) { - - // 48-bit RGB - // ---------------------------------------------------------- - - // load pixel data - - unsigned pixel_count = 0; - - for(int y = 0; y < hrr; y++) { - FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, hrr - 1 - y); - - for(int x = 0; x < wrr; x++) { - const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr; - - int r = image->comps[0].data[pixel_pos]; - r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); - - int g = image->comps[1].data[pixel_pos]; - g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); - - int b = image->comps[2].data[pixel_pos]; - b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); - - bits[x].red = (WORD)r; - bits[x].green = (WORD)g; - bits[x].blue = (WORD)b; - - pixel_count++; - } - } - } - else if(numcomps == 4) { - - // 64-bit RGBA - // ---------------------------------------------------------- - - // load pixel data - - unsigned pixel_count = 0; - - for(int y = 0; y < hrr; y++) { - FIRGBA16 *bits = (FIRGBA16*)FreeImage_GetScanLine(dib, hrr - 1 - y); - - for(int x = 0; x < wrr; x++) { - const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr; - - int r = image->comps[0].data[pixel_pos]; - r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); - - int g = image->comps[1].data[pixel_pos]; - g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); - - int b = image->comps[2].data[pixel_pos]; - b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); - - int a = image->comps[3].data[pixel_pos]; - a += (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0); - - bits[x].red = (WORD)r; - bits[x].green = (WORD)g; - bits[x].blue = (WORD)b; - bits[x].alpha = (WORD)a; - - pixel_count++; - } - } - } - } - - return dib; - - } catch(const char *text) { - if(dib) FreeImage_Unload(dib); - FreeImage_OutputMessageProc(format_id, text); - return NULL; - } - -} - -/** -Convert a FIBITMAP to a OpenJPEG image -@param format_id Plugin ID -@param dib FreeImage image -@param parameters Compression parameters -@return Returns the converted image if successful, returns NULL otherwise -*/ -opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters) { - int prec, numcomps, x, y, index; - OPJ_COLOR_SPACE color_space; - opj_image_cmptparm_t cmptparm[4]; // maximum of 4 components - opj_image_t *image = NULL; // image to encode - - try { - int w = FreeImage_GetWidth(dib); - int h = FreeImage_GetHeight(dib); - - // get image characteristics - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - if(image_type == FIT_BITMAP) { - // standard image ... - prec = 8; - switch(FreeImage_GetColorType(dib)) { - case FIC_MINISBLACK: - numcomps = 1; - color_space = OPJ_CLRSPC_GRAY; - break; - case FIC_RGB: - if(FreeImage_GetBPP(dib) == 32) { - // 32-bit image with a fully opaque layer - numcomps = 4; - color_space = OPJ_CLRSPC_SRGB; - } else { - // 24-bit image - numcomps = 3; - color_space = OPJ_CLRSPC_SRGB; - } - break; - case FIC_RGBALPHA: - numcomps = 4; - color_space = OPJ_CLRSPC_SRGB; - break; - default: - return NULL; - } - } else { - // HDR image ... - prec = 16; - switch(image_type) { - case FIT_UINT16: - numcomps = 1; - color_space = OPJ_CLRSPC_GRAY; - break; - case FIT_RGB16: - numcomps = 3; - color_space = OPJ_CLRSPC_SRGB; - break; - case FIT_RGBA16: - numcomps = 4; - color_space = OPJ_CLRSPC_SRGB; - break; - default: - return NULL; - } - } - - // initialize image components - memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t)); - for(int i = 0; i < numcomps; i++) { - cmptparm[i].dx = parameters->subsampling_dx; - cmptparm[i].dy = parameters->subsampling_dy; - cmptparm[i].w = w; - cmptparm[i].h = h; - cmptparm[i].prec = prec; - cmptparm[i].bpp = prec; - cmptparm[i].sgnd = 0; - } - // create the image - image = opj_image_create(numcomps, &cmptparm[0], color_space); - if(!image) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // set image offset and reference grid - image->x0 = parameters->image_offset_x0; - image->y0 = parameters->image_offset_y0; - image->x1 = parameters->image_offset_x0 + (w - 1) * parameters->subsampling_dx + 1; - image->y1 = parameters->image_offset_y0 + (h - 1) * parameters->subsampling_dy + 1; - - // set image data - if(prec == 8) { - switch(numcomps) { - case 1: - index = 0; - for(y = 0; y < h; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y); - for(x = 0; x < w; x++) { - image->comps[0].data[index] = bits[x]; - index++; - } - } - break; - case 3: - index = 0; - for(y = 0; y < h; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y); - for(x = 0; x < w; x++) { - image->comps[0].data[index] = bits[FI_RGBA_RED]; - image->comps[1].data[index] = bits[FI_RGBA_GREEN]; - image->comps[2].data[index] = bits[FI_RGBA_BLUE]; - bits += 3; - index++; - } - } - break; - case 4: - index = 0; - for(y = 0; y < h; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y); - for(x = 0; x < w; x++) { - image->comps[0].data[index] = bits[FI_RGBA_RED]; - image->comps[1].data[index] = bits[FI_RGBA_GREEN]; - image->comps[2].data[index] = bits[FI_RGBA_BLUE]; - image->comps[3].data[index] = bits[FI_RGBA_ALPHA]; - bits += 4; - index++; - } - } - break; - } - } - else if(prec == 16) { - switch(numcomps) { - case 1: - index = 0; - for(y = 0; y < h; y++) { - WORD *bits = (WORD*)FreeImage_GetScanLine(dib, h - 1 - y); - for(x = 0; x < w; x++) { - image->comps[0].data[index] = bits[x]; - index++; - } - } - break; - case 3: - index = 0; - for(y = 0; y < h; y++) { - FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, h - 1 - y); - for(x = 0; x < w; x++) { - image->comps[0].data[index] = bits[x].red; - image->comps[1].data[index] = bits[x].green; - image->comps[2].data[index] = bits[x].blue; - index++; - } - } - break; - case 4: - index = 0; - for(y = 0; y < h; y++) { - FIRGBA16 *bits = (FIRGBA16*)FreeImage_GetScanLine(dib, h - 1 - y); - for(x = 0; x < w; x++) { - image->comps[0].data[index] = bits[x].red; - image->comps[1].data[index] = bits[x].green; - image->comps[2].data[index] = bits[x].blue; - image->comps[3].data[index] = bits[x].alpha; - index++; - } - } - break; - } - } - - return image; - - } catch (const char *text) { - if(image) opj_image_destroy(image); - FreeImage_OutputMessageProc(format_id, text); - return NULL; - } -} diff --git a/plugins/AdvaImg/src/FreeImage/J2KHelper.h b/plugins/AdvaImg/src/FreeImage/J2KHelper.h deleted file mode 100644 index a8121f164e..0000000000 --- a/plugins/AdvaImg/src/FreeImage/J2KHelper.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef J2K_HELPER_H -#define J2K_HELPER_H - -// ========================================================== -// Helper functions (see J2KHelper.cpp) -// ========================================================== - -/** -FreeImageIO wrapper -*/ -typedef struct tagJ2KFIO_t { - FreeImageIO *io; //! FreeImage IO - fi_handle handle; //! FreeImage handle - opj_stream_t *stream; //! OpenJPEG stream -} J2KFIO_t; - -/** -Stream constructor -*/ -J2KFIO_t* opj_freeimage_stream_create(FreeImageIO *io, fi_handle handle, BOOL bRead); - -/** -Stream destructor -*/ -void opj_freeimage_stream_destroy(J2KFIO_t* fio); - -/** -Conversion opj_image_t => FIBITMAP -*/ -FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image, BOOL header_only); -/** -Conversion FIBITMAP => opj_image_t -*/ -opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters); - -#endif // J2K_HELPER_H
\ No newline at end of file diff --git a/plugins/AdvaImg/src/FreeImage/LFPQuantizer.cpp b/plugins/AdvaImg/src/FreeImage/LFPQuantizer.cpp deleted file mode 100644 index 8b592c30f1..0000000000 --- a/plugins/AdvaImg/src/FreeImage/LFPQuantizer.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// ========================================================== -// LFPQuantizer class implementation -// -// Design and implementation by -// - Carsten Klein (cklein05@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "Quantizers.h" -#include "FreeImage.h" -#include "Utilities.h" - -LFPQuantizer::LFPQuantizer(unsigned PaletteSize) : - m_size(0), m_limit(PaletteSize), m_index(0) { - m_map = new MapEntry[MAP_SIZE]; - memset(m_map, 0xFF, MAP_SIZE * sizeof(MapEntry)); -} - -LFPQuantizer::~LFPQuantizer() { - delete[] m_map; -} - -FIBITMAP* LFPQuantizer::Quantize(FIBITMAP *dib, int ReserveSize, RGBQUAD *ReservePalette) { - - if (ReserveSize > 0 && ReservePalette != NULL) { - AddReservePalette(ReservePalette, ReserveSize); - } - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - - FIBITMAP *dib8 = FreeImage_Allocate(width, height, 8); - if (dib8 == NULL) { - return NULL; - } - - const unsigned src_pitch = FreeImage_GetPitch(dib); - const unsigned dst_pitch = FreeImage_GetPitch(dib8); - - const BYTE * const src_bits = FreeImage_GetBits(dib); - BYTE * const dst_bits = FreeImage_GetBits(dib8); - - unsigned last_color = -1; - int last_index = 0; - - if (FreeImage_GetBPP(dib) == 24) { - - // Getting the source pixel as an unsigned int is much faster than - // working with FI_RGBA_xxx and shifting. However, this may fail - // for the very last pixel, since its rgbReserved member (alpha) - // may actually point to an address beyond the bitmap's memory. So, - // we do not process the last scanline in the first loop. - - // Process all but the last scanline. - for (unsigned y = 0; y < height - 1; ++y) { - BYTE *dst_line = dst_bits + y * dst_pitch; - const BYTE *src_line = src_bits + y * src_pitch; - for (unsigned x = 0; x < width; ++x) { - const unsigned color = *((unsigned *) src_line) & 0x00FFFFFF; - if (color != last_color) { - last_color = color; - last_index = GetIndexForColor(color); - if (last_index == -1) { - FreeImage_Unload(dib8); - return NULL; - } - } - dst_line[x] = last_index; - src_line += 3; - } - } - - // Process all but the last pixel of the last scanline. - BYTE *dst_line = dst_bits + (height - 1) * dst_pitch; - const BYTE *src_line = src_bits + (height - 1) * src_pitch; - for (unsigned x = 0; x < width - 1; ++x) { - const unsigned color = *((unsigned *) src_line) & 0x00FFFFFF; - if (color != last_color) { - last_color = color; - last_index = GetIndexForColor(color); - if (last_index == -1) { - FreeImage_Unload(dib8); - return NULL; - } - } - dst_line[x] = last_index; - src_line += 3; - } - - // Process the last pixel (src_line should already point to it). - const unsigned color = 0 | src_line[FI_RGBA_BLUE] << FI_RGBA_BLUE_SHIFT - | src_line[FI_RGBA_GREEN] << FI_RGBA_GREEN_SHIFT - | src_line[FI_RGBA_RED] << FI_RGBA_RED_SHIFT; - if (color != last_color) { - last_color = color; - last_index = GetIndexForColor(color); - if (last_index == -1) { - FreeImage_Unload(dib8); - return NULL; - } - } - dst_line[width - 1] = last_index; - - } else { - for (unsigned y = 0; y < height; ++y) { - BYTE *dst_line = dst_bits + y * dst_pitch; - const BYTE *src_line = src_bits + y * src_pitch; - for (unsigned x = 0; x < width; ++x) { - const unsigned color = *((unsigned *) src_line) & 0x00FFFFFF; - if (color != last_color) { - last_color = color; - last_index = GetIndexForColor(color); - if (last_index == -1) { - FreeImage_Unload(dib8); - return NULL; - } - } - dst_line[x] = last_index; - src_line += 4; - } - } - } - - WritePalette(FreeImage_GetPalette(dib8)); - return dib8; -} - -/** - * Returns the palette index of the specified color. Tries to put the - * color into the map, if it's not already present in the map. In that - * case, a new index is used for the color. Returns -1, if adding the - * color would exceed the desired maximum number of colors in the - * palette. - * @param color the color to get the index from - * @return the palette index of the specified color or -1, if there - * is no space left in the palette - */ -inline int LFPQuantizer::GetIndexForColor(unsigned color) { - unsigned bucket = hash(color) & (MAP_SIZE - 1); - while (m_map[bucket].color != color) { - if (m_map[bucket].color == EMPTY_BUCKET) { - if (m_size == m_limit) { - return -1; - } - m_map[bucket].color = color; - m_map[bucket].index = m_index++; - ++m_size; - break; - } - bucket = (bucket + 1) % MAP_SIZE; - } - return m_map[bucket].index; -} - -/** - * Adds the specified number of entries of the specified reserve - * palette to the newly created palette. - * @param *palette a pointer to the reserve palette to copy from - * @param size the number of entries to copy - */ -void LFPQuantizer::AddReservePalette(const void *palette, unsigned size) { - if (size > MAX_SIZE) { - size = MAX_SIZE; - } - unsigned *ppal = (unsigned *) palette; - const unsigned offset = m_limit - size; - for (unsigned i = 0; i < size; ++i) { - const unsigned color = *ppal++; - const unsigned index = i + offset; - unsigned bucket = hash(color) & (MAP_SIZE - 1); - while((m_map[bucket].color != EMPTY_BUCKET) && (m_map[bucket].color != color)) { - bucket = (bucket + 1) % MAP_SIZE; - } - if(m_map[bucket].color != color) { - m_map[bucket].color = color; - m_map[bucket].index = index; - } - } - m_size += size; -} - -/** - * Copies the newly created palette into the specified destination - * palette. Although unused palette entries are not overwritten in - * the destination palette, it is assumed to have space for at - * least 256 entries. - * @param palette a pointer to the destination palette - */ -void LFPQuantizer::WritePalette(void *palette) { - for (unsigned i = 0; i < MAP_SIZE; ++i) { - if (m_map[i].color != EMPTY_BUCKET) { - ((unsigned *) palette)[m_map[i].index] = m_map[i].color; - } - } -} diff --git a/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp b/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp deleted file mode 100644 index 2bc3e833a4..0000000000 --- a/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp +++ /dev/null @@ -1,1320 +0,0 @@ -// ========================================================== -// MNG / JNG helpers -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -/** -References -http://www.libpng.org/pub/mng/spec/jng.html -http://www.w3.org/TR/PNG/ -http://libpng.org/pub/mng/spec/ -*/ - -// -------------------------------------------------------------------------- - -#define MNG_INCLUDE_JNG - -#ifdef MNG_INCLUDE_JNG -#define MNG_COLORTYPE_JPEGGRAY 8 /* JHDR */ -#define MNG_COLORTYPE_JPEGCOLOR 10 -#define MNG_COLORTYPE_JPEGGRAYA 12 -#define MNG_COLORTYPE_JPEGCOLORA 14 - -#define MNG_BITDEPTH_JPEG8 8 /* JHDR */ -#define MNG_BITDEPTH_JPEG12 12 -#define MNG_BITDEPTH_JPEG8AND12 20 - -#define MNG_COMPRESSION_BASELINEJPEG 8 /* JHDR */ - -#define MNG_INTERLACE_SEQUENTIAL 0 /* JHDR */ -#define MNG_INTERLACE_PROGRESSIVE 8 -#endif /* MNG_INCLUDE_JNG */ - -// -------------------------------------------------------------------------- - -#define JNG_SUPPORTED - -/** Size of a JDAT chunk on writing */ -const DWORD JPEG_CHUNK_SIZE = 8192; - -/** PNG signature */ -static const BYTE g_png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; -/** JNG signature */ -static const BYTE g_jng_signature[8] = { 139, 74, 78, 71, 13, 10, 26, 10 }; - -// -------------------------------------------------------------------------- - -/** Chunk type converted to enum */ -enum eChunckType { - UNKNOWN_CHUNCK, - MHDR, - BACK, - BASI, - CLIP, - CLON, - DEFI, - DHDR, - DISC, - ENDL, - FRAM, - IEND, - IHDR, - JHDR, - LOOP, - MAGN, - MEND, - MOVE, - PAST, - PLTE, - SAVE, - SEEK, - SHOW, - TERM, - bKGD, - cHRM, - gAMA, - iCCP, - nEED, - pHYg, - vpAg, - pHYs, - sBIT, - sRGB, - tRNS, - IDAT, - JDAT, - JDAA, - JdAA, - JSEP, - oFFs, - hIST, - iTXt, - sPLT, - sTER, - tEXt, - tIME, - zTXt -}; - -/** -Helper for map<key, value> where value is a pointer to a string. -Used to store tEXt metadata. -*/ -typedef std::map<std::string, std::string> tEXtMAP; - -// -------------------------------------------------------------------------- - -/* - Constant strings for known chunk types. If you need to add a chunk, - add a string holding the name here. To make the code more - portable, we use ASCII numbers like this, not characters. -*/ - -static BYTE mng_MHDR[5]={ 77, 72, 68, 82, (BYTE) '\0'}; -static BYTE mng_BACK[5]={ 66, 65, 67, 75, (BYTE) '\0'}; -static BYTE mng_BASI[5]={ 66, 65, 83, 73, (BYTE) '\0'}; -static BYTE mng_CLIP[5]={ 67, 76, 73, 80, (BYTE) '\0'}; -static BYTE mng_CLON[5]={ 67, 76, 79, 78, (BYTE) '\0'}; -static BYTE mng_DEFI[5]={ 68, 69, 70, 73, (BYTE) '\0'}; -static BYTE mng_DHDR[5]={ 68, 72, 68, 82, (BYTE) '\0'}; -static BYTE mng_DISC[5]={ 68, 73, 83, 67, (BYTE) '\0'}; -static BYTE mng_ENDL[5]={ 69, 78, 68, 76, (BYTE) '\0'}; -static BYTE mng_FRAM[5]={ 70, 82, 65, 77, (BYTE) '\0'}; -static BYTE mng_IEND[5]={ 73, 69, 78, 68, (BYTE) '\0'}; -static BYTE mng_IHDR[5]={ 73, 72, 68, 82, (BYTE) '\0'}; -static BYTE mng_JHDR[5]={ 74, 72, 68, 82, (BYTE) '\0'}; -static BYTE mng_LOOP[5]={ 76, 79, 79, 80, (BYTE) '\0'}; -static BYTE mng_MAGN[5]={ 77, 65, 71, 78, (BYTE) '\0'}; -static BYTE mng_MEND[5]={ 77, 69, 78, 68, (BYTE) '\0'}; -static BYTE mng_MOVE[5]={ 77, 79, 86, 69, (BYTE) '\0'}; -static BYTE mng_PAST[5]={ 80, 65, 83, 84, (BYTE) '\0'}; -static BYTE mng_PLTE[5]={ 80, 76, 84, 69, (BYTE) '\0'}; -static BYTE mng_SAVE[5]={ 83, 65, 86, 69, (BYTE) '\0'}; -static BYTE mng_SEEK[5]={ 83, 69, 69, 75, (BYTE) '\0'}; -static BYTE mng_SHOW[5]={ 83, 72, 79, 87, (BYTE) '\0'}; -static BYTE mng_TERM[5]={ 84, 69, 82, 77, (BYTE) '\0'}; -static BYTE mng_bKGD[5]={ 98, 75, 71, 68, (BYTE) '\0'}; -static BYTE mng_cHRM[5]={ 99, 72, 82, 77, (BYTE) '\0'}; -static BYTE mng_gAMA[5]={103, 65, 77, 65, (BYTE) '\0'}; -static BYTE mng_iCCP[5]={105, 67, 67, 80, (BYTE) '\0'}; -static BYTE mng_nEED[5]={110, 69, 69, 68, (BYTE) '\0'}; -static BYTE mng_pHYg[5]={112, 72, 89, 103, (BYTE) '\0'}; -static BYTE mng_vpAg[5]={118, 112, 65, 103, (BYTE) '\0'}; -static BYTE mng_pHYs[5]={112, 72, 89, 115, (BYTE) '\0'}; -static BYTE mng_sBIT[5]={115, 66, 73, 84, (BYTE) '\0'}; -static BYTE mng_sRGB[5]={115, 82, 71, 66, (BYTE) '\0'}; -static BYTE mng_tRNS[5]={116, 82, 78, 83, (BYTE) '\0'}; - -#if defined(JNG_SUPPORTED) -static BYTE mng_IDAT[5]={ 73, 68, 65, 84, (BYTE) '\0'}; -static BYTE mng_JDAT[5]={ 74, 68, 65, 84, (BYTE) '\0'}; -static BYTE mng_JDAA[5]={ 74, 68, 65, 65, (BYTE) '\0'}; -static BYTE mng_JdAA[5]={ 74, 100, 65, 65, (BYTE) '\0'}; -static BYTE mng_JSEP[5]={ 74, 83, 69, 80, (BYTE) '\0'}; -static BYTE mng_oFFs[5]={111, 70, 70, 115, (BYTE) '\0'}; -#endif - -static BYTE mng_hIST[5]={104, 73, 83, 84, (BYTE) '\0'}; -static BYTE mng_iTXt[5]={105, 84, 88, 116, (BYTE) '\0'}; -static BYTE mng_sPLT[5]={115, 80, 76, 84, (BYTE) '\0'}; -static BYTE mng_sTER[5]={115, 84, 69, 82, (BYTE) '\0'}; -static BYTE mng_tEXt[5]={116, 69, 88, 116, (BYTE) '\0'}; -static BYTE mng_tIME[5]={116, 73, 77, 69, (BYTE) '\0'}; -static BYTE mng_zTXt[5]={122, 84, 88, 116, (BYTE) '\0'}; - - -// -------------------------------------------------------------------------- - -/** -Convert a chunk name to a unique ID -*/ -static eChunckType -mng_GetChunckType(const BYTE *mChunkName) { - if(memcmp(mChunkName, mng_MHDR, 4) == 0) { - return MHDR; - } - if(memcmp(mChunkName, mng_LOOP, 4) == 0) { - return LOOP; - } - if(memcmp(mChunkName, mng_DEFI, 4) == 0) { - return DEFI; - } - if(memcmp(mChunkName, mng_PLTE, 4) == 0) { - return PLTE; - } - if(memcmp(mChunkName, mng_tRNS, 4) == 0) { - return tRNS; - } - if(memcmp(mChunkName, mng_IHDR, 4) == 0) { - return IHDR; - } - if(memcmp(mChunkName, mng_JHDR, 4) == 0) { - return JHDR; - } - if(memcmp(mChunkName, mng_MEND, 4) == 0) { - return MEND; - } - if(memcmp(mChunkName, mng_IEND, 4) == 0) { - return IEND; - } - if(memcmp(mChunkName, mng_JDAT, 4) == 0) { - return JDAT; - } - if(memcmp(mChunkName, mng_IDAT, 4) == 0) { - return IDAT; - } - if(memcmp(mChunkName, mng_JDAA, 4) == 0) { - return JDAA; - } - if(memcmp(mChunkName, mng_gAMA, 4) == 0) { - return gAMA; - } - if(memcmp(mChunkName, mng_pHYs, 4) == 0) { - return pHYs; - } - if(memcmp(mChunkName, mng_bKGD, 4) == 0) { - return bKGD; - } - if(memcmp(mChunkName, mng_tEXt, 4) == 0) { - return tEXt; - } - - return UNKNOWN_CHUNCK; -} - -inline void -mng_SwapShort(WORD *sp) { -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(sp); -#endif -} - -inline void -mng_SwapLong(DWORD *lp) { -#ifndef FREEIMAGE_BIGENDIAN - SwapLong(lp); -#endif -} - -/** -Returns the size, in bytes, of a FreeImageIO stream, from the current position. -*/ -static long -mng_LOF(FreeImageIO *io, fi_handle handle) { - long start_pos = io->tell_proc(handle); - io->seek_proc(handle, 0, SEEK_END); - long file_length = io->tell_proc(handle); - io->seek_proc(handle, start_pos, SEEK_SET); - return file_length; -} - -/** -Count the number of bytes in a PNG stream, from IHDR to IEND. -If successful, the stream position, as given by io->tell_proc(handle), -should be the end of the PNG stream at the return of the function. -@param io -@param handle -@param inPos -@param m_TotalBytesOfChunks -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -mng_CountPNGChunks(FreeImageIO *io, fi_handle handle, long inPos, unsigned *m_TotalBytesOfChunks) { - long mLOF; - long mPos; - BOOL mEnd = FALSE; - DWORD mLength = 0; - BYTE mChunkName[5]; - - *m_TotalBytesOfChunks = 0; - - // get the length of the file - mLOF = mng_LOF(io, handle); - - // go to the start of the file - io->seek_proc(handle, inPos, SEEK_SET); - - try { - // parse chunks - while(mEnd == FALSE) { - // chunk length - mPos = io->tell_proc(handle); - if(mPos + 4 > mLOF) { - throw(1); - } - io->read_proc(&mLength, 1, 4, handle); - mng_SwapLong(&mLength); - // chunk name - mPos = io->tell_proc(handle); - if(mPos + 4 > mLOF) { - throw(1); - } - io->read_proc(&mChunkName[0], 1, 4, handle); - mChunkName[4] = '\0'; - - // go to next chunk - mPos = io->tell_proc(handle); - // 4 = size of the CRC - if(mPos + (long)mLength + 4 > mLOF) { - throw(1); - } - io->seek_proc(handle, mLength + 4, SEEK_CUR); - - switch( mng_GetChunckType(mChunkName) ) { - case IHDR: - if(mLength != 13) { - throw(1); - } - break; - - case IEND: - mEnd = TRUE; - // the length below includes 4 bytes CRC, but no bytes for Length - *m_TotalBytesOfChunks = io->tell_proc(handle) - inPos; - break; - - case UNKNOWN_CHUNCK: - default: - break; - } - - } // while(!mEnd) - - return TRUE; - - } catch(int) { - return FALSE; - } -} - -/** -Retrieve the position of a chunk in a PNG stream -@param hPngMemory PNG stream handle -@param chunk_name Name of the chunk to be found -@param offset Start of the search in the stream -@param start_pos [returned value] Start position of the chunk -@param next_pos [returned value] Start position of the next chunk -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -mng_FindChunk(FIMEMORY *hPngMemory, BYTE *chunk_name, long offset, DWORD *start_pos, DWORD *next_pos) { - DWORD mLength = 0; - - BYTE *data = NULL; - DWORD size_in_bytes = 0; - - *start_pos = 0; - *next_pos = 0; - - // get a pointer to the stream buffer - FreeImage_AcquireMemory(hPngMemory, &data, &size_in_bytes); - if(!(data && size_in_bytes) || (size_in_bytes < 20) || (size_in_bytes - offset < 20)) { - // not enough space to read a signature(8 bytes) + a chunk(at least 12 bytes) - return FALSE; - } - - try { - - // skip the signature and/or any following chunk(s) - DWORD chunk_pos = offset; - - while(1) { - // get chunk length - if(chunk_pos + 4 > size_in_bytes) { - break; - } - - memcpy(&mLength, &data[chunk_pos], 4); - mng_SwapLong(&mLength); - chunk_pos += 4; - - const DWORD next_chunk_pos = chunk_pos + 4 + mLength + 4; - if(next_chunk_pos > size_in_bytes) { - break; - } - - // get chunk name - if(memcmp(&data[chunk_pos], chunk_name, 4) == 0) { - chunk_pos -= 4; // found chunk - *start_pos = chunk_pos; - *next_pos = next_chunk_pos; - return TRUE; - } - - chunk_pos = next_chunk_pos; - } - - return FALSE; - - } catch(int) { - return FALSE; - } -} - -/** -Remove a chunk located at (start_pos, next_pos) in the PNG stream -@param hPngMemory PNG stream handle -@param start_pos Start position of the chunk -@param next_pos Start position of the next chunk -@return Returns TRUE if successfull, returns FALSE otherwise -*/ -static BOOL -mng_CopyRemoveChunks(FIMEMORY *hPngMemory, DWORD start_pos, DWORD next_pos) { - BYTE *data = NULL; - DWORD size_in_bytes = 0; - - // length of the chunk to remove - DWORD chunk_length = next_pos - start_pos; - if(chunk_length == 0) { - return TRUE; - } - - // get a pointer to the stream buffer - FreeImage_AcquireMemory(hPngMemory, &data, &size_in_bytes); - if(!(data && size_in_bytes) || (size_in_bytes < 20) || (chunk_length >= size_in_bytes)) { - // not enough space to read a signature(8 bytes) + a chunk(at least 12 bytes) - return FALSE; - } - - // new file length - unsigned buffer_size = size_in_bytes + chunk_length; - - BYTE *buffer = (BYTE*)malloc(buffer_size * sizeof(BYTE)); - if(!buffer) { - return FALSE; - } - memcpy(&buffer[0], &data[0], start_pos); - memcpy(&buffer[start_pos], &data[next_pos], size_in_bytes - next_pos); - - // seek to the start of the stream - FreeImage_SeekMemory(hPngMemory, 0, SEEK_SET); - // re-write the stream - FreeImage_WriteMemory(buffer, 1, buffer_size, hPngMemory); - - free(buffer); - - return TRUE; -} - -/** -Insert a chunk just before the inNextChunkName chunk -@param hPngMemory PNG stream handle -@param start_pos Start position of the inNextChunkName chunk -@param next_pos Start position of the next chunk -@return Returns TRUE if successfull, returns FALSE otherwise -*/ -static BOOL -mng_CopyInsertChunks(FIMEMORY *hPngMemory, BYTE *inNextChunkName, BYTE *inInsertChunk, DWORD inChunkLength, DWORD start_pos, DWORD next_pos) { - BYTE *data = NULL; - DWORD size_in_bytes = 0; - - // length of the chunk to check - DWORD chunk_length = next_pos - start_pos; - if(chunk_length == 0) { - return TRUE; - } - - // get a pointer to the stream buffer - FreeImage_AcquireMemory(hPngMemory, &data, &size_in_bytes); - if(!(data && size_in_bytes) || (size_in_bytes < 20) || (chunk_length >= size_in_bytes)) { - // not enough space to read a signature(8 bytes) + a chunk(at least 12 bytes) - return FALSE; - } - - // new file length - unsigned buffer_size = inChunkLength + size_in_bytes; - - BYTE *buffer = (BYTE*)malloc(buffer_size * sizeof(BYTE)); - if(!buffer) { - return FALSE; - } - unsigned p = 0; - memcpy(&buffer[p], &data[0], start_pos); - p += start_pos; - memcpy(&buffer[p], inInsertChunk, inChunkLength); - p += inChunkLength; - memcpy(&buffer[p], &data[start_pos], size_in_bytes - start_pos); - - // seek to the start of the stream - FreeImage_SeekMemory(hPngMemory, 0, SEEK_SET); - // re-write the stream - FreeImage_WriteMemory(buffer, 1, buffer_size, hPngMemory); - - free(buffer); - - return TRUE; -} - -static BOOL -mng_RemoveChunk(FIMEMORY *hPngMemory, BYTE *chunk_name) { - BOOL bResult = FALSE; - - DWORD start_pos = 0; - DWORD next_pos = 0; - - bResult = mng_FindChunk(hPngMemory, chunk_name, 8, &start_pos, &next_pos); - if(!bResult) { - return FALSE; - } - - bResult = mng_CopyRemoveChunks(hPngMemory, start_pos, next_pos); - if(!bResult) { - return FALSE; - } - - return TRUE; -} - -static BOOL -mng_InsertChunk(FIMEMORY *hPngMemory, BYTE *inNextChunkName, BYTE *inInsertChunk, unsigned chunk_length) { - BOOL bResult = FALSE; - - DWORD start_pos = 0; - DWORD next_pos = 0; - - bResult = mng_FindChunk(hPngMemory, inNextChunkName, 8, &start_pos, &next_pos); - if(!bResult) { - return FALSE; - } - - bResult = mng_CopyInsertChunks(hPngMemory, inNextChunkName, inInsertChunk, chunk_length, start_pos, next_pos); - if(!bResult) { - return FALSE; - } - - return TRUE; -} - -static FIBITMAP* -mng_LoadFromMemoryHandle(FIMEMORY *hmem, int flags = 0) { - long offset = 0; - FIBITMAP *dib = NULL; - - if(hmem) { - // seek to the start of the stream - FreeImage_SeekMemory(hmem, offset, SEEK_SET); - - // check the file signature and deduce its format - // (the second argument is currently not used by FreeImage) - FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0); - if(fif != FIF_UNKNOWN) { - dib = FreeImage_LoadFromMemory(fif, hmem, flags); - } - } - - return dib; -} - -/** -Write a chunk in a PNG stream from the current position. -@param chunk_name Name of the chunk -@param chunk_data Chunk array -@param length Chunk length -@param hPngMemory PNG stream handle -*/ -static void -mng_WriteChunk(BYTE *chunk_name, BYTE *chunk_data, DWORD length, FIMEMORY *hPngMemory) { - DWORD crc_file = 0; - // write a PNG chunk ... - // - length - mng_SwapLong(&length); - FreeImage_WriteMemory(&length, 1, 4, hPngMemory); - mng_SwapLong(&length); - // - chunk name - FreeImage_WriteMemory(chunk_name, 1, 4, hPngMemory); - if(chunk_data && length) { - // - chunk data - FreeImage_WriteMemory(chunk_data, 1, length, hPngMemory); - // - crc - crc_file = FreeImage_ZLibCRC32(0, chunk_name, 4); - crc_file = FreeImage_ZLibCRC32(crc_file, chunk_data, length); - mng_SwapLong(&crc_file); - FreeImage_WriteMemory(&crc_file, 1, 4, hPngMemory); - } else { - // - crc - crc_file = FreeImage_ZLibCRC32(0, chunk_name, 4); - mng_SwapLong(&crc_file); - FreeImage_WriteMemory(&crc_file, 1, 4, hPngMemory); - } - -} - -/** -Wrap a IDAT chunk as a PNG stream. -The stream has the structure { g_png_signature, IHDR, IDAT, IEND } -The image is assumed to be a greyscale image. - -@param jng_width Image width -@param jng_height Image height -@param jng_alpha_sample_depth Bits per pixel -@param mChunk PNG grayscale IDAT format -@param mLength IDAT chunk length -@param hPngMemory Output memory stream -*/ -static void -mng_WritePNGStream(DWORD jng_width, DWORD jng_height, BYTE jng_alpha_sample_depth, BYTE *mChunk, DWORD mLength, FIMEMORY *hPngMemory) { - // PNG grayscale IDAT format - - BYTE data[14]; - - // wrap the IDAT chunk as a PNG stream - - // write PNG file signature - FreeImage_WriteMemory(g_png_signature, 1, 8, hPngMemory); - - // write a IHDR chunk ... - /* - The IHDR chunk must appear FIRST. It contains: - Width: 4 bytes - Height: 4 bytes - Bit depth: 1 byte - Color type: 1 byte - Compression method: 1 byte - Filter method: 1 byte - Interlace method: 1 byte - */ - // - chunk data - mng_SwapLong(&jng_width); - mng_SwapLong(&jng_height); - memcpy(&data[0], &jng_width, 4); - memcpy(&data[4], &jng_height, 4); - mng_SwapLong(&jng_width); - mng_SwapLong(&jng_height); - data[8] = jng_alpha_sample_depth; - data[9] = 0; // color_type gray (jng_color_type) - data[10] = 0; // compression method 0 (jng_alpha_compression_method) - data[11] = 0; // filter_method 0 (jng_alpha_filter_method) - data[12] = 0; // interlace_method 0 (jng_alpha_interlace_method) - - mng_WriteChunk(mng_IHDR, &data[0], 13, hPngMemory); - - // write a IDAT chunk ... - mng_WriteChunk(mng_IDAT, mChunk, mLength, hPngMemory); - - // write a IEND chunk ... - mng_WriteChunk(mng_IEND, NULL, 0, hPngMemory); - -} - -// -------------------------------------------------------------------------- - -/** -Build and set a FITAG whose type is FIDT_ASCII. -The tag must be destroyed by the caller using FreeImage_DeleteTag. -@param model Metadata model to be filled -@param dib Image to be filled -@param key Tag key -@param value Tag value -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -mng_SetKeyValue(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, const char *value) { - if(!dib || !key || !value) { - return FALSE; - } - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - BOOL bSuccess = TRUE; - // fill the tag - DWORD tag_length = (DWORD)(strlen(value) + 1); - bSuccess &= FreeImage_SetTagKey(tag, key); - bSuccess &= FreeImage_SetTagLength(tag, tag_length); - bSuccess &= FreeImage_SetTagCount(tag, tag_length); - bSuccess &= FreeImage_SetTagType(tag, FIDT_ASCII); - bSuccess &= FreeImage_SetTagValue(tag, value); - if(bSuccess) { - // set the tag - FreeImage_SetMetadata(model, dib, FreeImage_GetTagKey(tag), tag); - } - FreeImage_DeleteTag(tag); - return bSuccess; - } - - return FALSE; -} - -/** -Read a tEXt chunk and extract the key/value pair. -@param key_value_pair [returned value] Array of key/value pairs -@param mChunk Chunk data -@param mLength Chunk length -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -mng_SetMetadata_tEXt(tEXtMAP &key_value_pair, const BYTE *mChunk, DWORD mLength) { - std::string key; - std::string value; - BYTE *buffer = (BYTE*)malloc(mLength * sizeof(BYTE)); - if(!buffer) { - return FALSE; - } - DWORD pos = 0; - - memset(buffer, 0, mLength * sizeof(BYTE)); - - for(DWORD i = 0; i < mLength; i++) { - buffer[pos++] = mChunk[i]; - if(mChunk[i] == '\0') { - if(key.size() == 0) { - key = (char*)buffer; - pos = 0; - memset(buffer, 0, mLength * sizeof(BYTE)); - } else { - break; - } - } - } - value = (char*)buffer; - free(buffer); - - key_value_pair[key] = value; - - return TRUE; -} - -// -------------------------------------------------------------------------- - -/** -Load a FIBITMAP from a MNG or a JNG stream -@param format_id ID of the caller -@param io Stream i/o functions -@param handle Stream handle -@param Offset Start of the first chunk -@param flags Loading flags -@return Returns a dib if successful, returns NULL otherwise -*/ -FIBITMAP* -mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, int flags = 0) { - DWORD mLength = 0; - BYTE mChunkName[5]; - BYTE *mChunk = NULL; - DWORD crc_file; - long LastOffset; - long mOrigPos; - BYTE *PLTE_file_chunk = NULL; // whole PLTE chunk (lentgh, name, array, crc) - DWORD PLTE_file_size = 0; // size of PLTE chunk - - BOOL m_HasGlobalPalette = FALSE; // may turn to TRUE in PLTE chunk - unsigned m_TotalBytesOfChunks = 0; - FIBITMAP *dib = NULL; - FIBITMAP *dib_alpha = NULL; - - FIMEMORY *hJpegMemory = NULL; - FIMEMORY *hPngMemory = NULL; - FIMEMORY *hIDATMemory = NULL; - - // --- - DWORD jng_width = 0; - DWORD jng_height = 0; - BYTE jng_color_type = 0; - BYTE jng_image_sample_depth = 0; - BYTE jng_image_compression_method = 0; - - BYTE jng_alpha_sample_depth = 0; - BYTE jng_alpha_compression_method = 0; - BYTE jng_alpha_filter_method = 0; - BYTE jng_alpha_interlace_method = 0; - - DWORD mng_frame_width = 0; - DWORD mng_frame_height = 0; - DWORD mng_ticks_per_second = 0; - DWORD mng_nominal_layer_count = 0; - DWORD mng_nominal_frame_count = 0; - DWORD mng_nominal_play_time = 0; - DWORD mng_simplicity_profile = 0; - - - DWORD res_x = 2835; // 72 dpi - DWORD res_y = 2835; // 72 dpi - RGBQUAD rgbBkColor = {0, 0, 0, 0}; - WORD bk_red, bk_green, bk_blue; - BOOL hasBkColor = FALSE; - BOOL mHasIDAT = FALSE; - - tEXtMAP key_value_pair; - - // --- - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // get the file size - const long mLOF = mng_LOF(io, handle); - // go to the first chunk - io->seek_proc(handle, Offset, SEEK_SET); - - try { - BOOL mEnd = FALSE; - - while(mEnd == FALSE) { - // start of the chunk - LastOffset = io->tell_proc(handle); - // read length - mLength = 0; - io->read_proc(&mLength, 1, sizeof(mLength), handle); - mng_SwapLong(&mLength); - // read name - io->read_proc(&mChunkName[0], 1, 4, handle); - mChunkName[4] = '\0'; - - if(mLength > 0) { - mChunk = (BYTE*)realloc(mChunk, mLength); - if(!mChunk) { - FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName); - throw (const char*)NULL; - } - Offset = io->tell_proc(handle); - if(Offset + (long)mLength > mLOF) { - FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: unexpected end of file", mChunkName); - throw (const char*)NULL; - } - // read chunk - io->read_proc(mChunk, 1, mLength, handle); - } - // read crc - io->read_proc(&crc_file, 1, sizeof(crc_file), handle); - mng_SwapLong(&crc_file); - // check crc - DWORD crc_check = FreeImage_ZLibCRC32(0, &mChunkName[0], 4); - crc_check = FreeImage_ZLibCRC32(crc_check, mChunk, mLength); - if(crc_check != crc_file) { - FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: bad CRC", mChunkName); - throw (const char*)NULL; - } - - switch( mng_GetChunckType(mChunkName) ) { - case MHDR: - // The MHDR chunk is always first in all MNG datastreams except for those - // that consist of a single PNG or JNG datastream with a PNG or JNG signature. - if(mLength == 28) { - memcpy(&mng_frame_width, &mChunk[0], 4); - memcpy(&mng_frame_height, &mChunk[4], 4); - memcpy(&mng_ticks_per_second, &mChunk[8], 4); - memcpy(&mng_nominal_layer_count, &mChunk[12], 4); - memcpy(&mng_nominal_frame_count, &mChunk[16], 4); - memcpy(&mng_nominal_play_time, &mChunk[20], 4); - memcpy(&mng_simplicity_profile, &mChunk[24], 4); - - mng_SwapLong(&mng_frame_width); - mng_SwapLong(&mng_frame_height); - mng_SwapLong(&mng_ticks_per_second); - mng_SwapLong(&mng_nominal_layer_count); - mng_SwapLong(&mng_nominal_frame_count); - mng_SwapLong(&mng_nominal_play_time); - mng_SwapLong(&mng_simplicity_profile); - - } else { - FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: size is %d instead of 28", mChunkName, mLength); - } - break; - - case MEND: - mEnd = TRUE; - break; - - case LOOP: - case ENDL: - break; - case DEFI: - break; - case SAVE: - case SEEK: - case TERM: - break; - case BACK: - break; - - // Global "PLTE" and "tRNS" (if any). PNG "PLTE" will be of 0 byte, as it uses global data. - case PLTE: // Global - m_HasGlobalPalette = TRUE; - PLTE_file_size = mLength + 12; // (lentgh, name, array, crc) = (4, 4, mLength, 4) - PLTE_file_chunk = (BYTE*)realloc(PLTE_file_chunk, PLTE_file_size); - if(!PLTE_file_chunk) { - FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName); - throw (const char*)NULL; - } else { - mOrigPos = io->tell_proc(handle); - // seek to the start of the chunk - io->seek_proc(handle, LastOffset, SEEK_SET); - // load the whole chunk - io->read_proc(PLTE_file_chunk, 1, PLTE_file_size, handle); - // go to the start of the next chunk - io->seek_proc(handle, mOrigPos, SEEK_SET); - } - break; - - case tRNS: // Global - break; - - case IHDR: - Offset = LastOffset; - // parse the PNG file and get its file size - if(mng_CountPNGChunks(io, handle, Offset, &m_TotalBytesOfChunks) == FALSE) { - // reach an unexpected end of file - mEnd = TRUE; - FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: unexpected end of PNG file", mChunkName); - break; - } - - // wrap the { IHDR, ..., IEND } chunks as a PNG stream - if(hPngMemory == NULL) { - hPngMemory = FreeImage_OpenMemory(); - } - - mOrigPos = io->tell_proc(handle); - - // write PNG file signature - FreeImage_SeekMemory(hPngMemory, 0, SEEK_SET); - FreeImage_WriteMemory(g_png_signature, 1, 8, hPngMemory); - - mChunk = (BYTE*)realloc(mChunk, m_TotalBytesOfChunks); - if(!mChunk) { - FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName); - throw (const char*)NULL; - } - - // on calling CountPNGChunks earlier, we were in Offset pos, - // go back there - io->seek_proc(handle, Offset, SEEK_SET); - io->read_proc(mChunk, 1, m_TotalBytesOfChunks, handle); - // Put back to original pos - io->seek_proc(handle, mOrigPos, SEEK_SET); - // write the PNG chunks - FreeImage_WriteMemory(mChunk, 1, m_TotalBytesOfChunks, hPngMemory); - - // plug in global PLTE if local PLTE exists - if(m_HasGlobalPalette) { - // ensure we remove some local chunks, so that global - // "PLTE" can be inserted right before "IDAT". - mng_RemoveChunk(hPngMemory, mng_PLTE); - mng_RemoveChunk(hPngMemory, mng_tRNS); - mng_RemoveChunk(hPngMemory, mng_bKGD); - // insert global "PLTE" chunk in its entirety before "IDAT" - mng_InsertChunk(hPngMemory, mng_IDAT, PLTE_file_chunk, PLTE_file_size); - } - - if(dib) FreeImage_Unload(dib); - dib = mng_LoadFromMemoryHandle(hPngMemory, flags); - - // stop after the first image - mEnd = TRUE; - break; - - case JHDR: - if(mLength == 16) { - memcpy(&jng_width, &mChunk[0], 4); - memcpy(&jng_height, &mChunk[4], 4); - mng_SwapLong(&jng_width); - mng_SwapLong(&jng_height); - - jng_color_type = mChunk[8]; - jng_image_sample_depth = mChunk[9]; - jng_image_compression_method = mChunk[10]; - //BYTE jng_image_interlace_method = mChunk[11]; // for debug only - - jng_alpha_sample_depth = mChunk[12]; - jng_alpha_compression_method = mChunk[13]; - jng_alpha_filter_method = mChunk[14]; - jng_alpha_interlace_method = mChunk[15]; - } else { - FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: invalid chunk length", mChunkName); - throw (const char*)NULL; - } - break; - - case JDAT: - if(hJpegMemory == NULL) { - hJpegMemory = FreeImage_OpenMemory(); - } - // as there may be several JDAT chunks, concatenate them - FreeImage_WriteMemory(mChunk, 1, mLength, hJpegMemory); - break; - - case IDAT: - if(!header_only && (jng_alpha_compression_method == 0)) { - // PNG grayscale IDAT format - if(hIDATMemory == NULL) { - hIDATMemory = FreeImage_OpenMemory(); - mHasIDAT = TRUE; - } - // as there may be several IDAT chunks, concatenate them - FreeImage_WriteMemory(mChunk, 1, mLength, hIDATMemory); - } - break; - - case IEND: - if(!hJpegMemory) { - mEnd = TRUE; - break; - } - // load the JPEG - if(dib) { - FreeImage_Unload(dib); - } - dib = mng_LoadFromMemoryHandle(hJpegMemory, flags); - - // load the PNG alpha layer - if(mHasIDAT) { - BYTE *data = NULL; - DWORD size_in_bytes = 0; - - // get a pointer to the IDAT buffer - FreeImage_AcquireMemory(hIDATMemory, &data, &size_in_bytes); - if(data && size_in_bytes) { - // wrap the IDAT chunk as a PNG stream - if(hPngMemory == NULL) { - hPngMemory = FreeImage_OpenMemory(); - } - mng_WritePNGStream(jng_width, jng_height, jng_alpha_sample_depth, data, size_in_bytes, hPngMemory); - // load the PNG - if(dib_alpha) { - FreeImage_Unload(dib_alpha); - } - dib_alpha = mng_LoadFromMemoryHandle(hPngMemory, flags); - } - } - // stop the parsing - mEnd = TRUE; - break; - - case JDAA: - break; - - case gAMA: - break; - - case pHYs: - // unit is pixels per meter - memcpy(&res_x, &mChunk[0], 4); - mng_SwapLong(&res_x); - memcpy(&res_y, &mChunk[4], 4); - mng_SwapLong(&res_y); - break; - - case bKGD: - memcpy(&bk_red, &mChunk[0], 2); - mng_SwapShort(&bk_red); - rgbBkColor.rgbRed = (BYTE)bk_red; - memcpy(&bk_green, &mChunk[2], 2); - mng_SwapShort(&bk_green); - rgbBkColor.rgbGreen = (BYTE)bk_green; - memcpy(&bk_blue, &mChunk[4], 2); - mng_SwapShort(&bk_blue); - rgbBkColor.rgbBlue = (BYTE)bk_blue; - hasBkColor = TRUE; - break; - - case tEXt: - mng_SetMetadata_tEXt(key_value_pair, mChunk, mLength); - break; - - case UNKNOWN_CHUNCK: - default: - break; - - - } // switch( GetChunckType ) - } // while(!mEnd) - - FreeImage_CloseMemory(hJpegMemory); - FreeImage_CloseMemory(hPngMemory); - FreeImage_CloseMemory(hIDATMemory); - free(mChunk); - free(PLTE_file_chunk); - - // convert to 32-bit if a transparent layer is available - if(!header_only && dib_alpha) { - FIBITMAP *dst = FreeImage_ConvertTo32Bits(dib); - if((FreeImage_GetBPP(dib_alpha) == 8) && (FreeImage_GetImageType(dib_alpha) == FIT_BITMAP)) { - FreeImage_SetChannel(dst, dib_alpha, FICC_ALPHA); - } else { - FIBITMAP *dst_alpha = FreeImage_ConvertTo8Bits(dib_alpha); - FreeImage_SetChannel(dst, dst_alpha, FICC_ALPHA); - FreeImage_Unload(dst_alpha); - } - FreeImage_Unload(dib); - dib = dst; - } - FreeImage_Unload(dib_alpha); - - if(dib) { - // set metadata - FreeImage_SetDotsPerMeterX(dib, res_x); - FreeImage_SetDotsPerMeterY(dib, res_y); - if(hasBkColor) { - FreeImage_SetBackgroundColor(dib, &rgbBkColor); - } - if(key_value_pair.size()) { - for(tEXtMAP::iterator j = key_value_pair.begin(); j != key_value_pair.end(); j++) { - std::string key = (*j).first; - std::string value = (*j).second; - mng_SetKeyValue(FIMD_COMMENTS, dib, key.c_str(), value.c_str()); - } - } - } - - return dib; - - } catch(const char *text) { - FreeImage_CloseMemory(hJpegMemory); - FreeImage_CloseMemory(hPngMemory); - FreeImage_CloseMemory(hIDATMemory); - free(mChunk); - free(PLTE_file_chunk); - FreeImage_Unload(dib); - FreeImage_Unload(dib_alpha); - if(text) { - FreeImage_OutputMessageProc(format_id, text); - } - return NULL; - } -} - -// -------------------------------------------------------------------------- - -/** -Write a FIBITMAP to a JNG stream -@param format_id ID of the caller -@param io Stream i/o functions -@param dib Image to be saved -@param handle Stream handle -@param flags Saving flags -@return Returns TRUE if successful, returns FALSE otherwise -*/ -BOOL -mng_WriteJNG(int format_id, FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int flags) { - DWORD jng_width = 0; - DWORD jng_height = 0; - BYTE jng_color_type = 0; - BYTE jng_image_sample_depth = 8; - BYTE jng_image_compression_method = 8; // 8: ISO-10918-1 Huffman-coded baseline JPEG. - BYTE jng_image_interlace_method = 0; - - BYTE jng_alpha_sample_depth = 0; - BYTE jng_alpha_compression_method = 0; - BYTE jng_alpha_filter_method = 0; - BYTE jng_alpha_interlace_method = 0; - - BYTE buffer[16]; - - FIMEMORY *hJngMemory = NULL; - FIMEMORY *hJpegMemory = NULL; - FIMEMORY *hPngMemory = NULL; - - FIBITMAP *dib_rgb = NULL; - FIBITMAP *dib_alpha = NULL; - - if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { - return FALSE; - } - - unsigned bpp = FreeImage_GetBPP(dib); - - switch(bpp) { - case 8: - if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) { - dib_rgb = dib; - jng_color_type = MNG_COLORTYPE_JPEGGRAY; - } else { - // JPEG plugin will convert other types (FIC_MINISWHITE, FIC_PALETTE) to 24-bit on the fly - //dib_rgb = FreeImage_ConvertTo24Bits(dib); - dib_rgb = dib; - jng_color_type = MNG_COLORTYPE_JPEGCOLOR; - - } - break; - case 24: - dib_rgb = dib; - jng_color_type = MNG_COLORTYPE_JPEGCOLOR; - break; - case 32: - dib_rgb = FreeImage_ConvertTo24Bits(dib); - jng_color_type = MNG_COLORTYPE_JPEGCOLORA; - jng_alpha_sample_depth = 8; - break; - default: - return FALSE; - } - - jng_width = (DWORD)FreeImage_GetWidth(dib); - jng_height = (DWORD)FreeImage_GetHeight(dib); - - try { - hJngMemory = FreeImage_OpenMemory(); - - // --- write JNG file signature --- - FreeImage_WriteMemory(g_jng_signature, 1, 8, hJngMemory); - - // --- write a JHDR chunk --- - SwapLong(&jng_width); - SwapLong(&jng_height); - memcpy(&buffer[0], &jng_width, 4); - memcpy(&buffer[4], &jng_height, 4); - SwapLong(&jng_width); - SwapLong(&jng_height); - buffer[8] = jng_color_type; - buffer[9] = jng_image_sample_depth; - buffer[10] = jng_image_compression_method; - buffer[11] = jng_image_interlace_method; - buffer[12] = jng_alpha_sample_depth; - buffer[13] = jng_alpha_compression_method; - buffer[14] = jng_alpha_filter_method; - buffer[15] = jng_alpha_interlace_method; - mng_WriteChunk(mng_JHDR, &buffer[0], 16, hJngMemory); - - // --- write a sequence of JDAT chunks --- - hJpegMemory = FreeImage_OpenMemory(); - flags |= JPEG_BASELINE; - if(!FreeImage_SaveToMemory(FIF_JPEG, dib_rgb, hJpegMemory, flags)) { - throw (const char*)NULL; - } - if(dib_rgb != dib) { - FreeImage_Unload(dib_rgb); - dib_rgb = NULL; - } - { - BYTE *jpeg_data = NULL; - DWORD size_in_bytes = 0; - - // get a pointer to the stream buffer - FreeImage_AcquireMemory(hJpegMemory, &jpeg_data, &size_in_bytes); - // write chunks - for(DWORD k = 0; k < size_in_bytes;) { - DWORD bytes_left = size_in_bytes - k; - DWORD chunk_size = MIN(JPEG_CHUNK_SIZE, bytes_left); - mng_WriteChunk(mng_JDAT, &jpeg_data[k], chunk_size, hJngMemory); - k += chunk_size; - } - } - FreeImage_CloseMemory(hJpegMemory); - hJpegMemory = NULL; - - // --- write alpha layer as a sequence of IDAT chunk --- - if((bpp == 32) && (jng_color_type == MNG_COLORTYPE_JPEGCOLORA)) { - dib_alpha = FreeImage_GetChannel(dib, FICC_ALPHA); - - hPngMemory = FreeImage_OpenMemory(); - if(!FreeImage_SaveToMemory(FIF_PNG, dib_alpha, hPngMemory, PNG_DEFAULT)) { - throw (const char*)NULL; - } - FreeImage_Unload(dib_alpha); - dib_alpha = NULL; - // get the IDAT chunk - { - BOOL bResult = FALSE; - DWORD start_pos = 0; - DWORD next_pos = 0; - long offset = 8; - - do { - // find the next IDAT chunk from 'offset' position - bResult = mng_FindChunk(hPngMemory, mng_IDAT, offset, &start_pos, &next_pos); - if(!bResult) break; - - BYTE *png_data = NULL; - DWORD size_in_bytes = 0; - - // get a pointer to the stream buffer - FreeImage_AcquireMemory(hPngMemory, &png_data, &size_in_bytes); - // write the IDAT chunk - mng_WriteChunk(mng_IDAT, &png_data[start_pos+8], next_pos - start_pos - 12, hJngMemory); - - offset = next_pos; - - } while(bResult); - } - - FreeImage_CloseMemory(hPngMemory); - hPngMemory = NULL; - } - - // --- write a IEND chunk --- - mng_WriteChunk(mng_IEND, NULL, 0, hJngMemory); - - // write the JNG on output stream - { - BYTE *jng_data = NULL; - DWORD size_in_bytes = 0; - FreeImage_AcquireMemory(hJngMemory, &jng_data, &size_in_bytes); - io->write_proc(jng_data, 1, size_in_bytes, handle); - } - - FreeImage_CloseMemory(hJngMemory); - FreeImage_CloseMemory(hJpegMemory); - FreeImage_CloseMemory(hPngMemory); - - return TRUE; - - } catch(const char *text) { - FreeImage_CloseMemory(hJngMemory); - FreeImage_CloseMemory(hJpegMemory); - FreeImage_CloseMemory(hPngMemory); - if(dib_rgb && (dib_rgb != dib)) { - FreeImage_Unload(dib_rgb); - } - FreeImage_Unload(dib_alpha); - if(text) { - FreeImage_OutputMessageProc(format_id, text); - } - return FALSE; - } -} diff --git a/plugins/AdvaImg/src/FreeImage/MemoryIO.cpp b/plugins/AdvaImg/src/FreeImage/MemoryIO.cpp deleted file mode 100644 index 7f587d3fa3..0000000000 --- a/plugins/AdvaImg/src/FreeImage/MemoryIO.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// ========================================================== -// Memory Input/Output functions -// -// Design and implementation by -// - Ryan Rubley <ryan@lostreality.org> -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "FreeImageIO.h" - -// ===================================================================== - - -// ===================================================================== -// Open and close a memory handle -// ===================================================================== - -FIMEMORY * DLL_CALLCONV -FreeImage_OpenMemory(BYTE *data, DWORD size_in_bytes) { - // allocate a memory handle - FIMEMORY *stream = (FIMEMORY*)malloc(sizeof(FIMEMORY)); - if(stream) { - stream->data = (BYTE*)malloc(sizeof(FIMEMORYHEADER)); - - if(stream->data) { - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data); - - // initialize the memory header - memset(mem_header, 0, sizeof(FIMEMORYHEADER)); - - if(data && size_in_bytes) { - // wrap a user buffer - mem_header->delete_me = FALSE; - mem_header->data = (BYTE*)data; - mem_header->data_length = mem_header->file_length = size_in_bytes; - } else { - mem_header->delete_me = TRUE; - } - - return stream; - } - free(stream); - } - - return NULL; -} - - -void DLL_CALLCONV -FreeImage_CloseMemory(FIMEMORY *stream) { - if(stream && stream->data) { - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data); - if(mem_header->delete_me) { - free(mem_header->data); - } - free(mem_header); - free(stream); - } -} - -// ===================================================================== -// Memory stream load/save functions -// ===================================================================== - -FIBITMAP * DLL_CALLCONV -FreeImage_LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags) { - if (stream && stream->data) { - FreeImageIO io; - SetMemoryIO(&io); - - return FreeImage_LoadFromHandle(fif, &io, (fi_handle)stream, flags); - } - - return NULL; -} - - -BOOL DLL_CALLCONV -FreeImage_SaveToMemory(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FIMEMORY *stream, int flags) { - if (stream) { - FreeImageIO io; - SetMemoryIO(&io); - - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data); - - if(mem_header->delete_me == TRUE) { - return FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)stream, flags); - } else { - // do not save in a user buffer - FreeImage_OutputMessageProc(fif, "Memory buffer is read only"); - } - } - - return FALSE; -} - -// ===================================================================== -// Memory stream buffer access -// ===================================================================== - -BOOL DLL_CALLCONV -FreeImage_AcquireMemory(FIMEMORY *stream, BYTE **data, DWORD *size_in_bytes) { - if (stream) { - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data); - - *data = (BYTE*)mem_header->data; - *size_in_bytes = mem_header->file_length; - return TRUE; - } - - return FALSE; -} - -// ===================================================================== -// 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 -// ===================================================================== - -/** -Moves the memory pointer to a specified location -@param stream Pointer to FIMEMORY structure -@param offset Number of bytes from origin -@param origin Initial position -@return Returns TRUE if successful, returns FALSE otherwise -*/ -BOOL DLL_CALLCONV -FreeImage_SeekMemory(FIMEMORY *stream, long offset, int origin) { - FreeImageIO io; - SetMemoryIO(&io); - - if (stream != NULL) { - int success = io.seek_proc((fi_handle)stream, offset, origin); - return (success == 0) ? TRUE : FALSE; - } - - return FALSE; -} - -/** -Gets the current position of a memory pointer -@param stream Target FIMEMORY structure -@return Returns the current file position if successful, -1 otherwise -*/ -long DLL_CALLCONV -FreeImage_TellMemory(FIMEMORY *stream) { - FreeImageIO io; - SetMemoryIO(&io); - - if (stream != NULL) { - return io.tell_proc((fi_handle)stream); - } - - return -1L; -} - -// ===================================================================== -// Reading or Writing in Memory stream -// ===================================================================== - -/** -Reads data from a memory stream -@param buffer Storage location for data -@param size Item size in bytes -@param count Maximum number of items to be read -@param stream Pointer to FIMEMORY structure -@return Returns the number of full items actually read, which may be less than count if an error occurs -*/ -unsigned DLL_CALLCONV -FreeImage_ReadMemory(void *buffer, unsigned size, unsigned count, FIMEMORY *stream) { - FreeImageIO io; - SetMemoryIO(&io); - - if (stream != NULL) { - return io.read_proc(buffer, size, count, stream); - } - - return 0; -} - -/** -Writes data to a memory stream. -@param buffer Pointer to data to be written -@param size Item size in bytes -@param count Maximum number of items to be written -@param stream Pointer to FIMEMORY structure -@return Returns the number of full items actually written, which may be less than count if an error occurs -*/ -unsigned DLL_CALLCONV -FreeImage_WriteMemory(const void *buffer, unsigned size, unsigned count, FIMEMORY *stream) { - if (stream != NULL) { - FreeImageIO io; - SetMemoryIO(&io); - - FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)stream)->data); - - if(mem_header->delete_me == TRUE) { - return io.write_proc((void *)buffer, size, count, stream); - } else { - // do not write in a user buffer - FreeImage_OutputMessageProc(FIF_UNKNOWN, "Memory buffer is read only"); - } - } - - return 0; -} - diff --git a/plugins/AdvaImg/src/FreeImage/MultiPage.cpp b/plugins/AdvaImg/src/FreeImage/MultiPage.cpp deleted file mode 100644 index 8c49d45396..0000000000 --- a/plugins/AdvaImg/src/FreeImage/MultiPage.cpp +++ /dev/null @@ -1,990 +0,0 @@ -// ========================================================== -// Multi-Page functions -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Laurent Rocher (rocherl@club-internet.fr) -// - Steve Johnson (steve@parisgroup.net) -// - Petr Pytelka (pyta@lightcomp.com) -// - Hervé Drolon (drolon@infonie.fr) -// - Vadim Alexandrov (vadimalexandrov@users.sourceforge.net -// - Martin Dyring-Andersen (mda@spamfighter.com) -// - Volodymyr Goncharov (volodymyr.goncharov@gmail.com) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#include "CacheFile.h" -#include "FreeImageIO.h" -#include "Plugin.h" -#include "Utilities.h" -#include "FreeImage.h" - -// ---------------------------------------------------------- - -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) { - } -}; - -// ---------------------------------------------------------- - -typedef std::list<BlockTypeS *> BlockList; -typedef std::list<BlockTypeS *>::iterator BlockListIterator; - -// ---------------------------------------------------------- - -FI_STRUCT (MULTIBITMAPHEADER) { - PluginNode *node; - FREE_IMAGE_FORMAT fif; - FreeImageIO *io; - fi_handle handle; - CacheFile *m_cachefile; - std::map<FIBITMAP *, int> locked_pages; - BOOL changed; - int page_count; - BlockList m_blocks; - char *m_filename; - BOOL read_only; - FREE_IMAGE_FORMAT cache_fif; - int load_flags; -}; - -// ===================================================================== -// Helper functions -// ===================================================================== - -inline void -ReplaceExtension(std::string& dst_filename, const std::string& src_filename, const std::string& dst_extension) { - size_t lastDot = src_filename.find_last_of('.'); - if (lastDot == std::string::npos) { - dst_filename = src_filename; - dst_filename += "."; - dst_filename += dst_extension; - } - else { - dst_filename = src_filename.substr(0, lastDot + 1); - dst_filename += dst_extension; - } -} - -// ===================================================================== -// Internal Multipage functions -// ===================================================================== - -inline MULTIBITMAPHEADER * -FreeImage_GetMultiBitmapHeader(FIMULTIBITMAP *bitmap) { - return (MULTIBITMAPHEADER *)bitmap->data; -} - -static BlockListIterator DLL_CALLCONV -FreeImage_FindBlock(FIMULTIBITMAP *bitmap, int position) { - assert(NULL != bitmap); - - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - // step 1: find the block that matches the given 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; - - 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) - 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; - } - } - } - // we should never go here ... - assert(false); - return header->m_blocks.end(); -} - -int DLL_CALLCONV -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); - - return page_count; - } - } - - return 0; -} - -// ===================================================================== -// Multipage functions -// ===================================================================== - -FIMULTIBITMAP * DLL_CALLCONV -FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory, int flags) { - - FILE *handle = NULL; - try { - // sanity check on the parameters - - if (create_new) { - read_only = FALSE; - } - - // retrieve the plugin list to find the node belonging to this plugin - - PluginList *list = FreeImage_GetPluginList(); - - if (list) { - 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) { - return NULL; - } - } - - 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->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; - - // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure - - bitmap->data = header.get(); - - // cache the page count - - header->page_count = FreeImage_InternalGetPageCount(bitmap.get()); - - // allocate a continueus block to describe the bitmap - - if (!create_new) { - header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1)); - } - - // set up the cache - - 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 { - // an error occured ... - fclose(handle); - return NULL; - } - } - // 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) - fclose(handle); - return NULL; -} - -FIMULTIBITMAP * DLL_CALLCONV -FreeImage_OpenMultiBitmapU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory, int flags) { - - // convert to single character - no national chars in extensions - char *extension = (char *)malloc(wcslen(filename)+1); - unsigned int i=0; - for (; i < wcslen(filename); i++) // convert 16-bit to 8-bit - extension[i] = (char)(filename[i] & 0x00FF); - // set terminating 0 - extension[i]=0; - FIMULTIBITMAP *fRet = FreeImage_OpenMultiBitmap(fif, extension, create_new, read_only, keep_cache_in_memory, flags); - free(extension); - - return fRet; -} - -FIMULTIBITMAP * DLL_CALLCONV -FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags) { - try { - BOOL read_only = FALSE; // modifications (if any) will be stored into the memory cache - - if (io && handle) { - - // retrieve the plugin list to find the node belonging to this plugin - PluginList *list = FreeImage_GetPluginList(); - - if (list) { - PluginNode *node = list->FindNodeFromFIF(fif); - - 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->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; - - // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure - - bitmap->data = header.get(); - - // cache the page count - - header->page_count = FreeImage_InternalGetPageCount(bitmap.get()); - - // 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 - 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(); - } - } - } - } catch (std::bad_alloc &) { - /** @todo report error */ - } - return NULL; -} - -BOOL DLL_CALLCONV -FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FreeImageIO *io, fi_handle handle, int flags) { - if(!bitmap || !bitmap->data || !io || !handle) { - return FALSE; - } - - BOOL success = TRUE; - - // retrieve the plugin list to find the node belonging to this plugin - PluginList *list = FreeImage_GetPluginList(); - - if (list) { - PluginNode *node = list->FindNodeFromFIF(fif); - - if(node) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - // dst data - void *data = FreeImage_Open(node, io, handle, FALSE); - // src data - void *data_read = NULL; - - 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); - } - - // write all the pages to the file using handle and io - - int count = 0; - - for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); i++) { - if (success) { - switch((*i)->m_type) { - case BLOCK_CONTINUEUS: - { - BlockContinueus *block = (BlockContinueus *)(*i); - - for (int j = block->m_start; j <= block->m_end; j++) { - - // load the original source data - 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); - count++; - - FreeImage_Unload(dib); - } - - break; - } - - case BLOCK_REFERENCE: - { - BlockReference *ref = (BlockReference *)(*i); - - // read the compressed data - - BYTE *compressed_data = (BYTE*)malloc(ref->m_size * sizeof(BYTE)); - - header->m_cachefile->readFile((BYTE *)compressed_data, ref->m_reference, ref->m_size); - - // uncompress the data - - FIMEMORY *hmem = FreeImage_OpenMemory(compressed_data, ref->m_size); - FIBITMAP *dib = FreeImage_LoadFromMemory(header->cache_fif, hmem, 0); - FreeImage_CloseMemory(hmem); - - // get rid of the buffer - free(compressed_data); - - // save the data - - success = node->m_plugin->save_proc(io, dib, handle, count, flags, data); - count++; - - // unload the dib - - FreeImage_Unload(dib); - - break; - } - } - } else { - break; - } - } - - // close the files - - FreeImage_Close(header->node, header->io, header->handle, data_read); - - FreeImage_Close(node, io, handle, data); - - return success; - } - } - - return FALSE; -} - - -BOOL DLL_CALLCONV -FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) { - if (bitmap) { - BOOL success = TRUE; - - if (bitmap->data) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - // saves changes only of images loaded directly from a file - if (header->changed && header->m_filename) { - try { - // open a temp file - - std::string spool_name; - - ReplaceExtension(spool_name, header->m_filename, "fispool"); - - // open the spool file and the source file - - FILE *f = fopen(spool_name.c_str(), "w+b"); - - // saves changes - if (f == NULL) { - 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); - - // close the files - - if (fclose(f) != 0) { - success = FALSE; - FreeImage_OutputMessageProc(header->fif, "Failed to close %s, %s", spool_name.c_str(), strerror(errno)); - } - } - if (header->handle) { - fclose((FILE *)header->handle); - } - - // applies changes to the destination file - - if (success) { - remove(header->m_filename); - success = (rename(spool_name.c_str(), header->m_filename) == 0) ? TRUE:FALSE; - if(!success) { - FreeImage_OutputMessageProc(header->fif, "Failed to rename %s to %s", spool_name.c_str(), header->m_filename); - } - } else { - remove(spool_name.c_str()); - } - } catch (std::bad_alloc &) { - success = FALSE; - } - - } else { - if (header->handle && header->m_filename) { - 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()) { - FreeImage_Unload(header->locked_pages.begin()->first); - - 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; - } - - delete bitmap; - - return success; - } - - return FALSE; -} - -int DLL_CALLCONV -FreeImage_GetPageCount(FIMULTIBITMAP *bitmap) { - if (bitmap) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - if (header->page_count == -1) { - 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; - } - } - } - - return header->page_count; - } - - return 0; -} - -static BlockReference* -FreeImage_SavePageToBlock(MULTIBITMAPHEADER *header, FIBITMAP *data) { - if (header->read_only || !header->locked_pages.empty()) - return NULL; - - DWORD compressed_size = 0; - BYTE *compressed_data = NULL; - - // compress the bitmap data - - // open a memory handle - FIMEMORY *hmem = FreeImage_OpenMemory(); - if(hmem==NULL) return NULL; - // save the file to memory - if(!FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0)) { - FreeImage_CloseMemory(hmem); - return NULL; - } - // get the buffer from the memory stream - if(!FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size)) { - FreeImage_CloseMemory(hmem); - return NULL; - } - - // write the compressed data to the cache - 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); -} - -void DLL_CALLCONV -FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *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; -} - -void DLL_CALLCONV -FreeImage_InsertPage(FIMULTIBITMAP *bitmap, int page, FIBITMAP *data) { - if (!bitmap || !data) - return; - - 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); - } - - header->changed = TRUE; - header->page_count = -1; -} - -void DLL_CALLCONV -FreeImage_DeletePage(FIMULTIBITMAP *bitmap, int page) { - if (bitmap) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - 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) { - 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_blocks.erase(i); - break; - } - - header->changed = TRUE; - header->page_count = -1; - } - } - } - } -} - - -FIBITMAP * DLL_CALLCONV -FreeImage_LockPage(FIMULTIBITMAP *bitmap, int page) { - if (bitmap) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - // only lock if the page wasn't locked before... - - for (std::map<FIBITMAP *, int>::iterator i = header->locked_pages.begin(); i != header->locked_pages.end(); ++i) { - if (i->second == page) { - return NULL; - } - } - - // open the bitmap - - 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; - - // close the file - - FreeImage_Close(header->node, header->io, header->handle, data); - - // if there was still another bitmap open, get rid of it - - if (dib) { - header->locked_pages[dib] = page; - - return dib; - } - - return NULL; - } - } - - return NULL; -} - -void DLL_CALLCONV -FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed) { - if ((bitmap) && (page)) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - // find out if the page we try to unlock is actually locked... - - 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; - - // cut loose the block from the rest - - BlockListIterator i = FreeImage_FindBlock(bitmap, header->locked_pages[page]); - - // compress the data - - DWORD compressed_size = 0; - BYTE *compressed_data = NULL; - - // open a memory handle - FIMEMORY *hmem = FreeImage_OpenMemory(); - // save the page to memory - FreeImage_SaveToMemory(header->cache_fif, page, hmem, 0); - // get the buffer from the memory stream - 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; - } - } - - // get rid of the compressed data - - FreeImage_CloseMemory(hmem); - } - - // reset the locked page so that another page can be locked - - FreeImage_Unload(page); - - header->locked_pages.erase(page); - } - } -} - -BOOL DLL_CALLCONV -FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source) { - if (bitmap) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - if ((!header->read_only) && (header->locked_pages.empty())) { - if ((target != source) && ((target >= 0) && (target < FreeImage_GetPageCount(bitmap))) && ((source >= 0) && (source < FreeImage_GetPageCount(bitmap)))) { - BlockListIterator block_source = FreeImage_FindBlock(bitmap, target); - BlockListIterator block_target = FreeImage_FindBlock(bitmap, source); - - header->m_blocks.insert(block_target, *block_source); - header->m_blocks.erase(block_source); - - header->changed = TRUE; - - return TRUE; - } - } - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count) { - if ((bitmap) && (count)) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - if ((pages == NULL) || (*count == 0)) { - *count = (int)header->locked_pages.size(); - } else { - int c = 0; - - for (std::map<FIBITMAP *, int>::iterator i = header->locked_pages.begin(); i != header->locked_pages.end(); ++i) { - pages[c] = i->second; - - c++; - - if (c == *count) - break; - } - } - - return TRUE; - } - - return FALSE; -} - -// ===================================================================== -// Memory IO Multipage functions -// ===================================================================== - -FIMULTIBITMAP * DLL_CALLCONV -FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags) { - BOOL read_only = FALSE; // modifications (if any) will be stored into the memory cache - - // retrieve the plugin list to find the node belonging to this plugin - - PluginList *list = FreeImage_GetPluginList(); - - if (list) { - PluginNode *node = list->FindNodeFromFIF(fif); - - if (node) { - FreeImageIO *io = new(std::nothrow) FreeImageIO; - - if (io) { - SetMemoryIO(io); - - FIMULTIBITMAP *bitmap = new(std::nothrow) FIMULTIBITMAP; - - if (bitmap) { - MULTIBITMAPHEADER *header = new(std::nothrow) MULTIBITMAPHEADER; - - if (header) { - header->m_filename = NULL; - header->node = node; - header->fif = fif; - header->io = 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; - - // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure - - bitmap->data = header; - - // cache the page count - - 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; - } - } - - return bitmap; - } - - delete bitmap; - } - - delete io; - } - } - } - - return NULL; -} - -BOOL DLL_CALLCONV -FreeImage_SaveMultiBitmapToMemory(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FIMEMORY *stream, int flags) { - if (stream && stream->data) { - FreeImageIO io; - SetMemoryIO(&io); - - return FreeImage_SaveMultiBitmapToHandle(fif, bitmap, &io, (fi_handle)stream, flags); - } - - return FALSE; -} diff --git a/plugins/AdvaImg/src/FreeImage/NNQuantizer.cpp b/plugins/AdvaImg/src/FreeImage/NNQuantizer.cpp deleted file mode 100644 index 4f02446d8e..0000000000 --- a/plugins/AdvaImg/src/FreeImage/NNQuantizer.cpp +++ /dev/null @@ -1,507 +0,0 @@ -// NeuQuant Neural-Net Quantization Algorithm -// ------------------------------------------ -// -// Copyright (c) 1994 Anthony Dekker -// -// NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. -// See "Kohonen neural networks for optimal colour quantization" -// in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367. -// for a discussion of the algorithm. -// -// Any party obtaining a copy of these files from the author, directly or -// indirectly, is granted, free of charge, a full and unrestricted irrevocable, -// world-wide, paid up, royalty-free, nonexclusive right and license to deal -// in this software and documentation files (the "Software"), including without -// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons who receive -// copies from any such party to do so, with the only requirement being -// that this copyright notice remain intact. - -/////////////////////////////////////////////////////////////////////// -// History -// ------- -// January 2001: Adaptation of the Neural-Net Quantization Algorithm -// for the FreeImage 2 library -// Author: Hervé Drolon (drolon@infonie.fr) -// March 2004: Adaptation for the FreeImage 3 library (port to big endian processors) -// Author: Hervé Drolon (drolon@infonie.fr) -// April 2004: Algorithm rewritten as a C++ class. -// Fixed a bug in the algorithm with handling of 4-byte boundary alignment. -// Author: Hervé Drolon (drolon@infonie.fr) -/////////////////////////////////////////////////////////////////////// - -#include "Quantizers.h" -#include "FreeImage.h" -#include "Utilities.h" - - -// Four primes near 500 - assume no image has a length so large -// that it is divisible by all four primes -// ========================================================== - -#define prime1 499 -#define prime2 491 -#define prime3 487 -#define prime4 503 - -// ---------------------------------------------------------------- - -NNQuantizer::NNQuantizer(int PaletteSize) -{ - netsize = PaletteSize; - maxnetpos = netsize - 1; - initrad = netsize < 8 ? 1 : (netsize >> 3); - initradius = (initrad * radiusbias); - - network = NULL; - - network = (pixel *)malloc(netsize * sizeof(pixel)); - bias = (int *)malloc(netsize * sizeof(int)); - freq = (int *)malloc(netsize * sizeof(int)); - radpower = (int *)malloc(initrad * sizeof(int)); - - if( !network || !bias || !freq || !radpower ) { - if(network) free(network); - if(bias) free(bias); - if(freq) free(freq); - if(radpower) free(radpower); - throw FI_MSG_ERROR_MEMORY; - } -} - -NNQuantizer::~NNQuantizer() -{ - if(network) free(network); - if(bias) free(bias); - if(freq) free(freq); - if(radpower) free(radpower); -} - -/////////////////////////////////////////////////////////////////////////// -// Initialise network in range (0,0,0) to (255,255,255) and set parameters -// ----------------------------------------------------------------------- - -void NNQuantizer::initnet() { - int i, *p; - - for (i = 0; i < netsize; i++) { - p = network[i]; - p[FI_RGBA_BLUE] = p[FI_RGBA_GREEN] = p[FI_RGBA_RED] = (i << (netbiasshift+8))/netsize; - freq[i] = intbias/netsize; /* 1/netsize */ - bias[i] = 0; - } -} - -/////////////////////////////////////////////////////////////////////////////////////// -// Unbias network to give byte values 0..255 and record position i to prepare for sort -// ------------------------------------------------------------------------------------ - -void NNQuantizer::unbiasnet() { - int i, j, temp; - - for (i = 0; i < netsize; i++) { - for (j = 0; j < 3; j++) { - // OLD CODE: network[i][j] >>= netbiasshift; - // Fix based on bug report by Juergen Weigert jw@suse.de - temp = (network[i][j] + (1 << (netbiasshift - 1))) >> netbiasshift; - if (temp > 255) temp = 255; - network[i][j] = temp; - } - network[i][3] = i; // record colour no - } -} - -////////////////////////////////////////////////////////////////////////////////// -// Insertion sort of network and building of netindex[0..255] (to do after unbias) -// ------------------------------------------------------------------------------- - -void NNQuantizer::inxbuild() { - int i,j,smallpos,smallval; - int *p,*q; - int previouscol,startpos; - - previouscol = 0; - startpos = 0; - for (i = 0; i < netsize; i++) { - p = network[i]; - smallpos = i; - smallval = p[FI_RGBA_GREEN]; // index on g - // find smallest in i..netsize-1 - for (j = i+1; j < netsize; j++) { - q = network[j]; - if (q[FI_RGBA_GREEN] < smallval) { // index on g - smallpos = j; - smallval = q[FI_RGBA_GREEN]; // index on g - } - } - q = network[smallpos]; - // swap p (i) and q (smallpos) entries - if (i != smallpos) { - j = q[FI_RGBA_BLUE]; q[FI_RGBA_BLUE] = p[FI_RGBA_BLUE]; p[FI_RGBA_BLUE] = j; - j = q[FI_RGBA_GREEN]; q[FI_RGBA_GREEN] = p[FI_RGBA_GREEN]; p[FI_RGBA_GREEN] = j; - j = q[FI_RGBA_RED]; q[FI_RGBA_RED] = p[FI_RGBA_RED]; p[FI_RGBA_RED] = j; - j = q[3]; q[3] = p[3]; p[3] = j; - } - // smallval entry is now in position i - if (smallval != previouscol) { - netindex[previouscol] = (startpos+i)>>1; - for (j = previouscol+1; j < smallval; j++) - netindex[j] = i; - previouscol = smallval; - startpos = i; - } - } - netindex[previouscol] = (startpos+maxnetpos)>>1; - for (j = previouscol+1; j < 256; j++) - netindex[j] = maxnetpos; // really 256 -} - -/////////////////////////////////////////////////////////////////////////////// -// Search for BGR values 0..255 (after net is unbiased) and return colour index -// ---------------------------------------------------------------------------- - -int NNQuantizer::inxsearch(int b, int g, int r) { - int i, j, dist, a, bestd; - int *p; - int best; - - bestd = 1000; // biggest possible dist is 256*3 - best = -1; - i = netindex[g]; // index on g - j = i-1; // start at netindex[g] and work outwards - - while ((i < netsize) || (j >= 0)) { - if (i < netsize) { - p = network[i]; - dist = p[FI_RGBA_GREEN] - g; // inx key - if (dist >= bestd) - i = netsize; // stop iter - else { - i++; - if (dist < 0) - dist = -dist; - a = p[FI_RGBA_BLUE] - b; - if (a < 0) - a = -a; - dist += a; - if (dist < bestd) { - a = p[FI_RGBA_RED] - r; - if (a<0) - a = -a; - dist += a; - if (dist < bestd) { - bestd = dist; - best = p[3]; - } - } - } - } - if (j >= 0) { - p = network[j]; - dist = g - p[FI_RGBA_GREEN]; // inx key - reverse dif - if (dist >= bestd) - j = -1; // stop iter - else { - j--; - if (dist < 0) - dist = -dist; - a = p[FI_RGBA_BLUE] - b; - if (a<0) - a = -a; - dist += a; - if (dist < bestd) { - a = p[FI_RGBA_RED] - r; - if (a<0) - a = -a; - dist += a; - if (dist < bestd) { - bestd = dist; - best = p[3]; - } - } - } - } - } - return best; -} - -/////////////////////////////// -// Search for biased BGR values -// ---------------------------- - -int NNQuantizer::contest(int b, int g, int r) { - // finds closest neuron (min dist) and updates freq - // finds best neuron (min dist-bias) and returns position - // for frequently chosen neurons, freq[i] is high and bias[i] is negative - // bias[i] = gamma*((1/netsize)-freq[i]) - - int i,dist,a,biasdist,betafreq; - int bestpos,bestbiaspos,bestd,bestbiasd; - int *p,*f, *n; - - bestd = ~(((int) 1)<<31); - bestbiasd = bestd; - bestpos = -1; - bestbiaspos = bestpos; - p = bias; - f = freq; - - for (i = 0; i < netsize; i++) { - n = network[i]; - dist = n[FI_RGBA_BLUE] - b; - if (dist < 0) - dist = -dist; - a = n[FI_RGBA_GREEN] - g; - if (a < 0) - a = -a; - dist += a; - a = n[FI_RGBA_RED] - r; - if (a < 0) - a = -a; - dist += a; - if (dist < bestd) { - bestd = dist; - bestpos = i; - } - biasdist = dist - ((*p)>>(intbiasshift-netbiasshift)); - if (biasdist < bestbiasd) { - bestbiasd = biasdist; - bestbiaspos = i; - } - betafreq = (*f >> betashift); - *f++ -= betafreq; - *p++ += (betafreq << gammashift); - } - freq[bestpos] += beta; - bias[bestpos] -= betagamma; - return bestbiaspos; -} - -/////////////////////////////////////////////////////// -// Move neuron i towards biased (b,g,r) by factor alpha -// ---------------------------------------------------- - -void NNQuantizer::altersingle(int alpha, int i, int b, int g, int r) { - int *n; - - n = network[i]; // alter hit neuron - n[FI_RGBA_BLUE] -= (alpha * (n[FI_RGBA_BLUE] - b)) / initalpha; - n[FI_RGBA_GREEN] -= (alpha * (n[FI_RGBA_GREEN] - g)) / initalpha; - n[FI_RGBA_RED] -= (alpha * (n[FI_RGBA_RED] - r)) / initalpha; -} - -//////////////////////////////////////////////////////////////////////////////////// -// Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|] -// --------------------------------------------------------------------------------- - -void NNQuantizer::alterneigh(int rad, int i, int b, int g, int r) { - int j, k, lo, hi, a; - int *p, *q; - - lo = i - rad; if (lo < -1) lo = -1; - hi = i + rad; if (hi > netsize) hi = netsize; - - j = i+1; - k = i-1; - q = radpower; - while ((j < hi) || (k > lo)) { - a = (*(++q)); - if (j < hi) { - p = network[j]; - p[FI_RGBA_BLUE] -= (a * (p[FI_RGBA_BLUE] - b)) / alpharadbias; - p[FI_RGBA_GREEN] -= (a * (p[FI_RGBA_GREEN] - g)) / alpharadbias; - p[FI_RGBA_RED] -= (a * (p[FI_RGBA_RED] - r)) / alpharadbias; - j++; - } - if (k > lo) { - p = network[k]; - p[FI_RGBA_BLUE] -= (a * (p[FI_RGBA_BLUE] - b)) / alpharadbias; - p[FI_RGBA_GREEN] -= (a * (p[FI_RGBA_GREEN] - g)) / alpharadbias; - p[FI_RGBA_RED] -= (a * (p[FI_RGBA_RED] - r)) / alpharadbias; - k--; - } - } -} - -///////////////////// -// Main Learning Loop -// ------------------ - -/** - Get a pixel sample at position pos. Handle 4-byte boundary alignment. - @param pos pixel position in a WxHx3 pixel buffer - @param b blue pixel component - @param g green pixel component - @param r red pixel component -*/ -void NNQuantizer::getSample(long pos, int *b, int *g, int *r) { - // get equivalent pixel coordinates - // - assume it's a 24-bit image - - int x = pos % img_line; - int y = pos / img_line; - - BYTE *bits = FreeImage_GetScanLine(dib_ptr, y) + x; - - *b = bits[FI_RGBA_BLUE] << netbiasshift; - *g = bits[FI_RGBA_GREEN] << netbiasshift; - *r = bits[FI_RGBA_RED] << netbiasshift; -} - -void NNQuantizer::learn(int sampling_factor) { - int i, j, b, g, r; - int radius, rad, alpha, step, delta, samplepixels; - int alphadec; // biased by 10 bits - long pos, lengthcount; - - // image size as viewed by the scan algorithm - lengthcount = img_width * img_height * 3; - - // number of samples used for the learning phase - samplepixels = lengthcount / (3 * sampling_factor); - - // decrease learning rate after delta pixel presentations - delta = samplepixels / ncycles; - if(delta == 0) { - // avoid a 'divide by zero' error with very small images - delta = 1; - } - - // initialize learning parameters - alphadec = 30 + ((sampling_factor - 1) / 3); - alpha = initalpha; - radius = initradius; - - rad = radius >> radiusbiasshift; - if (rad <= 1) rad = 0; - for (i = 0; i < rad; i++) - radpower[i] = alpha*(((rad*rad - i*i)*radbias)/(rad*rad)); - - // initialize pseudo-random scan - if ((lengthcount % prime1) != 0) - step = 3*prime1; - else { - if ((lengthcount % prime2) != 0) - step = 3*prime2; - else { - if ((lengthcount % prime3) != 0) - step = 3*prime3; - else - step = 3*prime4; - } - } - - i = 0; // iteration - pos = 0; // pixel position - - while (i < samplepixels) { - // get next learning sample - getSample(pos, &b, &g, &r); - - // find winning neuron - j = contest(b, g, r); - - // alter winner - altersingle(alpha, j, b, g, r); - - // alter neighbours - if (rad) alterneigh(rad, j, b, g, r); - - // next sample - pos += step; - while (pos >= lengthcount) pos -= lengthcount; - - i++; - if (i % delta == 0) { - // decrease learning rate and also the neighborhood - alpha -= alpha / alphadec; - radius -= radius / radiusdec; - rad = radius >> radiusbiasshift; - if (rad <= 1) rad = 0; - for (j = 0; j < rad; j++) - radpower[j] = alpha * (((rad*rad - j*j) * radbias) / (rad*rad)); - } - } - -} - -////////////// -// Quantizer -// ----------- - -FIBITMAP* NNQuantizer::Quantize(FIBITMAP *dib, int ReserveSize, RGBQUAD *ReservePalette, int sampling) { - - if ((!dib) || (FreeImage_GetBPP(dib) != 24)) { - return NULL; - } - - // 1) Select a sampling factor in range 1..30 (input parameter 'sampling') - // 1 => slower, 30 => faster. Default value is 1 - - - // 2) Get DIB parameters - - dib_ptr = dib; - - img_width = FreeImage_GetWidth(dib); // DIB width - img_height = FreeImage_GetHeight(dib); // DIB height - img_line = FreeImage_GetLine(dib); // DIB line length in bytes (should be equal to 3 x W) - - // For small images, adjust the sampling factor to avoid a 'divide by zero' error later - // (see delta in learn() routine) - int adjust = (img_width * img_height) / ncycles; - if(sampling >= adjust) - sampling = 1; - - - // 3) Initialize the network and apply the learning algorithm - - if( netsize > ReserveSize ) { - netsize -= ReserveSize; - initnet(); - learn(sampling); - unbiasnet(); - netsize += ReserveSize; - } - - // 3.5) Overwrite the last few palette entries with the reserved ones - for (int i = 0; i < ReserveSize; i++) { - network[netsize - ReserveSize + i][FI_RGBA_BLUE] = ReservePalette[i].rgbBlue; - network[netsize - ReserveSize + i][FI_RGBA_GREEN] = ReservePalette[i].rgbGreen; - network[netsize - ReserveSize + i][FI_RGBA_RED] = ReservePalette[i].rgbRed; - network[netsize - ReserveSize + i][3] = netsize - ReserveSize + i; - } - - // 4) Allocate a new 8-bit DIB - - FIBITMAP *new_dib = FreeImage_Allocate(img_width, img_height, 8); - - if (new_dib == NULL) - return NULL; - - // 5) Write the quantized palette - - RGBQUAD *new_pal = FreeImage_GetPalette(new_dib); - - for (int j = 0; j < netsize; j++) { - new_pal[j].rgbBlue = (BYTE)network[j][FI_RGBA_BLUE]; - new_pal[j].rgbGreen = (BYTE)network[j][FI_RGBA_GREEN]; - new_pal[j].rgbRed = (BYTE)network[j][FI_RGBA_RED]; - } - - inxbuild(); - - // 6) Write output image using inxsearch(b,g,r) - - for (WORD rows = 0; rows < img_height; rows++) { - BYTE *new_bits = FreeImage_GetScanLine(new_dib, rows); - BYTE *bits = FreeImage_GetScanLine(dib_ptr, rows); - - for (WORD cols = 0; cols < img_width; cols++) { - new_bits[cols] = (BYTE)inxsearch(bits[FI_RGBA_BLUE], bits[FI_RGBA_GREEN], bits[FI_RGBA_RED]); - - bits += 3; - } - } - - return (FIBITMAP*) new_dib; -} diff --git a/plugins/AdvaImg/src/FreeImage/PSDParser.cpp b/plugins/AdvaImg/src/FreeImage/PSDParser.cpp deleted file mode 100644 index fba54c2421..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PSDParser.cpp +++ /dev/null @@ -1,1057 +0,0 @@ -// ========================================================== -// Photoshop Loader -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// Based on LGPL code created and published by http://sourceforge.net/projects/elynx/ -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "PSDParser.h" - -// -------------------------------------------------------------------------- - -// PSD signature (= '8BPS') -#define PSD_SIGNATURE 0x38425053 -// Image resource block signature (= '8BIM') -#define PSD_RESOURCE 0x3842494D - -// PSD color modes -#define PSDP_BITMAP 0 -#define PSDP_GRAYSCALE 1 -#define PSDP_INDEXED 2 -#define PSDP_RGB 3 -#define PSDP_CMYK 4 -#define PSDP_MULTICHANNEL 7 -#define PSDP_DUOTONE 8 -#define PSDP_LAB 9 - -// PSD compression schemes -#define PSDP_COMPRESSION_NONE 0 // Raw data -#define PSDP_COMPRESSION_RLE 1 // RLE compression (same as TIFF packed bits) - -#define SAFE_DELETE_ARRAY(_p_) { if (NULL != (_p_)) { delete [] (_p_); (_p_) = NULL; } } - -// -------------------------------------------------------------------------- - -static inline int -psdGetValue(const BYTE * iprBuffer, const int iBytes) { - int v = iprBuffer[0]; - for (int i=1; i<iBytes; ++i) { - v = (v << 8) | iprBuffer[i]; - } - return v; -} - -// -------------------------------------------------------------------------- - -psdHeaderInfo::psdHeaderInfo() : _Channels(-1), _Height(-1), _Width(-1), _BitsPerChannel(-1), _ColourMode(-1) { -} - -psdHeaderInfo::~psdHeaderInfo() { -} - -bool psdHeaderInfo::Read(FreeImageIO *io, fi_handle handle) { - psdHeader header; - - const int n = (int)io->read_proc(&header, sizeof(header), 1, handle); - if(!n) { - return false; - } - - // check the signature - int nSignature = psdGetValue(header.Signature, sizeof(header.Signature)); - if (PSD_SIGNATURE == nSignature) { - // check the version - int nVersion = psdGetValue( header.Version, sizeof(header.Version) ); - if (1 == nVersion) { - // header.Reserved must be zero - BYTE psd_reserved[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - if(memcmp(header.Reserved, psd_reserved, 6) != 0) { - FreeImage_OutputMessageProc(FIF_PSD, "Warning: file header reserved member is not equal to zero"); - } - // read the header - _Channels = (short)psdGetValue( header.Channels, sizeof(header.Channels) ); - _Height = psdGetValue( header.Rows, sizeof(header.Rows) ); - _Width = psdGetValue( header.Columns, sizeof(header.Columns) ); - _BitsPerChannel = (short)psdGetValue( header.Depth, sizeof(header.Depth) ); - _ColourMode = (short)psdGetValue( header.Mode, sizeof(header.Mode) ); - - return true; - } - } - - return false; -} - -// -------------------------------------------------------------------------- - -psdColourModeData::psdColourModeData() : _Length(-1), _plColourData(NULL) { -} - -psdColourModeData::~psdColourModeData() { - SAFE_DELETE_ARRAY(_plColourData); -} - -bool psdColourModeData::Read(FreeImageIO *io, fi_handle handle) { - if (0 < _Length) { - SAFE_DELETE_ARRAY(_plColourData); - } - - BYTE Length[4]; - io->read_proc(&Length, sizeof(Length), 1, handle); - - _Length = psdGetValue( Length, sizeof(_Length) ); - if (0 < _Length) { - _plColourData = new BYTE[_Length]; - io->read_proc(_plColourData, _Length, 1, handle); - } - - return true; -} - -bool psdColourModeData::FillPalette(FIBITMAP *dib) { - RGBQUAD *pal = FreeImage_GetPalette(dib); - if(pal) { - for (int i = 0; i < 256; i++) { - pal[i].rgbRed = _plColourData[i + 0*256]; - pal[i].rgbGreen = _plColourData[i + 1*256]; - pal[i].rgbBlue = _plColourData[i + 2*256]; - } - return true; - } - return false; -} - -// -------------------------------------------------------------------------- - -psdImageResource::psdImageResource() : _plName (0) { - Reset(); -} - -psdImageResource::~psdImageResource() { - SAFE_DELETE_ARRAY(_plName); -} - -void psdImageResource::Reset() { - _Length = -1; - memset( _OSType, '\0', sizeof(_OSType) ); - _ID = -1; - SAFE_DELETE_ARRAY(_plName); - _Size = -1; -} - -// -------------------------------------------------------------------------- - -psdResolutionInfo::psdResolutionInfo() : _widthUnit(-1), _heightUnit(-1), _hRes(-1), _vRes(-1), _hResUnit(-1), _vResUnit(-1) { -} - -psdResolutionInfo::~psdResolutionInfo() { -} - -int psdResolutionInfo::Read(FreeImageIO *io, fi_handle handle) { - BYTE IntValue[4], ShortValue[2]; - int nBytes=0, n; - - // Horizontal resolution in pixels per inch. - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _hRes = (short)psdGetValue(ShortValue, sizeof(_hRes) ); - // 1=display horizontal resolution in pixels per inch; 2=display horizontal resolution in pixels per cm. - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _hResUnit = psdGetValue(IntValue, sizeof(_hResUnit) ); - // Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns. - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _widthUnit = (short)psdGetValue(ShortValue, sizeof(_widthUnit) ); - // Vertical resolution in pixels per inch. - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _vRes = (short)psdGetValue(ShortValue, sizeof(_vRes) ); - // 1=display vertical resolution in pixels per inch; 2=display vertical resolution in pixels per cm. - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _vResUnit = psdGetValue(IntValue, sizeof(_vResUnit) ); - // Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns. - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _heightUnit = (short)psdGetValue(ShortValue, sizeof(_heightUnit) ); - - return nBytes; -} - -void psdResolutionInfo::GetResolutionInfo(unsigned &res_x, unsigned &res_y) { - if(_hResUnit == 1) { - // convert pixels / inch to pixel / m - res_x = (unsigned) (_hRes / 0.0254000 + 0.5); - } else if(_hResUnit == 2) { - // convert pixels / cm to pixel / m - res_x = (unsigned) (_hRes * 100.0 + 0.5); - } - if(_vResUnit == 1) { - // convert pixels / inch to pixel / m - res_y = (unsigned) (_vRes / 0.0254000 + 0.5); - } else if(_vResUnit == 2) { - // convert pixels / cm to pixel / m - res_y = (unsigned) (_vRes * 100.0 + 0.5); - } -} - -// -------------------------------------------------------------------------- - -psdResolutionInfo_v2::psdResolutionInfo_v2() { - _Channels = _Rows = _Columns = _Depth = _Mode = -1; -} - -psdResolutionInfo_v2::~psdResolutionInfo_v2() { -} - -int psdResolutionInfo_v2::Read(FreeImageIO *io, fi_handle handle) { - BYTE ShortValue[2]; - int nBytes=0, n; - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Channels = (short)psdGetValue(ShortValue, sizeof(_Channels) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Rows = (short)psdGetValue(ShortValue, sizeof(_Rows) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Columns = (short)psdGetValue(ShortValue, sizeof(_Columns) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Depth = (short)psdGetValue(ShortValue, sizeof(_Depth) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Mode = (short)psdGetValue(ShortValue, sizeof(_Mode) ); - - return nBytes; -} - -// -------------------------------------------------------------------------- - -psdDisplayInfo::psdDisplayInfo() { - _Opacity = _ColourSpace = -1; - for (unsigned n = 0; n < 4; ++n) { - _Colour[n] = 0; - } - _Kind = 0; - _padding = '0'; -} - -psdDisplayInfo::~psdDisplayInfo() { -} - -int psdDisplayInfo::Read(FreeImageIO *io, fi_handle handle) { - BYTE ShortValue[2]; - int nBytes=0, n; - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _ColourSpace = (short)psdGetValue(ShortValue, sizeof(_ColourSpace) ); - - for (unsigned i = 0; i < 4; ++i) { - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Colour[i] = (short)psdGetValue(ShortValue, sizeof(_Colour[i]) ); - } - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Opacity = (short)psdGetValue(ShortValue, sizeof(_Opacity) ); - if((_Opacity < 0) || (_Opacity > 100)) { - throw "Invalid DisplayInfo::Opacity value"; - } - - BYTE c[1]; - n = (int)io->read_proc(&c, sizeof(c), 1, handle); - nBytes += n * sizeof(c); - _Kind = (BYTE)psdGetValue(c, sizeof(c)); - - n = (int)io->read_proc(&c, sizeof(c), 1, handle); - nBytes += n * sizeof(c); - _padding = (BYTE)psdGetValue(c, sizeof(c)); - if(_padding != 0) { - throw "Invalid DisplayInfo::Padding value"; - } - - return nBytes; -} - -// -------------------------------------------------------------------------- - -psdThumbnail::psdThumbnail() : -_Format(-1), _Width(-1), _Height(-1), _WidthBytes(-1), _Size(-1), _CompressedSize(-1), _BitPerPixel(-1), _Planes(-1), _dib(NULL) { -} - -psdThumbnail::~psdThumbnail() { - FreeImage_Unload(_dib); -} - -int psdThumbnail::Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR) { - BYTE ShortValue[2], IntValue[4]; - int nBytes=0, n; - - // remove the header size (28 bytes) from the total data size - int iTotalData = iResourceSize - 28; - - const long block_end = io->tell_proc(handle) + iTotalData; - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _Format = psdGetValue(IntValue, sizeof(_Format) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _Width = psdGetValue(IntValue, sizeof(_Width) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _Height = psdGetValue(IntValue, sizeof(_Height) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _WidthBytes = psdGetValue(IntValue, sizeof(_WidthBytes) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _Size = psdGetValue(IntValue, sizeof(_Size) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _CompressedSize = psdGetValue(IntValue, sizeof(_CompressedSize) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _BitPerPixel = (short)psdGetValue(ShortValue, sizeof(_BitPerPixel) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Planes = (short)psdGetValue(ShortValue, sizeof(_Planes) ); - - const long JFIF_startpos = io->tell_proc(handle); - - if(_dib) { - FreeImage_Unload(_dib); - } - - if(_Format == 1) { - // kJpegRGB thumbnail image - _dib = FreeImage_LoadFromHandle(FIF_JPEG, io, handle); - if(isBGR) { - SwapRedBlue32(_dib); - } - // HACK: manually go to end of thumbnail, because (for some reason) LoadFromHandle consumes more bytes then available! - io->seek_proc(handle, block_end, SEEK_SET); - } - else { - // kRawRGB thumbnail image - // ### Unimplemented (should be trivial) - - // skip the thumbnail part - io->seek_proc(handle, iTotalData, SEEK_CUR); - return iResourceSize; - } - - nBytes += (block_end - JFIF_startpos); - - return nBytes; -} - -//--------------------------------------------------------------------------- - -psdICCProfile::psdICCProfile() : _ProfileSize(0), _ProfileData(NULL) { -} - -psdICCProfile::~psdICCProfile() { - clear(); -} - -void psdICCProfile::clear() { SAFE_DELETE_ARRAY(_ProfileData); _ProfileSize = 0;} - -int psdICCProfile::Read(FreeImageIO *io, fi_handle handle, int size) { - int nBytes = 0, n; - - clear(); - - _ProfileData = new (std::nothrow) BYTE[size]; - if(NULL != _ProfileData) { - n = (int)io->read_proc(_ProfileData, 1, size, handle); - _ProfileSize = size; - nBytes += n * sizeof(BYTE); - } - - return nBytes; -} - -//--------------------------------------------------------------------------- - -/** -Invert only color components, skipping Alpha/Black -(Can be useful as public/utility function) -*/ -static -BOOL invertColor(FIBITMAP* dib) { - FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); - const unsigned Bpp = FreeImage_GetBPP(dib)/8; - - if((type == FIT_BITMAP && Bpp == 4) || type == FIT_RGBA16) { - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - BYTE *line_start = FreeImage_GetScanLine(dib, 0); - const unsigned pitch = FreeImage_GetPitch(dib); - const unsigned triBpp = Bpp - (Bpp == 4 ? 1 : 2); - - for(unsigned y = 0; y < height; y++) { - BYTE *line = line_start; - - for(unsigned x = 0; x < width; x++) { - for(unsigned b=0; b < triBpp; ++b) { - line[b] = ~line[b]; - } - - line += Bpp; - } - line_start += pitch; - } - - return TRUE; - } - else { - return FreeImage_Invert(dib); - } -} - -//--------------------------------------------------------------------------- - -psdParser::psdParser() { - _bThumbnailFilled = false; - _bDisplayInfoFilled = false; - _bResolutionInfoFilled = false; - _bResolutionInfoFilled_v2 = false; - _bCopyright = false; - _GlobalAngle = 30; - _ColourCount = -1; - _TransparentIndex = -1; - _fi_flags = 0; - _fi_format_id = FIF_UNKNOWN; -} - -psdParser::~psdParser() { -} - -bool psdParser::ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle) { - bool bSuccess = false; - - BYTE DataLength[4]; - int nBytes = 0; - int n = (int)io->read_proc(&DataLength, sizeof(DataLength), 1, handle); - int nTotalBytes = psdGetValue( DataLength, sizeof(DataLength) ); - - BYTE data[1]; - while( n && ( nBytes < nTotalBytes ) ) { - data[0] = '\0'; - n = (int)io->read_proc(&data, sizeof(data), 1, handle); - nBytes += n * sizeof(data); - } - - if ( nBytes == nTotalBytes ) { - bSuccess = true; - } - - return bSuccess; -} - -bool psdParser::ReadImageResources(FreeImageIO *io, fi_handle handle, LONG length) { - psdImageResource oResource; - bool bSuccess = false; - - if(length > 0) { - oResource._Length = length; - } else { - BYTE Length[4]; - int n = (int)io->read_proc(&Length, sizeof(Length), 1, handle); - - oResource._Length = psdGetValue( Length, sizeof(oResource._Length) ); - } - - int nBytes = 0; - int nTotalBytes = oResource._Length; - - while(nBytes < nTotalBytes) { - int n = 0; - oResource.Reset(); - - n = (int)io->read_proc(&oResource._OSType, sizeof(oResource._OSType), 1, handle); - if(n != 1) { - FreeImage_OutputMessageProc(_fi_format_id, "This file contains damaged data causing an unexpected end-of-file - stop reading resources"); - return false; - } - nBytes += n * sizeof(oResource._OSType); - - if( (nBytes % 2) != 0 ) { - return false; - } - - int nOSType = psdGetValue((BYTE*)&oResource._OSType, sizeof(oResource._OSType)); - - if ( PSD_RESOURCE == nOSType ) { - BYTE ID[2]; - n = (int)io->read_proc(&ID, sizeof(ID), 1, handle); - nBytes += n * sizeof(ID); - - oResource._ID = (short)psdGetValue( ID, sizeof(ID) ); - - BYTE SizeOfName; - n = (int)io->read_proc(&SizeOfName, sizeof(SizeOfName), 1, handle); - nBytes += n * sizeof(SizeOfName); - - int nSizeOfName = psdGetValue( &SizeOfName, sizeof(SizeOfName) ); - if ( 0 < nSizeOfName ) { - oResource._plName = new BYTE[nSizeOfName]; - n = (int)io->read_proc(oResource._plName, nSizeOfName, 1, handle); - nBytes += n * nSizeOfName; - } - - if ( 0 == (nSizeOfName % 2) ) { - n = (int)io->read_proc(&SizeOfName, sizeof(SizeOfName), 1, handle); - nBytes += n * sizeof(SizeOfName); - } - - BYTE Size[4]; - n = (int)io->read_proc(&Size, sizeof(Size), 1, handle); - nBytes += n * sizeof(Size); - - oResource._Size = psdGetValue( Size, sizeof(oResource._Size) ); - - if ( 0 != (oResource._Size % 2) ) { - // resource data must be even - oResource._Size++; - } - if ( 0 < oResource._Size ) { - BYTE IntValue[4]; - BYTE ShortValue[2]; - - switch( oResource._ID ) { - case 1000: - // Obsolete - Photoshop 2.0 - _bResolutionInfoFilled_v2 = true; - nBytes += _resolutionInfo_v2.Read(io, handle); - break; - - // ResolutionInfo structure - case 1005: - _bResolutionInfoFilled = true; - nBytes += _resolutionInfo.Read(io, handle); - break; - - // DisplayInfo structure - case 1007: - _bDisplayInfoFilled = true; - nBytes += _displayInfo.Read(io, handle); - break; - - // (Photoshop 4.0) Copyright flag - // Boolean indicating whether image is copyrighted. Can be set via Property suite or by user in File Info... - case 1034: - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _bCopyright = (1 == psdGetValue(ShortValue, sizeof(ShortValue))); - break; - - // (Photoshop 4.0) Thumbnail resource for Photoshop 4.0 only - case 1033: - // (Photoshop 5.0) Thumbnail resource (supersedes resource 1033) - case 1036: - { - _bThumbnailFilled = true; - bool bBGR = (1033==oResource._ID); - nBytes += _thumbnail.Read(io, handle, oResource._Size, bBGR); - break; - } - - // (Photoshop 5.0) Global Angle - // 4 bytes that contain an integer between 0 and 359, which is the global - // lighting angle for effects layer. If not present, assumed to be 30. - case 1037: - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _GlobalAngle = psdGetValue(IntValue, sizeof(_GlobalAngle) ); - break; - - // ICC profile - case 1039: - nBytes += _iccProfile.Read(io, handle, oResource._Size); - break; - - // (Photoshop 6.0) Indexed Color Table Count - // 2 bytes for the number of colors in table that are actually defined - case 1046: - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _ColourCount = (short)psdGetValue(ShortValue, sizeof(ShortValue) ); - break; - - // (Photoshop 6.0) Transparency Index. - // 2 bytes for the index of transparent color, if any. - case 1047: - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _TransparentIndex = (short)psdGetValue(ShortValue, sizeof(ShortValue) ); - break; - - default: - { - // skip resource - unsigned skip_length = MIN(oResource._Size, nTotalBytes - nBytes); - io->seek_proc(handle, skip_length, SEEK_CUR); - nBytes += skip_length; - } - break; - } - } - } - } - - if (nBytes == nTotalBytes) { - bSuccess = true; - } - - return bSuccess; - -} - -FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) { - if(handle == NULL) - return NULL; - - bool header_only = (_fi_flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - WORD nCompression = 0; - io->read_proc(&nCompression, sizeof(nCompression), 1, handle); - -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(&nCompression); -#endif - - if((nCompression != PSDP_COMPRESSION_NONE && nCompression != PSDP_COMPRESSION_RLE)) { - FreeImage_OutputMessageProc(_fi_format_id, "Unsupported compression %d", nCompression); - return NULL; - } - - const unsigned nWidth = _headerInfo._Width; - const unsigned nHeight = _headerInfo._Height; - const unsigned nChannels = _headerInfo._Channels; - const unsigned depth = _headerInfo._BitsPerChannel; - const unsigned bytes = (depth == 1) ? 1 : depth / 8; - - // channel(plane) line (BYTE aligned) - const unsigned lineSize = (_headerInfo._BitsPerChannel == 1) ? (nWidth + 7) / 8 : nWidth * bytes; - - if(nCompression == PSDP_COMPRESSION_RLE && depth > 16) { - FreeImage_OutputMessageProc(_fi_format_id, "Unsupported RLE with depth %d", depth); - return NULL; - } - - // build output buffer - - FIBITMAP* bitmap = NULL; - unsigned dstCh = 0; - - short mode = _headerInfo._ColourMode; - - if(mode == PSDP_MULTICHANNEL && nChannels < 3) { - // CM - mode = PSDP_GRAYSCALE; // C as gray, M as extra channel - } - - bool needPalette = false; - switch (mode) { - case PSDP_BITMAP: - case PSDP_DUOTONE: - case PSDP_INDEXED: - case PSDP_GRAYSCALE: - dstCh = 1; - switch(depth) { - case 16: - bitmap = FreeImage_AllocateHeaderT(header_only, FIT_UINT16, nWidth, nHeight, depth*dstCh); - break; - case 32: - bitmap = FreeImage_AllocateHeaderT(header_only, FIT_FLOAT, nWidth, nHeight, depth*dstCh); - break; - default: // 1-, 8- - needPalette = true; - bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); - break; - } - break; - case PSDP_RGB: - case PSDP_LAB: - case PSDP_CMYK : - case PSDP_MULTICHANNEL : - // force PSDP_MULTICHANNEL CMY as CMYK - dstCh = (mode == PSDP_MULTICHANNEL && !header_only) ? 4 : MIN<unsigned>(nChannels, 4); - if(dstCh < 3) { - throw "Invalid number of channels"; - } - - switch(depth) { - case 16: - bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGB16 : FIT_RGBA16, nWidth, nHeight, depth*dstCh); - break; - case 32: - bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGBF : FIT_RGBAF, nWidth, nHeight, depth*dstCh); - break; - default: - bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); - break; - } - break; - default: - throw "Unsupported color mode"; - break; - } - if(!bitmap) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // write thumbnail - FreeImage_SetThumbnail(bitmap, _thumbnail.getDib()); - - // @todo Add some metadata model - - if(header_only) { - return bitmap; - } - - // Load pixels data - - const unsigned dstChannels = dstCh; - - const unsigned dstBpp = (depth == 1) ? 1 : FreeImage_GetBPP(bitmap)/8; - const unsigned dstLineSize = FreeImage_GetPitch(bitmap); - BYTE* const dst_first_line = FreeImage_GetScanLine(bitmap, nHeight - 1);//<*** flipped - - BYTE* line_start = new BYTE[lineSize]; //< fileline cache - - switch ( nCompression ) { - case PSDP_COMPRESSION_NONE: // raw data - { - for(unsigned c = 0; c < nChannels; c++) { - if(c >= dstChannels) { - // @todo write extra channels - break; - } - - const unsigned channelOffset = c * bytes; - - BYTE* dst_line_start = dst_first_line; - for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped - - io->read_proc(line_start, lineSize, 1, handle); - - for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; - line += bytes, dst_line += dstBpp) { -#ifdef FREEIMAGE_BIGENDIAN - memcpy(dst_line + channelOffset, line, bytes); -#else - // reverse copy bytes - for (unsigned b = 0; b < bytes; ++b) { - dst_line[channelOffset + b] = line[(bytes-1) - b]; - } -#endif // FREEIMAGE_BIGENDIAN - } - } //< h - }//< ch - - SAFE_DELETE_ARRAY(line_start); - - } - break; - - case PSDP_COMPRESSION_RLE: // RLE compression - { - - // The RLE-compressed data is preceeded by a 2-byte line size for each row in the data, - // store an array of these - - // later use this array as WORD rleLineSizeList[nChannels][nHeight]; - WORD *rleLineSizeList = new (std::nothrow) WORD[nChannels*nHeight]; - - if(!rleLineSizeList) { - FreeImage_Unload(bitmap); - SAFE_DELETE_ARRAY(line_start); - throw std::bad_alloc(); - } - - io->read_proc(rleLineSizeList, 2, nChannels * nHeight, handle); - - WORD largestRLELine = 0; - for(unsigned ch = 0; ch < nChannels; ++ch) { - for(unsigned h = 0; h < nHeight; ++h) { - const unsigned index = ch * nHeight + h; - -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(&rleLineSizeList[index]); -#endif - if(largestRLELine < rleLineSizeList[index]) { - largestRLELine = rleLineSizeList[index]; - } - } - } - - BYTE* rle_line_start = new (std::nothrow) BYTE[largestRLELine]; - if(!rle_line_start) { - FreeImage_Unload(bitmap); - SAFE_DELETE_ARRAY(line_start); - SAFE_DELETE_ARRAY(rleLineSizeList); - throw std::bad_alloc(); - } - - // Read the RLE data (assume 8-bit) - - const BYTE* const line_end = line_start + lineSize; - - for (unsigned ch = 0; ch < nChannels; ch++) { - const unsigned channelOffset = ch * bytes; - - BYTE* dst_line_start = dst_first_line; - for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped - const unsigned index = ch * nHeight + h; - - // - read and uncompress line - - - const WORD rleLineSize = rleLineSizeList[index]; - - io->read_proc(rle_line_start, rleLineSize, 1, handle); - - for (BYTE* rle_line = rle_line_start, *line = line_start; - rle_line < rle_line_start + rleLineSize, line < line_end;) { - - int len = *rle_line++; - - // NOTE len is signed byte in PackBits RLE - - if ( len < 128 ) { //<- MSB is not set - // uncompressed packet - - // (len + 1) bytes of data are copied - - ++len; - - // assert we don't write beyound eol - memcpy(line, rle_line, line + len > line_end ? line_end - line : len); - line += len; - rle_line += len; - } - else if ( len > 128 ) { //< MSB is set - - // RLE compressed packet - - // One byte of data is repeated (–len + 1) times - - len ^= 0xFF; // same as (-len + 1) & 0xFF - len += 2; // - - // assert we don't write beyound eol - memset(line, *rle_line++, line + len > line_end ? line_end - line : len); - line += len; - - } - else if ( 128 == len ) { - // Do nothing - } - }//< rle_line - - // - write line to destination - - - if(ch >= dstChannels) { - // @todo write to extra channels - break; - } - - // byte by byte copy a single channel to pixel - for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; - line += bytes, dst_line += dstBpp) { - -#ifdef FREEIMAGE_BIGENDIAN - memcpy(dst_line + channelOffset, line, bytes); -#else - // reverse copy bytes - for (unsigned b = 0; b < bytes; ++b) { - dst_line[channelOffset + b] = line[(bytes-1) - b]; - } -#endif // FREEIMAGE_BIGENDIAN - } - }//< h - }//< ch - - SAFE_DELETE_ARRAY(line_start); - SAFE_DELETE_ARRAY(rleLineSizeList); - SAFE_DELETE_ARRAY(rle_line_start); - } - break; - - case 2: // ZIP without prediction, no specification - break; - - case 3: // ZIP with prediction, no specification - break; - - default: // Unknown format - break; - - } - - // --- Further process the bitmap --- - - if((mode == PSDP_CMYK || mode == PSDP_MULTICHANNEL)) { - // CMYK values are "inverted", invert them back - - if(mode == PSDP_MULTICHANNEL) { - invertColor(bitmap); - } else { - FreeImage_Invert(bitmap); - } - - if((_fi_flags & PSD_CMYK) == PSD_CMYK) { - // keep as CMYK - - if(mode == PSDP_MULTICHANNEL) { - //### we force CMY to be CMYK, but CMY has no ICC. - // Create empty profile and add the flag. - FreeImage_CreateICCProfile(bitmap, NULL, 0); - FreeImage_GetICCProfile(bitmap)->flags |= FIICC_COLOR_IS_CMYK; - } - } - else { - // convert to RGB - - ConvertCMYKtoRGBA(bitmap); - - // The ICC Profile is no longer valid - _iccProfile.clear(); - - // remove the pending A if not present in source - if(nChannels == 4 || nChannels == 3 ) { - FIBITMAP* t = RemoveAlphaChannel(bitmap); - if(t) { - FreeImage_Unload(bitmap); - bitmap = t; - } // else: silently fail - } - } - } - else if ( mode == PSDP_LAB && !((_fi_flags & PSD_LAB) == PSD_LAB)) { - ConvertLABtoRGB(bitmap); - } - else { - if (needPalette && FreeImage_GetPalette(bitmap)) { - - if(mode == PSDP_BITMAP) { - CREATE_GREYSCALE_PALETTE_REVERSE(FreeImage_GetPalette(bitmap), 2); - } - else if(mode == PSDP_INDEXED) { - if(!_colourModeData._plColourData || _colourModeData._Length != 768 || _ColourCount < 0) { - FreeImage_OutputMessageProc(_fi_format_id, "Indexed image has no palette. Using the default grayscale one."); - } else { - _colourModeData.FillPalette(bitmap); - } - } - // GRAYSCALE, DUOTONE - use default grayscale palette - } - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - if(FreeImage_GetImageType(bitmap) == FIT_BITMAP) { - SwapRedBlue32(bitmap); - } -#endif - } - - return bitmap; -} - -FIBITMAP* psdParser::Load(FreeImageIO *io, fi_handle handle, int s_format_id, int flags) { - FIBITMAP *Bitmap = NULL; - - _fi_flags = flags; - _fi_format_id = s_format_id; - - try { - if (NULL == handle) { - throw("Cannot open file"); - } - - if (!_headerInfo.Read(io, handle)) { - throw("Error in header"); - } - - if (!_colourModeData.Read(io, handle)) { - throw("Error in ColourMode Data"); - } - - if (!ReadImageResources(io, handle)) { - throw("Error in Image Resource"); - } - - if (!ReadLayerAndMaskInfoSection(io, handle)) { - throw("Error in Mask Info"); - } - - Bitmap = ReadImageData(io, handle); - if (NULL == Bitmap) { - throw("Error in Image Data"); - } - - // set resolution info - if(NULL != Bitmap) { - unsigned res_x = 2835; // 72 dpi - unsigned res_y = 2835; // 72 dpi - if (_bResolutionInfoFilled) { - _resolutionInfo.GetResolutionInfo(res_x, res_y); - } - FreeImage_SetDotsPerMeterX(Bitmap, res_x); - FreeImage_SetDotsPerMeterY(Bitmap, res_y); - } - - // set ICC profile - FreeImage_CreateICCProfile(Bitmap, _iccProfile._ProfileData, _iccProfile._ProfileSize); - if ((flags & PSD_CMYK) == PSD_CMYK) { - short mode = _headerInfo._ColourMode; - if((mode == PSDP_CMYK) || (mode == PSDP_MULTICHANNEL)) { - FreeImage_GetICCProfile(Bitmap)->flags |= FIICC_COLOR_IS_CMYK; - } - } - - } catch(const char *text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - catch(const std::exception& e) { - FreeImage_OutputMessageProc(s_format_id, "%s", e.what()); - } - - return Bitmap; -} diff --git a/plugins/AdvaImg/src/FreeImage/PSDParser.h b/plugins/AdvaImg/src/FreeImage/PSDParser.h deleted file mode 100644 index 15ab5425ca..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PSDParser.h +++ /dev/null @@ -1,271 +0,0 @@ -// ========================================================== -// Photoshop Loader -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// Based on LGPL code created and published by http://sourceforge.net/projects/elynx/ -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#ifndef PSDPARSER_H -#define PSDPARSER_H - -/** -Table 2-12: File header section. -The file header contains the basic properties of the image. -*/ -typedef struct psdHeader { - BYTE Signature[4]; //! Always equal 8BPS, do not try to read the file if the signature does not match this value. - BYTE Version[2]; //! Always equal 1, do not read file if the version does not match this value. - char Reserved[6]; //! Must be zero. - BYTE Channels[2]; //! Number of channels including any alpha channels, supported range is 1 to 24. - BYTE Rows[4]; //! The height of the image in pixels. Supported range is 1 to 30,000. - BYTE Columns[4]; //! The width of the image in pixels. Supported range is 1 to 30,000. - BYTE Depth[2]; //! The number of bits per channel. Supported values are 1, 8, and 16. - BYTE Mode[2]; //! Colour mode of the file, Bitmap=0, Grayscale=1, Indexed=2, RGB=3, CMYK=4, Multichannel=7, Duotone=8, Lab=9. -} psdHeader; - -/** -Table 2-12: HeaderInfo Color spaces -@see psdHeader -*/ -class psdHeaderInfo { -public: - short _Channels; //! Numer of channels including any alpha channels, supported range is 1 to 24. - int _Height; //! The height of the image in pixels. Supported range is 1 to 30,000. - int _Width; //! The width of the image in pixels. Supported range is 1 to 30,000. - short _BitsPerChannel;//! The number of bits per channel. Supported values are 1, 8, and 16. - short _ColourMode; //! Colour mode of the file, Bitmap=0, Grayscale=1, Indexed=2, RGB=3, CMYK=4, Multichannel=7, Duotone=8, Lab=9. - -public: - psdHeaderInfo(); - ~psdHeaderInfo(); - /** - @return Returns the number of bytes read - */ - bool Read(FreeImageIO *io, fi_handle handle); -}; - -/** -Table 2-13 Color mode data section - -Only indexed color and duotone have color mode data. For all other modes, -this section is just 4 bytes: the length field, which is set to zero. -For indexed color images, the length will be equal to 768, and the color data -will contain the color table for the image, in non-interleaved order. -For duotone images, the color data will contain the duotone specification, -the format of which is not documented. Other applications that read -Photoshop files can treat a duotone image as a grayscale image, and just -preserve the contents of the duotone information when reading and writing -the file. -*/ -class psdColourModeData { -public: - int _Length; //! The length of the following color data - BYTE * _plColourData; //! The color data - -public: - psdColourModeData(); - ~psdColourModeData(); - /** - @return Returns the number of bytes read - */ - bool Read(FreeImageIO *io, fi_handle handle); - bool FillPalette(FIBITMAP *dib); -}; - -/** -Table 2-1: Image resource block -NB: Resource data is padded to make size even -*/ -class psdImageResource { -public: - int _Length; - char _OSType[4]; //! Photoshop always uses its signature, 8BIM - short _ID; //! Unique identifier. Image resource IDs on page 8 - BYTE * _plName; //! A pascal string, padded to make size even (a null name consists of two bytes of 0) - int _Size; //! Actual size of resource data. This does not include the Type, ID, Name or Size fields. - -public: - psdImageResource(); - ~psdImageResource(); - void Reset(); -}; - -/** -Table A-6: ResolutionInfo structure -This structure contains information about the resolution of an image. It is -written as an image resource. See the Document file formats chapter for more -details. -*/ -class psdResolutionInfo { -public: - short _widthUnit; //! Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns. - short _heightUnit; //! Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns. - short _hRes; //! Horizontal resolution in pixels per inch. - short _vRes; //! Vertical resolution in pixels per inch. - int _hResUnit; //! 1=display horizontal resolution in pixels per inch; 2=display horizontal resolution in pixels per cm. - int _vResUnit; //! 1=display vertical resolution in pixels per inch; 2=display vertical resolution in pixels per cm. - -public: - psdResolutionInfo(); - ~psdResolutionInfo(); - /** - @return Returns the number of bytes read - */ - int Read(FreeImageIO *io, fi_handle handle); - /** - @param res_x [out] X resolution in pixels/meter - @param res_y [out] Y resolution in pixels/meter - */ - void GetResolutionInfo(unsigned &res_x, unsigned &res_y); -}; - -// Obsolete - Photoshop 2.0 -class psdResolutionInfo_v2 { -public: - short _Channels; - short _Rows; - short _Columns; - short _Depth; - short _Mode; - -public: - psdResolutionInfo_v2(); - ~psdResolutionInfo_v2(); - /** - @return Returns the number of bytes read - */ - int Read(FreeImageIO *io, fi_handle handle); -}; - -/** -Table A-7: DisplayInfo Color spaces -This structure contains display information about each channel. It is written as an image resource. -*/ -class psdDisplayInfo { -public: - short _ColourSpace; - short _Colour[4]; - short _Opacity; //! 0..100 - BYTE _Kind; //! selected = 0, protected = 1 - BYTE _padding; //! should be zero - -public: - psdDisplayInfo(); - ~psdDisplayInfo(); - /** - @return Returns the number of bytes read - */ - int Read(FreeImageIO *io, fi_handle handle); -}; - -/** -Table 2-5: Thumbnail resource header -Adobe Photoshop 5.0 and later stores thumbnail information for preview -display in an image resource block. These resource blocks consist of an initial -28 byte header, followed by a JFIF thumbnail in RGB (red, green, blue) order -for both Macintosh and Windows. Adobe Photoshop 4.0 stored the -thumbnail information in the same format except the data section is BGR -(blue, green, red). The Adobe Photoshop 4.0 format is at resource ID 1033 -and the Adobe Photoshop 5.0 format is at resource ID 1036. -*/ -class psdThumbnail { -public: - int _Format; //! = 1 (kJpegRGB). Also supports kRawRGB (0). - int _Width; //! Width of thumbnail in pixels. - int _Height; //! Height of thumbnail in pixels. - int _WidthBytes; //! Padded row bytes as (width * bitspixel + 31) / 32 * 4. - int _Size; //! Total size as widthbytes * height * planes - int _CompressedSize; //! Size after compression. Used for consistentcy check. - short _BitPerPixel; //! = 24. Bits per pixel. - short _Planes; //! = 1. Number of planes. - FIBITMAP * _dib; //! JFIF data as uncompressed dib. Note: For resource ID 1033 the data is in BGR format. - -public: - psdThumbnail(); - ~psdThumbnail(); - FIBITMAP* getDib() { return _dib; } - /** - @return Returns the number of bytes read - */ - int Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR); - -private: - psdThumbnail(const psdThumbnail&); - psdThumbnail& operator=(const psdThumbnail&); -}; - -class psdICCProfile { -public: - int _ProfileSize; - BYTE * _ProfileData; -public: - psdICCProfile(); - ~psdICCProfile(); - void clear(); - /** - @return Returns the number of bytes read - */ - int Read(FreeImageIO *io, fi_handle handle, int size); -}; - -/** -PSD loader -*/ -class psdParser { -private: - psdHeaderInfo _headerInfo; - psdColourModeData _colourModeData; - psdResolutionInfo _resolutionInfo; - psdResolutionInfo_v2 _resolutionInfo_v2; - psdDisplayInfo _displayInfo; - psdThumbnail _thumbnail; - psdICCProfile _iccProfile; - - short _ColourCount; - short _TransparentIndex; - int _GlobalAngle; - bool _bResolutionInfoFilled; - bool _bResolutionInfoFilled_v2; - bool _bDisplayInfoFilled; - bool _bThumbnailFilled; - bool _bCopyright; - - int _fi_flags; - int _fi_format_id; - -private: - /** Actually ignore it */ - bool ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle); - FIBITMAP* ReadImageData(FreeImageIO *io, fi_handle handle); - -public: - psdParser(); - ~psdParser(); - FIBITMAP* Load(FreeImageIO *io, fi_handle handle, int s_format_id, int flags=0); - /** Also used by the TIFF plugin */ - bool ReadImageResources(FreeImageIO *io, fi_handle handle, LONG length=0); - /** Used by the TIFF plugin */ - FIBITMAP* GetThumbnail() { - return _thumbnail.getDib(); - } -}; - -#endif // PSDPARSER_H - diff --git a/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp b/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp deleted file mode 100644 index 70b381f105..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// ========================================================== -// Pixel access functions -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Ryan Rubley (ryan@lostreality.org) -// - Riley McNiff (rmcniff@marexgroup.com) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- - -BYTE * DLL_CALLCONV -FreeImage_GetScanLine(FIBITMAP *dib, int scanline) { - if(!FreeImage_HasPixels(dib)) { - return NULL; - } - return CalculateScanLine(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), scanline); -} - -BOOL DLL_CALLCONV -FreeImage_GetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value) { - BYTE shift; - - if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) - return FALSE; - - if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - - switch(FreeImage_GetBPP(dib)) { - case 1: - *value = (bits[x >> 3] & (0x80 >> (x & 0x07))) != 0; - break; - case 4: - shift = (BYTE)((1 - x % 2) << 2); - *value = (bits[x >> 1] & (0x0F << shift)) >> shift; - break; - case 8: - *value = bits[x]; - break; - default: - return FALSE; - } - - return TRUE; - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_GetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value) { - if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) - return FALSE; - - if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - - switch(FreeImage_GetBPP(dib)) { - case 16: - { - bits += 2*x; - WORD *pixel = (WORD *)bits; - if((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { - value->rgbBlue = (BYTE)((((*pixel & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F); - value->rgbGreen = (BYTE)((((*pixel & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F); - value->rgbRed = (BYTE)((((*pixel & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F); - value->rgbReserved = 0; - } else { - value->rgbBlue = (BYTE)((((*pixel & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); - value->rgbGreen = (BYTE)((((*pixel & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F); - value->rgbRed = (BYTE)((((*pixel & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); - value->rgbReserved = 0; - } - break; - } - case 24: - bits += 3*x; - value->rgbBlue = bits[FI_RGBA_BLUE]; // B - value->rgbGreen = bits[FI_RGBA_GREEN]; // G - value->rgbRed = bits[FI_RGBA_RED]; // R - value->rgbReserved = 0; - break; - case 32: - bits += 4*x; - value->rgbBlue = bits[FI_RGBA_BLUE]; // B - value->rgbGreen = bits[FI_RGBA_GREEN]; // G - value->rgbRed = bits[FI_RGBA_RED]; // R - value->rgbReserved = bits[FI_RGBA_ALPHA]; // A - break; - default: - return FALSE; - } - - return TRUE; - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_SetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value) { - BYTE shift; - - if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) - return FALSE; - - if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - - switch(FreeImage_GetBPP(dib)) { - case 1: - *value ? bits[x >> 3] |= (0x80 >> (x & 0x7)) : bits[x >> 3] &= (0xFF7F >> (x & 0x7)); - break; - case 4: - shift = (BYTE)((1 - x % 2) << 2); - bits[x >> 1] &= ~(0x0F << shift); - bits[x >> 1] |= ((*value & 0x0F) << shift); - break; - case 8: - bits[x] = *value; - break; - default: - return FALSE; - } - - return TRUE; - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_SetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value) { - if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) - return FALSE; - - if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - - switch(FreeImage_GetBPP(dib)) { - case 16: - { - bits += 2*x; - WORD *pixel = (WORD *)bits; - if((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { - *pixel = ((value->rgbBlue >> 3) << FI16_565_BLUE_SHIFT) | - ((value->rgbGreen >> 2) << FI16_565_GREEN_SHIFT) | - ((value->rgbRed >> 3) << FI16_565_RED_SHIFT); - } else { - *pixel = ((value->rgbBlue >> 3) << FI16_555_BLUE_SHIFT) | - ((value->rgbGreen >> 3) << FI16_555_GREEN_SHIFT) | - ((value->rgbRed >> 3) << FI16_555_RED_SHIFT); - } - break; - } - case 24: - bits += 3*x; - bits[FI_RGBA_BLUE] = value->rgbBlue; // B - bits[FI_RGBA_GREEN] = value->rgbGreen; // G - bits[FI_RGBA_RED] = value->rgbRed; // R - break; - case 32: - bits += 4*x; - bits[FI_RGBA_BLUE] = value->rgbBlue; // B - bits[FI_RGBA_GREEN] = value->rgbGreen; // G - bits[FI_RGBA_RED] = value->rgbRed; // R - bits[FI_RGBA_ALPHA] = value->rgbReserved; // A - break; - default: - return FALSE; - } - - return TRUE; - } - - return FALSE; -} - diff --git a/plugins/AdvaImg/src/FreeImage/Plugin.cpp b/plugins/AdvaImg/src/FreeImage/Plugin.cpp deleted file mode 100644 index 1bc13412a5..0000000000 --- a/plugins/AdvaImg/src/FreeImage/Plugin.cpp +++ /dev/null @@ -1,822 +0,0 @@ -// ===================================================================== -// FreeImage Plugin Interface -// -// Design and implementation by -// - Floris van den Berg (floris@geekhq.nl) -// - Rui Lopes (ruiglopes@yahoo.com) -// - Detlev Vendt (detlev.vendt@brillit.de) -// - Petr Pytelka (pyta@lightcomp.com) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ===================================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#ifdef _WIN32 -#include <windows.h> -#include <io.h> -#else -#include <ctype.h> -#endif // _WIN32 - -#include "FreeImage.h" -#include "Utilities.h" -#include "FreeImageIO.h" -#include "Plugin.h" - -#include "../Metadata/FreeImageTag.h" - -// ===================================================================== - -using namespace std; - -// ===================================================================== -// Plugin search list -// ===================================================================== - -const char * -s_search_list[] = { - "", - "plugins\\", -}; - -static int s_search_list_size = sizeof(s_search_list) / sizeof(char *); -static PluginList *s_plugins = NULL; -static int s_plugin_reference_count = 0; - - -// ===================================================================== -// Reimplementation of stricmp (it is not supported on some systems) -// ===================================================================== - -int -FreeImage_stricmp(const char *s1, const char *s2) { - int c1, c2; - - do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } while (c1 && c1 == c2); - - return c1 - c2; -} - -// ===================================================================== -// Implementation of PluginList -// ===================================================================== - -PluginList::PluginList() : -m_plugin_map(), -m_node_count(0) { -} - -FREE_IMAGE_FORMAT -PluginList::AddNode(FI_InitProc init_proc, void *instance, const char *format, const char *description, const char *extension, const char *regexpr) { - if (init_proc != NULL) { - PluginNode *node = new(std::nothrow) PluginNode; - Plugin *plugin = new(std::nothrow) Plugin; - if(!node || !plugin) { - if(node) delete node; - if(plugin) delete plugin; - FreeImage_OutputMessageProc(FIF_UNKNOWN, FI_MSG_ERROR_MEMORY); - return FIF_UNKNOWN; - } - - memset(plugin, 0, sizeof(Plugin)); - - // fill-in the plugin structure - // note we have memset to 0, so all unset pointers should be NULL) - - init_proc(plugin, (int)m_plugin_map.size()); - - // get the format string (two possible ways) - - const char *the_format = NULL; - - if (format != NULL) { - the_format = format; - } else if (plugin->format_proc != NULL) { - the_format = plugin->format_proc(); - } - - // add the node if it wasn't there already - - if (the_format != NULL) { - node->m_id = (int)m_plugin_map.size(); - node->m_instance = instance; - node->m_plugin = plugin; - node->m_format = format; - node->m_description = description; - node->m_extension = extension; - node->m_regexpr = regexpr; - node->m_enabled = TRUE; - - m_plugin_map[(const int)m_plugin_map.size()] = node; - - return (FREE_IMAGE_FORMAT)node->m_id; - } - - // something went wrong while allocating the plugin... cleanup - - delete plugin; - delete node; - } - - return FIF_UNKNOWN; -} - -PluginNode * -PluginList::FindNodeFromFormat(const char *format) { - for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) { - const char *the_format = ((*i).second->m_format != NULL) ? (*i).second->m_format : (*i).second->m_plugin->format_proc(); - - if ((*i).second->m_enabled) { - if (FreeImage_stricmp(the_format, format) == 0) { - return (*i).second; - } - } - } - - return NULL; -} - -PluginNode * -PluginList::FindNodeFromMime(const char *mime) { - for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) { - const char *the_mime = ((*i).second->m_plugin->mime_proc != NULL) ? (*i).second->m_plugin->mime_proc() : ""; - - if ((*i).second->m_enabled) { - if ((the_mime != NULL) && (strcmp(the_mime, mime) == 0)) { - return (*i).second; - } - } - } - - return NULL; -} - -PluginNode * -PluginList::FindNodeFromFIF(int node_id) { - map<int, PluginNode *>::iterator i = m_plugin_map.find(node_id); - - if (i != m_plugin_map.end()) { - return (*i).second; - } - - return NULL; -} - -int -PluginList::Size() const { - return (int)m_plugin_map.size(); -} - -BOOL -PluginList::IsEmpty() const { - return m_plugin_map.empty(); -} - -PluginList::~PluginList() { - for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) { -#ifdef _WIN32 - if ((*i).second->m_instance != NULL) { - FreeLibrary((HINSTANCE)(*i).second->m_instance); - } -#endif - delete (*i).second->m_plugin; - delete ((*i).second); - } -} - -// ===================================================================== -// Retrieve a pointer to the plugin list container -// ===================================================================== - -PluginList * DLL_CALLCONV -FreeImage_GetPluginList() { - return s_plugins; -} - -// ===================================================================== -// Plugin System Initialization -// ===================================================================== - -void DLL_CALLCONV -FreeImage_Initialise(BOOL load_local_plugins_only) { - if (s_plugin_reference_count++ == 0) { - - /* - Note: initialize all singletons here - in order to avoid race conditions with multi-threading - */ - - // initialise the TagLib singleton - TagLib& s = TagLib::instance(); - - // internal plugin initialization - - s_plugins = new(std::nothrow) PluginList; - - if (s_plugins) { - /* NOTE : - The order used to initialize internal plugins below MUST BE the same order - as the one used to define the FREE_IMAGE_FORMAT enum. - */ - s_plugins->AddNode(InitBMP); - s_plugins->AddNode(InitICO); - s_plugins->AddNode(InitJPEG); - s_plugins->AddNode(InitPNG); - s_plugins->AddNode(InitGIF); - //s_plugins->AddNode(InitJNG); - //s_plugins->AddNode(InitKOALA); - //s_plugins->AddNode(InitIFF); - //s_plugins->AddNode(InitMNG); - //s_plugins->AddNode(InitPNM, NULL, "PBM", "Portable Bitmap (ASCII)", "pbm", "^P1"); - //s_plugins->AddNode(InitPNM, NULL, "PBMRAW", "Portable Bitmap (RAW)", "pbm", "^P4"); - //s_plugins->AddNode(InitPCD); - //s_plugins->AddNode(InitPCX); - //s_plugins->AddNode(InitPNM, NULL, "PGM", "Portable Greymap (ASCII)", "pgm", "^P2"); - //s_plugins->AddNode(InitPNM, NULL, "PGMRAW", "Portable Greymap (RAW)", "pgm", "^P5"); - //s_plugins->AddNode(InitPNM, NULL, "PPM", "Portable Pixelmap (ASCII)", "ppm", "^P3"); - //s_plugins->AddNode(InitPNM, NULL, "PPMRAW", "Portable Pixelmap (RAW)", "ppm", "^P6"); - //s_plugins->AddNode(InitRAS); - //s_plugins->AddNode(InitTARGA); - //s_plugins->AddNode(InitTIFF); - //s_plugins->AddNode(InitWBMP); - //s_plugins->AddNode(InitPSD); - //s_plugins->AddNode(InitCUT); - //s_plugins->AddNode(InitXBM); - //s_plugins->AddNode(InitXPM); - //s_plugins->AddNode(InitDDS); - //s_plugins->AddNode(InitHDR); - //s_plugins->AddNode(InitG3); - //s_plugins->AddNode(InitSGI); - //s_plugins->AddNode(InitEXR); - //s_plugins->AddNode(InitJ2K); - //s_plugins->AddNode(InitJP2); - //s_plugins->AddNode(InitPFM); - //s_plugins->AddNode(InitPICT); - //s_plugins->AddNode(InitRAW); - //s_plugins->AddNode(InitWEBP); -//#if !(defined(_MSC_VER) && (_MSC_VER <= 1310)) - //s_plugins->AddNode(InitJXR); -//#endif // unsupported by MS Visual Studio 2003 !!! - - // external plugin initialization - -#ifdef _WIN32 - if (!load_local_plugins_only) { - int count = 0; - char buffer[MAX_PATH + 200]; - wchar_t current_dir[2 * _MAX_PATH], module[2 * _MAX_PATH]; - BOOL bOk = FALSE; - - // store the current directory. then set the directory to the application location - - if (GetCurrentDirectoryW(2 * _MAX_PATH, current_dir) != 0) { - if (GetModuleFileNameW(NULL, module, 2 * _MAX_PATH) != 0) { - wchar_t *last_point = wcsrchr(module, L'\\'); - - if (last_point) { - *last_point = L'\0'; - - bOk = SetCurrentDirectoryW(module); - } - } - } - - // search for plugins - - while (count < s_search_list_size) { - _finddata_t find_data; - long find_handle; - - strcpy(buffer, s_search_list[count]); - strcat(buffer, "*.fip"); - - if ((find_handle = (long)_findfirst(buffer, &find_data)) != -1L) { - do { - strcpy(buffer, s_search_list[count]); - strncat(buffer, find_data.name, MAX_PATH + 200); - - HINSTANCE instance = LoadLibraryA(buffer); - - if (instance != NULL) { - FARPROC proc_address = GetProcAddress(instance, "_Init@8"); - - if (proc_address != NULL) { - s_plugins->AddNode((FI_InitProc)proc_address, (void *)instance); - } else { - FreeLibrary(instance); - } - } - } while (_findnext(find_handle, &find_data) != -1L); - - _findclose(find_handle); - } - - count++; - } - - // restore the current directory - - if (bOk) { - SetCurrentDirectoryW(current_dir); - } - } -#endif // _WIN32 - } - } -} - -void DLL_CALLCONV -FreeImage_DeInitialise() { - --s_plugin_reference_count; - - if (s_plugin_reference_count == 0) { - delete s_plugins; - } -} - -// ===================================================================== -// Open and close a bitmap -// ===================================================================== - -void * DLL_CALLCONV -FreeImage_Open(PluginNode *node, FreeImageIO *io, fi_handle handle, BOOL open_for_reading) { - if (node->m_plugin->open_proc != NULL) { - return node->m_plugin->open_proc(io, handle, open_for_reading); - } - - return NULL; -} - -void DLL_CALLCONV -FreeImage_Close(PluginNode *node, FreeImageIO *io, fi_handle handle, void *data) { - if (node->m_plugin->close_proc != NULL) { - node->m_plugin->close_proc(io, handle, data); - } -} - -// ===================================================================== -// Plugin System Load/Save Functions -// ===================================================================== - -FIBITMAP * DLL_CALLCONV -FreeImage_LoadFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags) { - if ((fif >= 0) && (fif < FreeImage_GetFIFCount())) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - if (node != NULL) { - if(node->m_plugin->load_proc != NULL) { - void *data = FreeImage_Open(node, io, handle, TRUE); - - FIBITMAP *bitmap = node->m_plugin->load_proc(io, handle, -1, flags, data); - - FreeImage_Close(node, io, handle, data); - - return bitmap; - } - } - } - - return NULL; -} - -FIBITMAP * DLL_CALLCONV -FreeImage_Load(FREE_IMAGE_FORMAT fif, const char *filename, int flags) { - FreeImageIO io; - SetDefaultIO(&io); - - FILE *handle = fopen(filename, "rb"); - - if (handle) { - FIBITMAP *bitmap = FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags); - - fclose(handle); - - return bitmap; - } else { - FreeImage_OutputMessageProc((int)fif, "FreeImage_Load: failed to open file %s", filename); - } - - return NULL; -} - -FIBITMAP * DLL_CALLCONV -FreeImage_LoadU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, int flags) { - FreeImageIO io; - SetDefaultIO(&io); -#ifdef _WIN32 - FILE *handle = _wfopen(filename, L"rb"); - - if (handle) { - FIBITMAP *bitmap = FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags); - - fclose(handle); - - return bitmap; - } else { - FreeImage_OutputMessageProc((int)fif, "FreeImage_LoadU: failed to open input file"); - } -#endif - return NULL; -} - -BOOL DLL_CALLCONV -FreeImage_SaveToHandle(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FreeImageIO *io, fi_handle handle, int flags) { - // cannot save "header only" formats - if(FreeImage_HasPixels(dib) == FALSE) { - FreeImage_OutputMessageProc((int)fif, "FreeImage_SaveToHandle: cannot save \"header only\" formats"); - return FALSE; - } - - if ((fif >= 0) && (fif < FreeImage_GetFIFCount())) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - if (node) { - if(node->m_plugin->save_proc != NULL) { - void *data = FreeImage_Open(node, io, handle, FALSE); - - BOOL result = node->m_plugin->save_proc(io, dib, handle, -1, flags, data); - - FreeImage_Close(node, io, handle, data); - - return result; - } - } - } - - return FALSE; -} - - -BOOL DLL_CALLCONV -FreeImage_Save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags) { - FreeImageIO io; - SetDefaultIO(&io); - - FILE *handle = fopen(filename, "w+b"); - - if (handle) { - BOOL success = FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags); - - fclose(handle); - - return success; - } else { - FreeImage_OutputMessageProc((int)fif, "FreeImage_Save: failed to open file %s", filename); - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_SaveU(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const wchar_t *filename, int flags) { - FreeImageIO io; - SetDefaultIO(&io); -#ifdef _WIN32 - FILE *handle = _wfopen(filename, L"w+b"); - - if (handle) { - BOOL success = FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags); - - fclose(handle); - - return success; - } else { - FreeImage_OutputMessageProc((int)fif, "FreeImage_SaveU: failed to open output file"); - } -#endif - return FALSE; -} - -// ===================================================================== -// Plugin construction + enable/disable functions -// ===================================================================== - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_RegisterLocalPlugin(FI_InitProc proc_address, const char *format, const char *description, const char *extension, const char *regexpr) { - return s_plugins->AddNode(proc_address, NULL, format, description, extension, regexpr); -} - -#ifdef _WIN32 -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_RegisterExternalPlugin(const char *path, const char *format, const char *description, const char *extension, const char *regexpr) { - if (path != NULL) { - HINSTANCE instance = LoadLibraryA(path); - - if (instance != NULL) { - FARPROC proc_address = GetProcAddress(instance, "_Init@8"); - - FREE_IMAGE_FORMAT result = s_plugins->AddNode((FI_InitProc)proc_address, (void *)instance, format, description, extension, regexpr); - - if (result == FIF_UNKNOWN) - FreeLibrary(instance); - - return result; - } - } - - return FIF_UNKNOWN; -} -#endif // _WIN32 - -int DLL_CALLCONV -FreeImage_SetPluginEnabled(FREE_IMAGE_FORMAT fif, BOOL enable) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - if (node != NULL) { - BOOL previous_state = node->m_enabled; - - node->m_enabled = enable; - - return previous_state; - } - } - - return -1; -} - -int DLL_CALLCONV -FreeImage_IsPluginEnabled(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? node->m_enabled : FALSE; - } - - return -1; -} - -// ===================================================================== -// Plugin Access Functions -// ===================================================================== - -int DLL_CALLCONV -FreeImage_GetFIFCount() { - return (s_plugins != NULL) ? s_plugins->Size() : 0; -} - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_GetFIFFromFormat(const char *format) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFormat(format); - - return (node != NULL) ? (FREE_IMAGE_FORMAT)node->m_id : FIF_UNKNOWN; - } - - return FIF_UNKNOWN; -} - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_GetFIFFromMime(const char *mime) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromMime(mime); - - return (node != NULL) ? (FREE_IMAGE_FORMAT)node->m_id : FIF_UNKNOWN; - } - - return FIF_UNKNOWN; -} - -const char * DLL_CALLCONV -FreeImage_GetFormatFromFIF(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? (node->m_format != NULL) ? node->m_format : node->m_plugin->format_proc() : NULL; - } - - return NULL; -} - -const char * DLL_CALLCONV -FreeImage_GetFIFMimeType(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? (node->m_plugin != NULL) ? ( node->m_plugin->mime_proc != NULL )? node->m_plugin->mime_proc() : NULL : NULL : NULL; - } - - return NULL; -} - -const char * DLL_CALLCONV -FreeImage_GetFIFExtensionList(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? (node->m_extension != NULL) ? node->m_extension : (node->m_plugin->extension_proc != NULL) ? node->m_plugin->extension_proc() : NULL : NULL; - } - - return NULL; -} - -const char * DLL_CALLCONV -FreeImage_GetFIFDescription(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? (node->m_description != NULL) ? node->m_description : (node->m_plugin->description_proc != NULL) ? node->m_plugin->description_proc() : NULL : NULL; - } - - return NULL; -} - -const char * DLL_CALLCONV -FreeImage_GetFIFRegExpr(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? (node->m_regexpr != NULL) ? node->m_regexpr : (node->m_plugin->regexpr_proc != NULL) ? node->m_plugin->regexpr_proc() : NULL : NULL; - } - - return NULL; -} - -BOOL DLL_CALLCONV -FreeImage_FIFSupportsReading(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? node->m_plugin->load_proc != NULL : FALSE; - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_FIFSupportsWriting(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? node->m_plugin->save_proc != NULL : FALSE ; - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif, int depth) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? - (node->m_plugin->supports_export_bpp_proc != NULL) ? - node->m_plugin->supports_export_bpp_proc(depth) : FALSE : FALSE; - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_FIFSupportsExportType(FREE_IMAGE_FORMAT fif, FREE_IMAGE_TYPE type) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? - (node->m_plugin->supports_export_type_proc != NULL) ? - node->m_plugin->supports_export_type_proc(type) : FALSE : FALSE; - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? - (node->m_plugin->supports_icc_profiles_proc != NULL) ? - node->m_plugin->supports_icc_profiles_proc() : FALSE : FALSE; - } - - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_FIFSupportsNoPixels(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? - (node->m_plugin->supports_no_pixels_proc != NULL) ? - node->m_plugin->supports_no_pixels_proc() : FALSE : FALSE; - } - - return FALSE; -} - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_GetFIFFromFilename(const char *filename) { - if (filename != NULL) { - const char *extension; - - // get the proper extension if we received a filename - - char *place = strrchr((char *)filename, '.'); - extension = (place != NULL) ? ++place : filename; - - // look for the extension in the plugin table - - for (int i = 0; i < FreeImage_GetFIFCount(); ++i) { - - if (s_plugins->FindNodeFromFIF(i)->m_enabled) { - - // compare the format id with the extension - - if (FreeImage_stricmp(FreeImage_GetFormatFromFIF((FREE_IMAGE_FORMAT)i), extension) == 0) { - return (FREE_IMAGE_FORMAT)i; - } else { - // make a copy of the extension list and split it - - char *copy = (char *)malloc(strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i)) + 1); - memset(copy, 0, strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i)) + 1); - memcpy(copy, FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i), strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i))); - - // get the first token - - char *token = strtok(copy, ","); - - while (token != NULL) { - if (FreeImage_stricmp(token, extension) == 0) { - free(copy); - - return (FREE_IMAGE_FORMAT)i; - } - - token = strtok(NULL, ","); - } - - // free the copy of the extension list - - free(copy); - } - } - } - } - - return FIF_UNKNOWN; -} - -FREE_IMAGE_FORMAT DLL_CALLCONV -FreeImage_GetFIFFromFilenameU(const wchar_t *filename) { -#ifdef _WIN32 - if (filename == NULL) return FIF_UNKNOWN; - - // get the proper extension if we received a filename - wchar_t *place = wcsrchr((wchar_t *)filename, '.'); - if (place == NULL) return FIF_UNKNOWN; - // convert to single character - no national chars in extensions - char *extension = (char *)malloc(wcslen(place)+1); - unsigned int i=0; - for(; i < wcslen(place); i++) // convert 16-bit to 8-bit - extension[i] = (char)(place[i] & 0x00FF); - // set terminating 0 - extension[i]=0; - FREE_IMAGE_FORMAT fRet = FreeImage_GetFIFFromFilename(extension); - free(extension); - - return fRet; -#else - return FIF_UNKNOWN; -#endif // _WIN32 -} - -BOOL DLL_CALLCONV -FreeImage_Validate(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle) { - if (s_plugins != NULL) { - BOOL validated = FALSE; - - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - if (node) { - long tell = io->tell_proc(handle); - - validated = (node != NULL) ? (node->m_enabled) ? (node->m_plugin->validate_proc != NULL) ? node->m_plugin->validate_proc(io, handle) : FALSE : FALSE : FALSE; - - io->seek_proc(handle, tell, SEEK_SET); - } - - return validated; - } - - return FALSE; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginBMP.cpp b/plugins/AdvaImg/src/FreeImage/PluginBMP.cpp deleted file mode 100644 index 13206f7b71..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginBMP.cpp +++ /dev/null @@ -1,1494 +0,0 @@ -// ========================================================== -// BMP Loader and Writer -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Markus Loibl (markus.loibl@epost.de) -// - Martin Weber (martweb@gmx.net) -// - Hervé Drolon (drolon@infonie.fr) -// - Michal Novotny (michal@etc.cz) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// Constants + headers -// ---------------------------------------------------------- - -static const BYTE RLE_COMMAND = 0; -static const BYTE RLE_ENDOFLINE = 0; -static const BYTE RLE_ENDOFBITMAP = 1; -static const BYTE RLE_DELTA = 2; - -static const BYTE BI_RGB = 0; // compression: none -static const BYTE BI_RLE8 = 1; // compression: RLE 8-bit/pixel -static const BYTE BI_RLE4 = 2; // compression: RLE 4-bit/pixel -static const BYTE BI_BITFIELDS = 3; // compression: Bit field or Huffman 1D compression for BITMAPCOREHEADER2 -static const BYTE BI_JPEG = 4; // compression: JPEG or RLE-24 compression for BITMAPCOREHEADER2 -static const BYTE BI_PNG = 5; // compression: PNG -static const BYTE BI_ALPHABITFIELDS = 6; // compression: Bit field (this value is valid in Windows CE .NET 4.0 and later) - -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagBITMAPCOREHEADER { - DWORD bcSize; - WORD bcWidth; - WORD bcHeight; - WORD bcPlanes; - WORD bcBitCnt; -} BITMAPCOREHEADER, *PBITMAPCOREHEADER; - -typedef struct tagBITMAPINFOOS2_1X_HEADER { - DWORD biSize; - WORD biWidth; - WORD biHeight; - WORD biPlanes; - WORD biBitCount; -} BITMAPINFOOS2_1X_HEADER, *PBITMAPINFOOS2_1X_HEADER; - -typedef struct tagBITMAPFILEHEADER { - WORD bfType; //! The file type - DWORD bfSize; //! The size, in bytes, of the bitmap file - WORD bfReserved1; //! Reserved; must be zero - WORD bfReserved2; //! Reserved; must be zero - DWORD bfOffBits; //! The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits -} BITMAPFILEHEADER, *PBITMAPFILEHEADER; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Internal functions -// ========================================================== - -#ifdef FREEIMAGE_BIGENDIAN -static void -SwapInfoHeader(BITMAPINFOHEADER *header) { - SwapLong(&header->biSize); - SwapLong((DWORD *)&header->biWidth); - SwapLong((DWORD *)&header->biHeight); - SwapShort(&header->biPlanes); - SwapShort(&header->biBitCount); - SwapLong(&header->biCompression); - SwapLong(&header->biSizeImage); - SwapLong((DWORD *)&header->biXPelsPerMeter); - SwapLong((DWORD *)&header->biYPelsPerMeter); - SwapLong(&header->biClrUsed); - SwapLong(&header->biClrImportant); -} - -static void -SwapCoreHeader(BITMAPCOREHEADER *header) { - SwapLong(&header->bcSize); - SwapShort(&header->bcWidth); - SwapShort(&header->bcHeight); - SwapShort(&header->bcPlanes); - SwapShort(&header->bcBitCnt); -} - -static void -SwapOS21XHeader(BITMAPINFOOS2_1X_HEADER *header) { - SwapLong(&header->biSize); - SwapShort(&header->biWidth); - SwapShort(&header->biHeight); - SwapShort(&header->biPlanes); - SwapShort(&header->biBitCount); -} - -static void -SwapFileHeader(BITMAPFILEHEADER *header) { - SwapShort(&header->bfType); - SwapLong(&header->bfSize); - SwapShort(&header->bfReserved1); - SwapShort(&header->bfReserved2); - SwapLong(&header->bfOffBits); -} -#endif - -// -------------------------------------------------------------------------- - -/** -Load uncompressed image pixels for 1-, 4-, 8-, 16-, 24- and 32-bit dib -@param io FreeImage IO -@param handle FreeImage IO handle -@param dib Image to be loaded -@param height Image height -@param pitch Image pitch -@param bit_count Image bit-depth (1-, 4-, 8-, 16-, 24- or 32-bit) -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -LoadPixelData(FreeImageIO *io, fi_handle handle, FIBITMAP *dib, int height, unsigned pitch, unsigned bit_count) { - unsigned count = 0; - - // Load pixel data - // NB: height can be < 0 for BMP data - if (height > 0) { - count = io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle); - if(count != 1) { - return FALSE; - } - } else { - int positiveHeight = abs(height); - for (int c = 0; c < positiveHeight; ++c) { - count = io->read_proc((void *)FreeImage_GetScanLine(dib, positiveHeight - c - 1), pitch, 1, handle); - if(count != 1) { - return FALSE; - } - } - } - - // swap as needed -#ifdef FREEIMAGE_BIGENDIAN - if (bit_count == 16) { - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { - SwapShort(pixel); - pixel++; - } - } - } -#endif -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - if (bit_count == 24 || bit_count == 32) { - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *pixel = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { - INPLACESWAP(pixel[0], pixel[2]); - pixel += (bit_count >> 3); - } - } - } -#endif - - return TRUE; -} - -/** -Load image pixels for 4-bit RLE compressed dib -@param io FreeImage IO -@param handle FreeImage IO handle -@param width Image width -@param height Image height -@param dib Image to be loaded -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -LoadPixelDataRLE4(FreeImageIO *io, fi_handle handle, int width, int height, FIBITMAP *dib) { - int status_byte = 0; - BYTE second_byte = 0; - int bits = 0; - - BYTE *pixels = NULL; // temporary 8-bit buffer - - try { - height = abs(height); - - pixels = (BYTE*)malloc(width * height * sizeof(BYTE)); - if(!pixels) throw(1); - memset(pixels, 0, width * height * sizeof(BYTE)); - - BYTE *q = pixels; - BYTE *end = pixels + height * width; - - for (int scanline = 0; scanline < height; ) { - if (q < pixels || q >= end) { - break; - } - if(io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) { - throw(1); - } - if (status_byte != 0) { - status_byte = (int)MIN((size_t)status_byte, (size_t)(end - q)); - // Encoded mode - if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) { - throw(1); - } - for (int i = 0; i < status_byte; i++) { - *q++=(BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f)); - } - bits += status_byte; - } - else { - // Escape mode - if(io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) { - throw(1); - } - switch (status_byte) { - case RLE_ENDOFLINE: - { - // End of line - bits = 0; - scanline++; - q = pixels + scanline*width; - } - break; - - case RLE_ENDOFBITMAP: - // End of bitmap - q = end; - break; - - case RLE_DELTA: - { - // read the delta values - - BYTE delta_x = 0; - BYTE delta_y = 0; - - if(io->read_proc(&delta_x, sizeof(BYTE), 1, handle) != 1) { - throw(1); - } - if(io->read_proc(&delta_y, sizeof(BYTE), 1, handle) != 1) { - throw(1); - } - - // apply them - - bits += delta_x; - scanline += delta_y; - q = pixels + scanline*width+bits; - } - break; - - default: - { - // Absolute mode - status_byte = (int)MIN((size_t)status_byte, (size_t)(end - q)); - for (int i = 0; i < status_byte; i++) { - if ((i & 0x01) == 0) { - if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) { - throw(1); - } - } - *q++=(BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f)); - } - bits += status_byte; - // Read pad byte - if (((status_byte & 0x03) == 1) || ((status_byte & 0x03) == 2)) { - BYTE padding = 0; - if(io->read_proc(&padding, sizeof(BYTE), 1, handle) != 1) { - throw(1); - } - } - } - break; - } - } - } - - { - // Convert to 4-bit - for(int y = 0; y < height; y++) { - const BYTE *src = (BYTE*)pixels + y * width; - BYTE *dst = FreeImage_GetScanLine(dib, y); - - BOOL hinibble = TRUE; - - for (int cols = 0; cols < width; cols++){ - if (hinibble) { - dst[cols >> 1] = (src[cols] << 4); - } else { - dst[cols >> 1] |= src[cols]; - } - - hinibble = !hinibble; - } - } - } - - free(pixels); - - return TRUE; - - } catch(int) { - if(pixels) free(pixels); - return FALSE; - } -} - -/** -Load image pixels for 8-bit RLE compressed dib -@param io FreeImage IO -@param handle FreeImage IO handle -@param width Image width -@param height Image height -@param dib Image to be loaded -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -LoadPixelDataRLE8(FreeImageIO *io, fi_handle handle, int width, int height, FIBITMAP *dib) { - BYTE status_byte = 0; - BYTE second_byte = 0; - int scanline = 0; - int bits = 0; - - for (;;) { - if( io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) { - return FALSE; - } - - switch (status_byte) { - case RLE_COMMAND : - if(io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) { - return FALSE; - } - - switch (status_byte) { - case RLE_ENDOFLINE : - bits = 0; - scanline++; - break; - - case RLE_ENDOFBITMAP : - return TRUE; - - case RLE_DELTA : - { - // read the delta values - - BYTE delta_x = 0; - BYTE delta_y = 0; - - if(io->read_proc(&delta_x, sizeof(BYTE), 1, handle) != 1) { - return FALSE; - } - if(io->read_proc(&delta_y, sizeof(BYTE), 1, handle) != 1) { - return FALSE; - } - - // apply them - - bits += delta_x; - scanline += delta_y; - - break; - } - - default : - { - if(scanline >= abs(height)) { - return TRUE; - } - - int count = MIN((int)status_byte, width - bits); - - BYTE *sline = FreeImage_GetScanLine(dib, scanline); - - if(io->read_proc((void *)(sline + bits), sizeof(BYTE) * count, 1, handle) != 1) { - return FALSE; - } - - // align run length to even number of bytes - - if ((status_byte & 1) == 1) { - if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) { - return FALSE; - } - } - - bits += status_byte; - - break; - } - } - - break; - - default : - { - if(scanline >= abs(height)) { - return TRUE; - } - - int count = MIN((int)status_byte, width - bits); - - BYTE *sline = FreeImage_GetScanLine(dib, scanline); - - if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) { - return FALSE; - } - - for (int i = 0; i < count; i++) { - *(sline + bits) = second_byte; - - bits++; - } - - break; - } - } - } -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * -LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset, int type) { - FIBITMAP *dib = NULL; - - try { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // load the info header - - BITMAPINFOHEADER bih; - - io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapInfoHeader(&bih); -#endif - - // keep some general information about the bitmap - - unsigned used_colors = bih.biClrUsed; - int width = bih.biWidth; - int height = bih.biHeight; // WARNING: height can be < 0 => check each call using 'height' as a parameter - unsigned bit_count = bih.biBitCount; - unsigned compression = bih.biCompression; - unsigned pitch = CalculatePitch(CalculateLine(width, bit_count)); - - switch (bit_count) { - case 1 : - case 4 : - case 8 : - { - if ((used_colors == 0) || (used_colors > CalculateUsedPaletteEntries(bit_count))) { - used_colors = CalculateUsedPaletteEntries(bit_count); - } - - // allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette - - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count); - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // set resolution information - FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter); - FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter); - - // seek to the end of the header (depending on the BMP header version) - // type == sizeof(BITMAPVxINFOHEADER) - switch(type) { - case 40: // sizeof(BITMAPINFOHEADER) - all Windows versions since Windows 3.0 - break; - case 52: // sizeof(BITMAPV2INFOHEADER) (undocumented) - case 56: // sizeof(BITMAPV3INFOHEADER) (undocumented) - case 108: // sizeof(BITMAPV4HEADER) - all Windows versions since Windows 95/NT4 (not supported) - case 124: // sizeof(BITMAPV5HEADER) - Windows 98/2000 and newer (not supported) - io->seek_proc(handle, (long)(type - sizeof(BITMAPINFOHEADER)), SEEK_CUR); - break; - } - - // load the palette - - io->read_proc(FreeImage_GetPalette(dib), used_colors * sizeof(RGBQUAD), 1, handle); -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - RGBQUAD *pal = FreeImage_GetPalette(dib); - for(int i = 0; i < used_colors; i++) { - INPLACESWAP(pal[i].rgbRed, pal[i].rgbBlue); - } -#endif - - if(header_only) { - // header only mode - return dib; - } - - // seek to the actual pixel data. - // this is needed because sometimes the palette is larger than the entries it contains predicts - io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - - // read the pixel data - - switch (compression) { - case BI_RGB : - if( LoadPixelData(io, handle, dib, height, pitch, bit_count) ) { - return dib; - } else { - throw "Error encountered while decoding BMP data"; - } - break; - - case BI_RLE4 : - if( LoadPixelDataRLE4(io, handle, width, height, dib) ) { - return dib; - } else { - throw "Error encountered while decoding RLE4 BMP data"; - } - break; - - case BI_RLE8 : - if( LoadPixelDataRLE8(io, handle, width, height, dib) ) { - return dib; - } else { - throw "Error encountered while decoding RLE8 BMP data"; - } - break; - - default : - throw FI_MSG_ERROR_UNSUPPORTED_COMPRESSION; - } - } - break; // 1-, 4-, 8-bit - - case 16 : - { - int use_bitfields = 0; - if (bih.biCompression == BI_BITFIELDS) use_bitfields = 3; - else if (bih.biCompression == BI_ALPHABITFIELDS) use_bitfields = 4; - else if (type == 52) use_bitfields = 3; - else if (type >= 56) use_bitfields = 4; - - if (use_bitfields > 0) { - 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, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK); - } - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // set resolution information - FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter); - FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter); - - if(header_only) { - // header only mode - return dib; - } - - // seek to the actual pixel data - io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - - // load pixel data and swap as needed if OS is Big Endian - LoadPixelData(io, handle, dib, height, pitch, bit_count); - - return dib; - } - break; // 16-bit - - case 24 : - case 32 : - { - int use_bitfields = 0; - if (bih.biCompression == BI_BITFIELDS) use_bitfields = 3; - else if (bih.biCompression == BI_ALPHABITFIELDS) use_bitfields = 4; - else if (type == 52) use_bitfields = 3; - else if (type >= 56) use_bitfields = 4; - - if (use_bitfields > 0) { - 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 { - 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; - } - - // set resolution information - FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter); - FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter); - - if(header_only) { - // header only mode - return dib; - } - - // Skip over the optional palette - // A 24 or 32 bit DIB may contain a palette for faster color reduction - // i.e. you can have (FreeImage_GetColorsUsed(dib) > 0) - - // seek to the actual pixel data - io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - - // read in the bitmap bits - // load pixel data and swap as needed if OS is Big Endian - LoadPixelData(io, handle, dib, height, pitch, bit_count); - - // check if the bitmap contains transparency, if so enable it in the header - - FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA)); - - return dib; - } - break; // 24-, 32-bit - } - } catch(const char *message) { - if(dib) { - FreeImage_Unload(dib); - } - if(message) { - FreeImage_OutputMessageProc(s_format_id, message); - } - } - - return NULL; -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * -LoadOS22XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) { - FIBITMAP *dib = NULL; - - try { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // load the info header - - BITMAPINFOHEADER bih; - - io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapInfoHeader(&bih); -#endif - - // keep some general information about the bitmap - - unsigned used_colors = bih.biClrUsed; - int width = bih.biWidth; - int height = bih.biHeight; // WARNING: height can be < 0 => check each read_proc using 'height' as a parameter - unsigned bit_count = bih.biBitCount; - unsigned compression = bih.biCompression; - unsigned pitch = CalculatePitch(CalculateLine(width, bit_count)); - - switch (bit_count) { - case 1 : - case 4 : - case 8 : - { - if ((used_colors == 0) || (used_colors > CalculateUsedPaletteEntries(bit_count))) - used_colors = CalculateUsedPaletteEntries(bit_count); - - // allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette - - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // set resolution information - FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter); - FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter); - - // load the palette - // note that it may contain RGB or RGBA values : we will calculate this - unsigned pal_size = (bitmap_bits_offset - sizeof(BITMAPFILEHEADER) - bih.biSize) / used_colors; - - io->seek_proc(handle, sizeof(BITMAPFILEHEADER) + bih.biSize, SEEK_SET); - - RGBQUAD *pal = FreeImage_GetPalette(dib); - - if(pal_size == 4) { - for (unsigned count = 0; count < used_colors; count++) { - FILE_BGRA bgra; - - io->read_proc(&bgra, sizeof(FILE_BGRA), 1, handle); - - pal[count].rgbRed = bgra.r; - pal[count].rgbGreen = bgra.g; - pal[count].rgbBlue = bgra.b; - } - } else if(pal_size == 3) { - for (unsigned count = 0; count < used_colors; count++) { - FILE_BGR bgr; - - io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle); - - pal[count].rgbRed = bgr.r; - pal[count].rgbGreen = bgr.g; - pal[count].rgbBlue = bgr.b; - } - } - - if(header_only) { - // header only mode - return dib; - } - - // seek to the actual pixel data. - // this is needed because sometimes the palette is larger than the entries it contains predicts - - if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) { - io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - } - - // read the pixel data - - switch (compression) { - case BI_RGB : - // load pixel data - LoadPixelData(io, handle, dib, height, pitch, bit_count); - return dib; - - case BI_RLE4 : - if( LoadPixelDataRLE4(io, handle, width, height, dib) ) { - return dib; - } else { - throw "Error encountered while decoding RLE4 BMP data"; - } - break; - - case BI_RLE8 : - if( LoadPixelDataRLE8(io, handle, width, height, dib) ) { - return dib; - } else { - throw "Error encountered while decoding RLE8 BMP data"; - } - break; - - default : - throw FI_MSG_ERROR_UNSUPPORTED_COMPRESSION; - } - } - - case 16 : - { - if (bih.biCompression == 3) { - DWORD bitfields[3]; - - io->read_proc(bitfields, 3 * 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, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK); - } - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // set resolution information - FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter); - FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter); - - if(header_only) { - // header only mode - return dib; - } - - if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) { - io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - } - - // load pixel data and swap as needed if OS is Big Endian - LoadPixelData(io, handle, dib, height, pitch, bit_count); - - return dib; - } - - case 24 : - case 32 : - { - 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; - } - - // set resolution information - FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter); - FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter); - - if(header_only) { - // header only mode - return dib; - } - - // Skip over the optional palette - // A 24 or 32 bit DIB may contain a palette for faster color reduction - - if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) { - io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - } - - // read in the bitmap bits - // load pixel data and swap as needed if OS is Big Endian - LoadPixelData(io, handle, dib, height, pitch, bit_count); - - // check if the bitmap contains transparency, if so enable it in the header - - FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA)); - - return dib; - } - } - } catch(const char *message) { - if(dib) - FreeImage_Unload(dib); - - FreeImage_OutputMessageProc(s_format_id, message); - } - - return NULL; -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * -LoadOS21XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) { - FIBITMAP *dib = NULL; - - try { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - BITMAPINFOOS2_1X_HEADER bios2_1x; - - io->read_proc(&bios2_1x, sizeof(BITMAPINFOOS2_1X_HEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapOS21XHeader(&bios2_1x); -#endif - // keep some general information about the bitmap - - unsigned used_colors = 0; - unsigned width = bios2_1x.biWidth; - unsigned height = bios2_1x.biHeight; // WARNING: height can be < 0 => check each read_proc using 'height' as a parameter - unsigned bit_count = bios2_1x.biBitCount; - unsigned pitch = CalculatePitch(CalculateLine(width, bit_count)); - - switch (bit_count) { - case 1 : - case 4 : - case 8 : - { - used_colors = CalculateUsedPaletteEntries(bit_count); - - // allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette - - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // set resolution information to default values (72 dpi in english units) - FreeImage_SetDotsPerMeterX(dib, 2835); - FreeImage_SetDotsPerMeterY(dib, 2835); - - // load the palette - - RGBQUAD *pal = FreeImage_GetPalette(dib); - - for (unsigned count = 0; count < used_colors; count++) { - FILE_BGR bgr; - - io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle); - - pal[count].rgbRed = bgr.r; - pal[count].rgbGreen = bgr.g; - pal[count].rgbBlue = bgr.b; - } - - if(header_only) { - // header only mode - return dib; - } - - // Skip over the optional palette - // A 24 or 32 bit DIB may contain a palette for faster color reduction - - io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - - // read the pixel data - - // load pixel data - LoadPixelData(io, handle, dib, height, pitch, bit_count); - - return dib; - } - - case 16 : - { - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // set resolution information to default values (72 dpi in english units) - FreeImage_SetDotsPerMeterX(dib, 2835); - FreeImage_SetDotsPerMeterY(dib, 2835); - - if(header_only) { - // header only mode - return dib; - } - - // load pixel data and swap as needed if OS is Big Endian - LoadPixelData(io, handle, dib, height, pitch, bit_count); - - return dib; - } - - case 24 : - case 32 : - { - 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; - } - - // set resolution information to default values (72 dpi in english units) - FreeImage_SetDotsPerMeterX(dib, 2835); - FreeImage_SetDotsPerMeterY(dib, 2835); - - if(header_only) { - // header only mode - return dib; - } - - // Skip over the optional palette - // A 24 or 32 bit DIB may contain a palette for faster color reduction - - // load pixel data and swap as needed if OS is Big Endian - LoadPixelData(io, handle, dib, height, pitch, bit_count); - - // check if the bitmap contains transparency, if so enable it in the header - - FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA)); - - return dib; - } - } - } catch(const char *message) { - if(dib) - FreeImage_Unload(dib); - - FreeImage_OutputMessageProc(s_format_id, message); - } - - return NULL; -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "BMP"; -} - -static const char * DLL_CALLCONV -Description() { - return "Windows or OS/2 Bitmap"; -} - -static const char * DLL_CALLCONV -Extension() { - return "bmp"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return "^BM"; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/bmp"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE bmp_signature1[] = { 0x42, 0x4D }; - BYTE bmp_signature2[] = { 0x42, 0x41 }; - BYTE signature[2] = { 0, 0 }; - - io->read_proc(signature, 1, sizeof(bmp_signature1), handle); - - if (memcmp(bmp_signature1, signature, sizeof(bmp_signature1)) == 0) - return TRUE; - - if (memcmp(bmp_signature2, signature, sizeof(bmp_signature2)) == 0) - return TRUE; - - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 1) || - (depth == 4) || - (depth == 8) || - (depth == 16) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (handle != NULL) { - BITMAPFILEHEADER bitmapfileheader; - DWORD type = 0; - - // we use this offset value to make seemingly absolute seeks relative in the file - - long offset_in_file = io->tell_proc(handle); - - // read the fileheader - - io->read_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapFileHeader(&bitmapfileheader); -#endif - - // check the signature - - if((bitmapfileheader.bfType != 0x4D42) && (bitmapfileheader.bfType != 0x4142)) { - FreeImage_OutputMessageProc(s_format_id, FI_MSG_ERROR_MAGIC_NUMBER); - return NULL; - } - - // read the first byte of the infoheader - - io->read_proc(&type, sizeof(DWORD), 1, handle); - io->seek_proc(handle, 0 - (long)sizeof(DWORD), SEEK_CUR); -#ifdef FREEIMAGE_BIGENDIAN - SwapLong(&type); -#endif - - // call the appropriate load function for the found bitmap type - - switch(type) { - case 12: - // OS/2 and also all Windows versions since Windows 3.0 - return LoadOS21XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); - - case 64: - // OS/2 - return LoadOS22XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); - - case 40: // BITMAPINFOHEADER - all Windows versions since Windows 3.0 - case 52: // BITMAPV2INFOHEADER (undocumented, partially supported) - case 56: // BITMAPV3INFOHEADER (undocumented, partially supported) - case 108: // BITMAPV4HEADER - all Windows versions since Windows 95/NT4 (partially supported) - case 124: // BITMAPV5HEADER - Windows 98/2000 and newer (partially supported) - return LoadWindowsBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits, type); - - default: - break; - } - - FreeImage_OutputMessageProc(s_format_id, "unknown bmp subtype with id %d", type); - } - - return NULL; -} - -// ---------------------------------------------------------- - -/** -Encode a 8-bit source buffer into a 8-bit target buffer using a RLE compression algorithm. -The size of the target buffer must be equal to the size of the source buffer. -On return, the function will return the real size of the target buffer, which should be less that or equal to the source buffer size. -@param target 8-bit Target buffer -@param source 8-bit Source buffer -@param size Source/Target input buffer size -@return Returns the target buffer size -*/ -static int -RLEEncodeLine(BYTE *target, BYTE *source, int size) { - BYTE buffer[256]; - int buffer_size = 0; - int target_pos = 0; - - for (int i = 0; i < size; ++i) { - if ((i < size - 1) && (source[i] == source[i + 1])) { - // find a solid block of same bytes - - int j = i + 1; - int jmax = 254 + i; - - while ((j < size - 1) && (j < jmax) && (source[j] == source[j + 1])) - ++j; - - // if the block is larger than 3 bytes, use it - // else put the data into the larger pool - - if (((j - i) + 1) > 3) { - // don't forget to write what we already have in the buffer - - switch(buffer_size) { - case 0 : - break; - - case RLE_DELTA : - target[target_pos++] = 1; - target[target_pos++] = buffer[0]; - target[target_pos++] = 1; - target[target_pos++] = buffer[1]; - break; - - case RLE_ENDOFBITMAP : - target[target_pos++] = (BYTE)buffer_size; - target[target_pos++] = buffer[0]; - break; - - default : - target[target_pos++] = RLE_COMMAND; - target[target_pos++] = (BYTE)buffer_size; - memcpy(target + target_pos, buffer, buffer_size); - - // prepare for next run - - target_pos += buffer_size; - - if ((buffer_size & 1) == 1) - target_pos++; - - break; - } - - // write the continuous data - - target[target_pos++] = (BYTE)((j - i) + 1); - target[target_pos++] = source[i]; - - buffer_size = 0; - } else { - for (int k = 0; k < (j - i) + 1; ++k) { - buffer[buffer_size++] = source[i + k]; - - if (buffer_size == 254) { - // write what we have - - target[target_pos++] = RLE_COMMAND; - target[target_pos++] = (BYTE)buffer_size; - memcpy(target + target_pos, buffer, buffer_size); - - // prepare for next run - - target_pos += buffer_size; - buffer_size = 0; - } - } - } - - i = j; - } else { - buffer[buffer_size++] = source[i]; - } - - // write the buffer if it's full - - if (buffer_size == 254) { - target[target_pos++] = RLE_COMMAND; - target[target_pos++] = (BYTE)buffer_size; - memcpy(target + target_pos, buffer, buffer_size); - - // prepare for next run - - target_pos += buffer_size; - buffer_size = 0; - } - } - - // write the last bytes - - switch(buffer_size) { - case 0 : - break; - - case RLE_DELTA : - target[target_pos++] = 1; - target[target_pos++] = buffer[0]; - target[target_pos++] = 1; - target[target_pos++] = buffer[1]; - break; - - case RLE_ENDOFBITMAP : - target[target_pos++] = (BYTE)buffer_size; - target[target_pos++] = buffer[0]; - break; - - default : - target[target_pos++] = RLE_COMMAND; - target[target_pos++] = (BYTE)buffer_size; - memcpy(target + target_pos, buffer, buffer_size); - - // prepare for next run - - target_pos += buffer_size; - - if ((buffer_size & 1) == 1) - target_pos++; - - break; - } - - // write the END_OF_LINE marker - - target[target_pos++] = RLE_COMMAND; - target[target_pos++] = RLE_ENDOFLINE; - - // return the written size - - return target_pos; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - if ((dib != NULL) && (handle != NULL)) { - // write the file header - - 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.bfReserved1 = 0; - bitmapfileheader.bfReserved2 = 0; - - // take care of the bit fields data of any - - bool bit_fields = (FreeImage_GetBPP(dib) == 16); - - if (bit_fields) { - bitmapfileheader.bfSize += 3 * sizeof(DWORD); - bitmapfileheader.bfOffBits += 3 * sizeof(DWORD); - } - -#ifdef FREEIMAGE_BIGENDIAN - SwapFileHeader(&bitmapfileheader); -#endif - 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) - bih.biCompression = BI_BITFIELDS; - else if ((bih.biBitCount == 8) && (flags & BMP_SAVE_RLE)) - bih.biCompression = BI_RLE8; - 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) - return FALSE; - - // write the bit fields when we are dealing with a 16 bit BMP - - if (bit_fields) { - DWORD d; - - d = FreeImage_GetRedMask(dib); - - 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) - return FALSE; - - d = FreeImage_GetBlueMask(dib); - - if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) - return FALSE; - } - - // write the palette - - if (FreeImage_GetPalette(dib) != NULL) { - RGBQUAD *pal = FreeImage_GetPalette(dib); - FILE_BGRA bgra; - for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++ ) { - bgra.b = pal[i].rgbBlue; - 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) - 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)); - - for (DWORD i = 0; i < FreeImage_GetHeight(dib); ++i) { - int size = RLEEncodeLine(buffer, FreeImage_GetScanLine(dib, i), FreeImage_GetLine(dib)); - - if (io->write_proc(buffer, size, 1, handle) != 1) { - free(buffer); - return FALSE; - } - } - - buffer[0] = RLE_COMMAND; - buffer[1] = RLE_ENDOFBITMAP; - - if (io->write_proc(buffer, 2, 1, handle) != 1) { - free(buffer); - return FALSE; - } - - free(buffer); -#ifdef FREEIMAGE_BIGENDIAN - } else if (bpp == 16) { - int padding = FreeImage_GetPitch(dib) - FreeImage_GetWidth(dib) * sizeof(WORD); - WORD pad = 0; - WORD pixel; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { - pixel = ((WORD *)line)[x]; - SwapShort(&pixel); - if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1) - return FALSE; - } - if(padding != 0) { - if(io->write_proc(&pad, padding, 1, handle) != 1) { - return FALSE; - } - } - } -#endif -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - } else if (bpp == 24) { - int padding = FreeImage_GetPitch(dib) - FreeImage_GetWidth(dib) * sizeof(FILE_BGR); - DWORD pad = 0; - FILE_BGR bgr; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); 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) - return FALSE; - } - if(padding != 0) { - if(io->write_proc(&pad, padding, 1, handle) != 1) { - return FALSE; - } - } - } - } else if (bpp == 32) { - FILE_BGRA bgra; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); 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) - return FALSE; - } - } -#endif - } else if (io->write_proc(FreeImage_GetBits(dib), FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib), 1, handle) != 1) { - return FALSE; - } - - return TRUE; - } else { - return FALSE; - } -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitBMP(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; // not implemented yet; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp b/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp deleted file mode 100644 index d9b430eac5..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp +++ /dev/null @@ -1,1406 +0,0 @@ -// ========================================================== -// GIF Loader and Writer -// -// Design and implementation by -// - Ryan Rubley <ryan@lostreality.org> -// - Raphaлl Gaquer <raphael.gaquer@alcer.com> -// - Aaron Shumate <aaron@shumate.us> -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#include "FreeImage.h" -#include "Utilities.h" -#include "../Metadata/FreeImageTag.h" - -// ========================================================== -// Metadata declarations -// ========================================================== - -#define GIF_DISPOSAL_UNSPECIFIED 0 -#define GIF_DISPOSAL_LEAVE 1 -#define GIF_DISPOSAL_BACKGROUND 2 -#define GIF_DISPOSAL_PREVIOUS 3 - -// ========================================================== -// Constant/Typedef declarations -// ========================================================== - -struct GIFinfo { - BOOL read; - //only really used when reading - size_t global_color_table_offset; - int global_color_table_size; - BYTE background_color; - std::vector<size_t> application_extension_offsets; - std::vector<size_t> comment_extension_offsets; - std::vector<size_t> graphic_control_extension_offsets; - std::vector<size_t> image_descriptor_offsets; - - GIFinfo() : read(0), global_color_table_offset(0), global_color_table_size(0), background_color(0) - { - } -}; - -struct PageInfo { - PageInfo(int d, int l, int t, int w, int h) { - disposal_method = d; left = (WORD)l; top = (WORD)t; width = (WORD)w; height = (WORD)h; - } - int disposal_method; - WORD left, top, width, height; -}; - -//GIF defines a max of 12 bits per code -#define MAX_LZW_CODE 4096 - -class StringTable -{ -public: - StringTable(); - ~StringTable(); - void Initialize(int minCodeSize); - BYTE *FillInputBuffer(int len); - void CompressStart(int bpp, int width); - int CompressEnd(BYTE *buf); //0-4 bytes - bool Compress(BYTE *buf, int *len); - bool Decompress(BYTE *buf, int *len); - void Done(void); - -protected: - bool m_done; - - int m_minCodeSize, m_clearCode, m_endCode, m_nextCode; - - int m_bpp, m_slack; //Compressor information - - int m_prefix; //Compressor state variable - int m_codeSize, m_codeMask; //Compressor/Decompressor state variables - int m_oldCode; //Decompressor state variable - int m_partial, m_partialSize; //Compressor/Decompressor bit buffer - - int firstPixelPassed; // A specific flag that indicates if the first pixel - // of the whole image had already been read - - std::string m_strings[MAX_LZW_CODE]; //This is what is really the "string table" data for the Decompressor - int* m_strmap; - - //input buffer - BYTE *m_buffer; - int m_bufferSize, m_bufferRealSize, m_bufferPos, m_bufferShift; - - void ClearCompressorTable(void); - void ClearDecompressorTable(void); -}; - -#define GIF_PACKED_LSD_HAVEGCT 0x80 -#define GIF_PACKED_LSD_COLORRES 0x70 -#define GIF_PACKED_LSD_GCTSORTED 0x08 -#define GIF_PACKED_LSD_GCTSIZE 0x07 -#define GIF_PACKED_ID_HAVELCT 0x80 -#define GIF_PACKED_ID_INTERLACED 0x40 -#define GIF_PACKED_ID_LCTSORTED 0x20 -#define GIF_PACKED_ID_RESERVED 0x18 -#define GIF_PACKED_ID_LCTSIZE 0x07 -#define GIF_PACKED_GCE_RESERVED 0xE0 -#define GIF_PACKED_GCE_DISPOSAL 0x1C -#define GIF_PACKED_GCE_WAITINPUT 0x02 -#define GIF_PACKED_GCE_HAVETRANS 0x01 - -#define GIF_BLOCK_IMAGE_DESCRIPTOR 0x2C -#define GIF_BLOCK_EXTENSION 0x21 -#define GIF_BLOCK_TRAILER 0x3B - -#define GIF_EXT_PLAINTEXT 0x01 -#define GIF_EXT_GRAPHIC_CONTROL 0xF9 -#define GIF_EXT_COMMENT 0xFE -#define GIF_EXT_APPLICATION 0xFF - -#define GIF_INTERLACE_PASSES 4 -static int g_GifInterlaceOffset[GIF_INTERLACE_PASSES] = {0, 4, 2, 1}; -static int g_GifInterlaceIncrement[GIF_INTERLACE_PASSES] = {8, 8, 4, 2}; - -// ========================================================== -// Helpers Functions -// ========================================================== - -static BOOL -FreeImage_SetMetadataEx(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, WORD id, FREE_IMAGE_MDTYPE type, DWORD count, DWORD length, const void *value) -{ - BOOL bResult = FALSE; - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - FreeImage_SetTagKey(tag, key); - FreeImage_SetTagID(tag, id); - FreeImage_SetTagType(tag, type); - FreeImage_SetTagCount(tag, count); - FreeImage_SetTagLength(tag, length); - FreeImage_SetTagValue(tag, value); - if(model == FIMD_ANIMATION) { - TagLib& s = TagLib::instance(); - // get the tag description - const char *description = s.getTagDescription(TagLib::ANIMATION, id); - FreeImage_SetTagDescription(tag, description); - } - // store the tag - bResult = FreeImage_SetMetadata(model, dib, key, tag); - FreeImage_DeleteTag(tag); - } - return bResult; -} - -static BOOL -FreeImage_GetMetadataEx(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FREE_IMAGE_MDTYPE type, FITAG **tag) -{ - if( FreeImage_GetMetadata(model, dib, key, tag) ) { - if( FreeImage_GetTagType(*tag) == type ) { - return TRUE; - } - } - return FALSE; -} - -StringTable::StringTable() -{ - m_buffer = NULL; - firstPixelPassed = 0; // Still no pixel read - // Maximum number of entries in the map is MAX_LZW_CODE * 256 - // (aka 2**12 * 2**8 => a 20 bits key) - // This Map could be optmized to only handle MAX_LZW_CODE * 2**(m_bpp) - m_strmap = new(std::nothrow) int[1<<20]; -} - -StringTable::~StringTable() -{ - if( m_buffer != NULL ) { - delete [] m_buffer; - } - if( m_strmap != NULL ) { - delete [] m_strmap; - m_strmap = NULL; - } -} - -void StringTable::Initialize(int minCodeSize) -{ - m_done = false; - - m_bpp = 8; - m_minCodeSize = minCodeSize; - m_clearCode = 1 << m_minCodeSize; - if(m_clearCode > MAX_LZW_CODE) { - m_clearCode = MAX_LZW_CODE; - } - m_endCode = m_clearCode + 1; - - m_partial = 0; - m_partialSize = 0; - - m_bufferSize = 0; - ClearCompressorTable(); - ClearDecompressorTable(); -} - -BYTE *StringTable::FillInputBuffer(int len) -{ - if( m_buffer == NULL ) { - m_buffer = new(std::nothrow) BYTE[len]; - m_bufferRealSize = len; - } else if( len > m_bufferRealSize ) { - delete [] m_buffer; - m_buffer = new(std::nothrow) BYTE[len]; - m_bufferRealSize = len; - } - m_bufferSize = len; - m_bufferPos = 0; - m_bufferShift = 8 - m_bpp; - return m_buffer; -} - -void StringTable::CompressStart(int bpp, int width) -{ - m_bpp = bpp; - m_slack = (8 - ((width * bpp) % 8)) % 8; - - m_partial |= m_clearCode << m_partialSize; - m_partialSize += m_codeSize; - ClearCompressorTable(); -} - -int StringTable::CompressEnd(BYTE *buf) -{ - int len = 0; - - //output code for remaining prefix - m_partial |= m_prefix << m_partialSize; - m_partialSize += m_codeSize; - while( m_partialSize >= 8 ) { - *buf++ = (BYTE)m_partial; - m_partial >>= 8; - m_partialSize -= 8; - len++; - } - - //add the end of information code and flush the entire buffer out - m_partial |= m_endCode << m_partialSize; - m_partialSize += m_codeSize; - while( m_partialSize > 0 ) { - *buf++ = (BYTE)m_partial; - m_partial >>= 8; - m_partialSize -= 8; - len++; - } - - //most this can be is 4 bytes. 7 bits in m_partial to start + 12 for the - //last code + 12 for the end code = 31 bits total. - return len; -} - -bool StringTable::Compress(BYTE *buf, int *len) -{ - if( m_bufferSize == 0 || m_done ) { - return false; - } - - int mask = (1 << m_bpp) - 1; - BYTE *bufpos = buf; - while( m_bufferPos < m_bufferSize ) { - //get the current pixel value - char ch = (char)((m_buffer[m_bufferPos] >> m_bufferShift) & mask); - - // The next prefix is : - // <the previous LZW code (on 12 bits << 8)> | <the code of the current pixel (on 8 bits)> - int nextprefix = (((m_prefix)<<8)&0xFFF00) + (ch & 0x000FF); - if(firstPixelPassed) { - - if( m_strmap[nextprefix] > 0) { - m_prefix = m_strmap[nextprefix]; - } else { - m_partial |= m_prefix << m_partialSize; - m_partialSize += m_codeSize; - //grab full bytes for the output buffer - while( m_partialSize >= 8 && bufpos - buf < *len ) { - *bufpos++ = (BYTE)m_partial; - m_partial >>= 8; - m_partialSize -= 8; - } - - //add the code to the "table map" - m_strmap[nextprefix] = m_nextCode; - - //increment the next highest valid code, increase the code size - if( m_nextCode == (1 << m_codeSize) ) { - m_codeSize++; - } - m_nextCode++; - - //if we're out of codes, restart the string table - if( m_nextCode == MAX_LZW_CODE ) { - m_partial |= m_clearCode << m_partialSize; - m_partialSize += m_codeSize; - ClearCompressorTable(); - } - - // Only keep the 8 lowest bits (prevent problems with "negative chars") - m_prefix = ch & 0x000FF; - } - - //increment to the next pixel - if( m_bufferShift > 0 && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack) ) { - m_bufferShift -= m_bpp; - } else { - m_bufferPos++; - m_bufferShift = 8 - m_bpp; - } - - //jump out here if the output buffer is full - if( bufpos - buf == *len ) { - return true; - } - - } else { - // Specific behavior for the first pixel of the whole image - - firstPixelPassed=1; - // Only keep the 8 lowest bits (prevent problems with "negative chars") - m_prefix = ch & 0x000FF; - - //increment to the next pixel - if( m_bufferShift > 0 && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack) ) { - m_bufferShift -= m_bpp; - } else { - m_bufferPos++; - m_bufferShift = 8 - m_bpp; - } - - //jump out here if the output buffer is full - if( bufpos - buf == *len ) { - return true; - } - } - } - - m_bufferSize = 0; - *len = (int)(bufpos - buf); - - return true; -} - -bool StringTable::Decompress(BYTE *buf, int *len) -{ - if( m_bufferSize == 0 || m_done ) { - return false; - } - - BYTE *bufpos = buf; - for( ; m_bufferPos < m_bufferSize; m_bufferPos++ ) { - m_partial |= (int)m_buffer[m_bufferPos] << m_partialSize; - m_partialSize += 8; - while( m_partialSize >= m_codeSize ) { - int code = m_partial & m_codeMask; - m_partial >>= m_codeSize; - m_partialSize -= m_codeSize; - - if( code > m_nextCode || /*(m_nextCode == MAX_LZW_CODE && code != m_clearCode) || */code == m_endCode ) { - m_done = true; - *len = (int)(bufpos - buf); - return true; - } - if( code == m_clearCode ) { - ClearDecompressorTable(); - continue; - } - - //add new string to string table, if not the first pass since a clear code - if( m_oldCode != MAX_LZW_CODE && m_nextCode < MAX_LZW_CODE) { - m_strings[m_nextCode] = m_strings[m_oldCode] + m_strings[code == m_nextCode ? m_oldCode : code][0]; - } - - if( (int)m_strings[code].size() > *len - (bufpos - buf) ) { - //out of space, stuff the code back in for next time - m_partial <<= m_codeSize; - m_partialSize += m_codeSize; - m_partial |= code; - m_bufferPos++; - *len = (int)(bufpos - buf); - return true; - } - - //output the string into the buffer - memcpy(bufpos, m_strings[code].data(), m_strings[code].size()); - bufpos += m_strings[code].size(); - - //increment the next highest valid code, add a bit to the mask if we need to increase the code size - if( m_oldCode != MAX_LZW_CODE && m_nextCode < MAX_LZW_CODE ) { - if( ++m_nextCode < MAX_LZW_CODE ) { - if( (m_nextCode & m_codeMask) == 0 ) { - m_codeSize++; - m_codeMask |= m_nextCode; - } - } - } - - m_oldCode = code; - } - } - - m_bufferSize = 0; - *len = (int)(bufpos - buf); - - return true; -} - -void StringTable::Done(void) -{ - m_done = true; -} - -void StringTable::ClearCompressorTable(void) -{ - if(m_strmap) { - memset(m_strmap, 0xFF, sizeof(unsigned int)*(1<<20)); - } - m_nextCode = m_endCode + 1; - - m_prefix = 0; - m_codeSize = m_minCodeSize + 1; -} - -void StringTable::ClearDecompressorTable(void) -{ - for( int i = 0; i < m_clearCode; i++ ) { - m_strings[i].resize(1); - m_strings[i][0] = (char)i; - } - m_nextCode = m_endCode + 1; - - m_codeSize = m_minCodeSize + 1; - m_codeMask = (1 << m_codeSize) - 1; - m_oldCode = MAX_LZW_CODE; -} - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "GIF"; -} - -static const char * DLL_CALLCONV -Description() { - return "Graphics Interchange Format"; -} - -static const char * DLL_CALLCONV -Extension() { - return "gif"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return "^GIF"; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/gif"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - char buf[6]; - if( io->read_proc(buf, 6, 1, handle) < 1 ) { - return FALSE; - } - - 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->seek_proc(handle, -6, SEEK_CUR); - - return bResult; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return (depth == 1) || - (depth == 4) || - (depth == 8); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -// ---------------------------------------------------------- - -static void *DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - GIFinfo *info = new(std::nothrow) GIFinfo; - if( info == NULL ) { - 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)); - - info->read = read; - if( read ) { - try { - //Header - 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); - BYTE packed; - if( io->read_proc(&packed, 1, 1, handle) < 1 ) { - throw "EOF reading Logical Screen Descriptor"; - } - if( io->read_proc(&info->background_color, 1, 1, handle) < 1 ) { - throw "EOF reading Logical Screen Descriptor"; - } - io->seek_proc(handle, 1, SEEK_CUR); - - //Global Color Table - if( packed & GIF_PACKED_LSD_HAVEGCT ) { - info->global_color_table_offset = io->tell_proc(handle); - info->global_color_table_size = 2 << (packed & GIF_PACKED_LSD_GCTSIZE); - io->seek_proc(handle, 3 * info->global_color_table_size, SEEK_CUR); - } - - //Scan through all the rest of the blocks, saving offsets - size_t gce_offset = 0; - BYTE block = 0; - while( block != GIF_BLOCK_TRAILER ) { - if( io->read_proc(&block, 1, 1, handle) < 1 ) { - throw "EOF reading blocks"; - } - if( block == GIF_BLOCK_IMAGE_DESCRIPTOR ) { - info->image_descriptor_offsets.push_back(io->tell_proc(handle)); - //GCE may be 0, meaning no GCE preceded this ID - info->graphic_control_extension_offsets.push_back(gce_offset); - gce_offset = 0; - - io->seek_proc(handle, 8, SEEK_CUR); - if( io->read_proc(&packed, 1, 1, handle) < 1 ) { - throw "EOF reading Image Descriptor"; - } - - //Local Color Table - if( packed & GIF_PACKED_ID_HAVELCT ) { - io->seek_proc(handle, 3 * (2 << (packed & GIF_PACKED_ID_LCTSIZE)), SEEK_CUR); - } - - //LZW Minimum Code Size - io->seek_proc(handle, 1, SEEK_CUR); - } else if( block == GIF_BLOCK_EXTENSION ) { - BYTE ext; - if( io->read_proc(&ext, 1, 1, handle) < 1 ) { - throw "EOF reading extension"; - } - - if( ext == GIF_EXT_GRAPHIC_CONTROL ) { - //overwrite previous offset if more than one GCE found before an ID - gce_offset = io->tell_proc(handle); - } else if( ext == GIF_EXT_COMMENT ) { - info->comment_extension_offsets.push_back(io->tell_proc(handle)); - } else if( ext == GIF_EXT_APPLICATION ) { - info->application_extension_offsets.push_back(io->tell_proc(handle)); - } - } else if( block == GIF_BLOCK_TRAILER ) { - continue; - } else { - throw "Invalid GIF block found"; - } - - //Data Sub-blocks - BYTE len; - if( io->read_proc(&len, 1, 1, handle) < 1 ) { - throw "EOF reading sub-block"; - } - while( len != 0 ) { - io->seek_proc(handle, len, SEEK_CUR); - if( io->read_proc(&len, 1, 1, handle) < 1 ) { - throw "EOF reading sub-block"; - } - } - } - } catch (const char *msg) { - FreeImage_OutputMessageProc(s_format_id, msg); - delete info; - return NULL; - } - } else { - //Header - io->write_proc((void *)"GIF89a", 6, 1, handle); - } - - return info; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { - if( data == NULL ) { - return; - } - GIFinfo *info = (GIFinfo *)data; - - if( !info->read ) { - //Trailer - BYTE b = GIF_BLOCK_TRAILER; - io->write_proc(&b, 1, 1, handle); - } - - delete info; -} - -static int DLL_CALLCONV -PageCount(FreeImageIO *io, fi_handle handle, void *data) { - if( data == NULL ) { - return 0; - } - GIFinfo *info = (GIFinfo *)data; - - return (int) info->image_descriptor_offsets.size(); -} - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if( data == NULL ) { - return NULL; - } - GIFinfo *info = (GIFinfo *)data; - - if( page == -1 ) { - page = 0; - } - if( page < 0 || page >= (int)info->image_descriptor_offsets.size() ) { - return NULL; - } - - FIBITMAP *dib = NULL; - try { - bool have_transparent = false, no_local_palette = false, interlaced = false; - int disposal_method = GIF_DISPOSAL_LEAVE, delay_time = 0, transparent_color = 0; - WORD left, top, width, height; - BYTE packed, b; - WORD w; - - //playback pages to generate what the user would see for this frame - if( (flags & GIF_PLAYBACK) == GIF_PLAYBACK ) { - //Logical Screen Descriptor - io->seek_proc(handle, 6, SEEK_SET); - WORD logicalwidth, logicalheight; - io->read_proc(&logicalwidth, 2, 1, handle); - io->read_proc(&logicalheight, 2, 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&logicalwidth); - SwapShort(&logicalheight); -#endif - //set the background color with 0 alpha - RGBQUAD background; - if( info->global_color_table_offset != 0 && info->background_color < info->global_color_table_size ) { - io->seek_proc(handle, (long)(info->global_color_table_offset + (info->background_color * 3)), SEEK_SET); - io->read_proc(&background.rgbRed, 1, 1, handle); - io->read_proc(&background.rgbGreen, 1, 1, handle); - io->read_proc(&background.rgbBlue, 1, 1, handle); - } else { - background.rgbRed = 0; - background.rgbGreen = 0; - background.rgbBlue = 0; - } - background.rgbReserved = 0; - - //allocate entire logical area - dib = FreeImage_Allocate(logicalwidth, logicalheight, 32); - if( dib == NULL ) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - //fill with background color to start - int x, y; - RGBQUAD *scanline; - for( y = 0; y < logicalheight; y++ ) { - scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, y); - for( x = 0; x < logicalwidth; x++ ) { - *scanline++ = background; - } - } - - //cache some info about each of the pages so we can avoid decoding as many of them as possible - std::vector<PageInfo> pageinfo; - int start = page, end = page; - while( start >= 0 ) { - //Graphic Control Extension - io->seek_proc(handle, (long)(info->graphic_control_extension_offsets[start] + 1), SEEK_SET); - io->read_proc(&packed, 1, 1, handle); - have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false; - disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2; - //Image Descriptor - io->seek_proc(handle, (long)(info->image_descriptor_offsets[start]), SEEK_SET); - io->read_proc(&left, 2, 1, handle); - io->read_proc(&top, 2, 1, handle); - io->read_proc(&width, 2, 1, handle); - io->read_proc(&height, 2, 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&left); - SwapShort(&top); - SwapShort(&width); - SwapShort(&height); -#endif - - pageinfo.push_back(PageInfo(disposal_method, left, top, width, height)); - - if( start != end ) { - if( left == 0 && top == 0 && width == logicalwidth && height == logicalheight ) { - if( disposal_method == GIF_DISPOSAL_BACKGROUND ) { - pageinfo.pop_back(); - start++; - break; - } else if( disposal_method != GIF_DISPOSAL_PREVIOUS ) { - if( !have_transparent ) { - break; - } - } - } - } - start--; - } - if( start < 0 ) { - start = 0; - } - - //draw each page into the logical area - delay_time = 0; - for( page = start; page <= end; page++ ) { - PageInfo &info = pageinfo[end - page]; - //things we can skip having to decode - if( page != end ) { - if( info.disposal_method == GIF_DISPOSAL_PREVIOUS ) { - continue; - } - if( info.disposal_method == GIF_DISPOSAL_BACKGROUND ) { - for( y = 0; y < info.height; y++ ) { - const int scanidx = logicalheight - (y + info.top) - 1; - if ( scanidx < 0 ) { - break; // If data is corrupt, don't calculate in invalid scanline - } - scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, scanidx) + info.left; - for( x = 0; x < info.width; x++ ) { - *scanline++ = background; - } - } - continue; - } - } - - //decode page - FIBITMAP *pagedib = Load(io, handle, page, GIF_LOAD256, data); - if( pagedib != NULL ) { - RGBQUAD *pal = FreeImage_GetPalette(pagedib); - have_transparent = false; - if( FreeImage_IsTransparent(pagedib) ) { - int count = FreeImage_GetTransparencyCount(pagedib); - BYTE *table = FreeImage_GetTransparencyTable(pagedib); - for( int i = 0; i < count; i++ ) { - if( table[i] == 0 ) { - have_transparent = true; - transparent_color = i; - break; - } - } - } - //copy page data into logical buffer, with full alpha opaqueness - for( y = 0; y < info.height; y++ ) { - const int scanidx = logicalheight - (y + info.top) - 1; - if ( scanidx < 0 ) { - break; // If data is corrupt, don't calculate in invalid scanline - } - scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, scanidx) + info.left; - BYTE *pageline = FreeImage_GetScanLine(pagedib, info.height - y - 1); - for( x = 0; x < info.width; x++ ) { - if( !have_transparent || *pageline != transparent_color ) { - *scanline = pal[*pageline]; - scanline->rgbReserved = 255; - } - scanline++; - pageline++; - } - } - //copy frame time - if( page == end ) { - FITAG *tag; - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, pagedib, "FrameTime", FIDT_LONG, &tag) ) { - delay_time = *(LONG *)FreeImage_GetTagValue(tag); - } - } - FreeImage_Unload(pagedib); - } - } - - //setup frame time - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameTime", ANIMTAG_FRAMETIME, FIDT_LONG, 1, 4, &delay_time); - return dib; - } - - //get the actual frame image data for a single frame - - //Image Descriptor - io->seek_proc(handle, (long)info->image_descriptor_offsets[page], SEEK_SET); - io->read_proc(&left, 2, 1, handle); - io->read_proc(&top, 2, 1, handle); - io->read_proc(&width, 2, 1, handle); - io->read_proc(&height, 2, 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&left); - SwapShort(&top); - SwapShort(&width); - SwapShort(&height); -#endif - io->read_proc(&packed, 1, 1, handle); - interlaced = (packed & GIF_PACKED_ID_INTERLACED) ? true : false; - no_local_palette = (packed & GIF_PACKED_ID_HAVELCT) ? false : true; - - int bpp = 8; - if( (flags & GIF_LOAD256) == 0 ) { - if( !no_local_palette ) { - int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE); - if( size <= 2 ) bpp = 1; - else if( size <= 16 ) bpp = 4; - } else if( info->global_color_table_offset != 0 ) { - if( info->global_color_table_size <= 2 ) bpp = 1; - else if( info->global_color_table_size <= 16 ) bpp = 4; - } - } - dib = FreeImage_Allocate(width, height, bpp); - if( dib == NULL ) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameLeft", ANIMTAG_FRAMELEFT, FIDT_SHORT, 1, 2, &left); - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameTop", ANIMTAG_FRAMETOP, FIDT_SHORT, 1, 2, &top); - b = no_local_palette ? 1 : 0; - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "NoLocalPalette", ANIMTAG_NOLOCALPALETTE, FIDT_BYTE, 1, 1, &b); - b = interlaced ? 1 : 0; - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "Interlaced", ANIMTAG_INTERLACED, FIDT_BYTE, 1, 1, &b); - - //Palette - RGBQUAD *pal = FreeImage_GetPalette(dib); - if( !no_local_palette ) { - int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE); - - int i = 0; - while( i < size ) { - io->read_proc(&pal[i].rgbRed, 1, 1, handle); - io->read_proc(&pal[i].rgbGreen, 1, 1, handle); - io->read_proc(&pal[i].rgbBlue, 1, 1, handle); - i++; - } - } else if( info->global_color_table_offset != 0 ) { - long pos = io->tell_proc(handle); - io->seek_proc(handle, (long)info->global_color_table_offset, SEEK_SET); - - int i = 0; - while( i < info->global_color_table_size ) { - io->read_proc(&pal[i].rgbRed, 1, 1, handle); - io->read_proc(&pal[i].rgbGreen, 1, 1, handle); - io->read_proc(&pal[i].rgbBlue, 1, 1, handle); - i++; - } - - io->seek_proc(handle, pos, SEEK_SET); - } else { - //its legal to have no palette, but we're going to generate *something* - for( int i = 0; i < 256; i++ ) { - pal[i].rgbRed = (BYTE)i; - pal[i].rgbGreen = (BYTE)i; - pal[i].rgbBlue = (BYTE)i; - } - } - - //LZW Minimum Code Size - io->read_proc(&b, 1, 1, handle); - StringTable *stringtable = new(std::nothrow) StringTable; - stringtable->Initialize(b); - - //Image Data Sub-blocks - int x = 0, xpos = 0, y = 0, shift = 8 - bpp, mask = (1 << bpp) - 1, interlacepass = 0; - BYTE *scanline = FreeImage_GetScanLine(dib, height - 1); - BYTE buf[4096]; - io->read_proc(&b, 1, 1, handle); - while( b ) { - io->read_proc(stringtable->FillInputBuffer(b), b, 1, handle); - int size = sizeof(buf); - while( stringtable->Decompress(buf, &size) ) { - for( int i = 0; i < size; i++ ) { - scanline[xpos] |= (buf[i] & mask) << shift; - if( shift > 0 ) { - shift -= bpp; - } else { - xpos++; - shift = 8 - bpp; - } - if( ++x >= width ) { - if( interlaced ) { - y += g_GifInterlaceIncrement[interlacepass]; - if( y >= height && ++interlacepass < GIF_INTERLACE_PASSES ) { - y = g_GifInterlaceOffset[interlacepass]; - } - } else { - y++; - } - if( y >= height ) { - stringtable->Done(); - break; - } - x = xpos = 0; - shift = 8 - bpp; - scanline = FreeImage_GetScanLine(dib, height - y - 1); - } - } - size = sizeof(buf); - } - io->read_proc(&b, 1, 1, handle); - } - - if( page == 0 ) { - size_t idx; - - //Logical Screen Descriptor - io->seek_proc(handle, 6, SEEK_SET); - WORD logicalwidth, logicalheight; - io->read_proc(&logicalwidth, 2, 1, handle); - io->read_proc(&logicalheight, 2, 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&logicalwidth); - SwapShort(&logicalheight); -#endif - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "LogicalWidth", ANIMTAG_LOGICALWIDTH, FIDT_SHORT, 1, 2, &logicalwidth); - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "LogicalHeight", ANIMTAG_LOGICALHEIGHT, FIDT_SHORT, 1, 2, &logicalheight); - - //Global Color Table - if( info->global_color_table_offset != 0 ) { - RGBQUAD globalpalette[256]; - io->seek_proc(handle, (long)info->global_color_table_offset, SEEK_SET); - int i = 0; - while( i < info->global_color_table_size ) { - io->read_proc(&globalpalette[i].rgbRed, 1, 1, handle); - io->read_proc(&globalpalette[i].rgbGreen, 1, 1, handle); - io->read_proc(&globalpalette[i].rgbBlue, 1, 1, handle); - globalpalette[i].rgbReserved = 0; - i++; - } - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "GlobalPalette", ANIMTAG_GLOBALPALETTE, FIDT_PALETTE, info->global_color_table_size, info->global_color_table_size * 4, globalpalette); - //background color - if( info->background_color < info->global_color_table_size ) { - FreeImage_SetBackgroundColor(dib, &globalpalette[info->background_color]); - } - } - - //Application Extension - LONG loop = 1; //If no AE with a loop count is found, the default must be 1 - for( idx = 0; idx < info->application_extension_offsets.size(); idx++ ) { - io->seek_proc(handle, (long)info->application_extension_offsets[idx], SEEK_SET); - io->read_proc(&b, 1, 1, handle); - if( b == 11 ) { //All AEs start with an 11 byte sub-block to determine what type of AE it is - char buf[11]; - io->read_proc(buf, 11, 1, handle); - if( !memcmp(buf, "NETSCAPE2.0", 11) || !memcmp(buf, "ANIMEXTS1.0", 11) ) { //Not everybody recognizes ANIMEXTS1.0 but it is valid - io->read_proc(&b, 1, 1, handle); - if( b == 3 ) { //we're supposed to have a 3 byte sub-block now - io->read_proc(&b, 1, 1, handle); //this should be 0x01 but isn't really important - io->read_proc(&w, 2, 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&w); -#endif - loop = w; - if( loop > 0 ) loop++; - break; - } - } - } - } - 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++) { - 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) { - 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); - DWORD comment_size = (DWORD)comment.size(); - FreeImage_SetMetadataEx(FIMD_COMMENTS, dib, buf, 1, FIDT_ASCII, comment_size, comment_size, comment.c_str()); - } - } - - //Graphic Control Extension - if( info->graphic_control_extension_offsets[page] != 0 ) { - io->seek_proc(handle, (long)(info->graphic_control_extension_offsets[page] + 1), SEEK_SET); - io->read_proc(&packed, 1, 1, handle); - io->read_proc(&w, 2, 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&w); -#endif - io->read_proc(&b, 1, 1, handle); - have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false; - disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2; - delay_time = w * 10; //convert cs to ms - transparent_color = b; - if( have_transparent ) { - int size = 1 << bpp; - if( transparent_color <= size ) { - BYTE table[256]; - memset(table, 0xFF, size); - table[transparent_color] = 0; - FreeImage_SetTransparencyTable(dib, table, size); - } - } - } - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameTime", ANIMTAG_FRAMETIME, FIDT_LONG, 1, 4, &delay_time); - b = (BYTE)disposal_method; - FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "DisposalMethod", ANIMTAG_DISPOSALMETHOD, FIDT_BYTE, 1, 1, &b); - - delete stringtable; - - } catch (const char *msg) { - if( dib != NULL ) { - FreeImage_Unload(dib); - } - FreeImage_OutputMessageProc(s_format_id, msg); - return NULL; - } - - return dib; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - if( data == NULL ) { - return FALSE; - } - //GIFinfo *info = (GIFinfo *)data; - - if( page == -1 ) { - page = 0; - } - - try { - BYTE packed, b; - WORD w; - FITAG *tag; - - int bpp = FreeImage_GetBPP(dib); - if( bpp != 1 && bpp != 4 && bpp != 8 ) { - throw "Only 1, 4, or 8 bpp images supported"; - } - - bool have_transparent = false, no_local_palette = false, interlaced = false; - int disposal_method = GIF_DISPOSAL_BACKGROUND, delay_time = 100, transparent_color = 0; - WORD left = 0, top = 0, width = (WORD)FreeImage_GetWidth(dib), height = (WORD)FreeImage_GetHeight(dib); - WORD output_height = height; - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "FrameLeft", FIDT_SHORT, &tag) ) { - left = *(WORD *)FreeImage_GetTagValue(tag); - } - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "FrameTop", FIDT_SHORT, &tag) ) { - top = *(WORD *)FreeImage_GetTagValue(tag); - } - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "NoLocalPalette", FIDT_BYTE, &tag) ) { - no_local_palette = *(BYTE *)FreeImage_GetTagValue(tag) ? true : false; - } - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "Interlaced", FIDT_BYTE, &tag) ) { - interlaced = *(BYTE *)FreeImage_GetTagValue(tag) ? true : false; - } - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "FrameTime", FIDT_LONG, &tag) ) { - delay_time = *(LONG *)FreeImage_GetTagValue(tag); - } - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "DisposalMethod", FIDT_BYTE, &tag) ) { - disposal_method = *(BYTE *)FreeImage_GetTagValue(tag); - } - - RGBQUAD *pal = FreeImage_GetPalette(dib); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&left); - SwapShort(&top); - SwapShort(&width); - SwapShort(&height); -#endif - - if( page == 0 ) { - //gather some info - WORD logicalwidth = width; // width has already been swapped... - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "LogicalWidth", FIDT_SHORT, &tag) ) { - logicalwidth = *(WORD *)FreeImage_GetTagValue(tag); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&logicalwidth); -#endif - } - WORD logicalheight = height; // height has already been swapped... - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "LogicalHeight", FIDT_SHORT, &tag) ) { - logicalheight = *(WORD *)FreeImage_GetTagValue(tag); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&logicalheight); -#endif - } - RGBQUAD *globalpalette = NULL; - int globalpalette_size = 0; - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "GlobalPalette", FIDT_PALETTE, &tag) ) { - globalpalette_size = FreeImage_GetTagCount(tag); - if( globalpalette_size >= 2 ) { - globalpalette = (RGBQUAD *)FreeImage_GetTagValue(tag); - } - } - - //Logical Screen Descriptor - io->write_proc(&logicalwidth, 2, 1, handle); - io->write_proc(&logicalheight, 2, 1, handle); - packed = GIF_PACKED_LSD_COLORRES; - b = 0; - RGBQUAD background_color; - if( globalpalette != NULL ) { - packed |= GIF_PACKED_LSD_HAVEGCT; - if( globalpalette_size < 4 ) { - globalpalette_size = 2; - packed |= 0 & GIF_PACKED_LSD_GCTSIZE; - } else if( globalpalette_size < 8 ) { - globalpalette_size = 4; - packed |= 1 & GIF_PACKED_LSD_GCTSIZE; - } else if( globalpalette_size < 16 ) { - globalpalette_size = 8; - packed |= 2 & GIF_PACKED_LSD_GCTSIZE; - } else if( globalpalette_size < 32 ) { - globalpalette_size = 16; - packed |= 3 & GIF_PACKED_LSD_GCTSIZE; - } else if( globalpalette_size < 64 ) { - globalpalette_size = 32; - packed |= 4 & GIF_PACKED_LSD_GCTSIZE; - } else if( globalpalette_size < 128 ) { - globalpalette_size = 64; - packed |= 5 & GIF_PACKED_LSD_GCTSIZE; - } else if( globalpalette_size < 256 ) { - globalpalette_size = 128; - packed |= 6 & GIF_PACKED_LSD_GCTSIZE; - } else { - globalpalette_size = 256; - packed |= 7 & GIF_PACKED_LSD_GCTSIZE; - } - if( FreeImage_GetBackgroundColor(dib, &background_color) ) { - for( int i = 0; i < globalpalette_size; i++ ) { - if( background_color.rgbRed == globalpalette[i].rgbRed && - background_color.rgbGreen == globalpalette[i].rgbGreen && - background_color.rgbBlue == globalpalette[i].rgbBlue ) { - - b = (BYTE)i; - break; - } - } - } - } else { - packed |= (bpp - 1) & GIF_PACKED_LSD_GCTSIZE; - } - io->write_proc(&packed, 1, 1, handle); - io->write_proc(&b, 1, 1, handle); - b = 0; - io->write_proc(&b, 1, 1, handle); - - //Global Color Table - if( globalpalette != NULL ) { - int i = 0; - while( i < globalpalette_size ) { - io->write_proc(&globalpalette[i].rgbRed, 1, 1, handle); - io->write_proc(&globalpalette[i].rgbGreen, 1, 1, handle); - io->write_proc(&globalpalette[i].rgbBlue, 1, 1, handle); - i++; - } - } - - //Application Extension - LONG loop = 0; - if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "Loop", FIDT_LONG, &tag) ) { - loop = *(LONG *)FreeImage_GetTagValue(tag); - } - if( loop != 1 ) { - //the Netscape extension is really "repeats" not "loops" - if( loop > 1 ) loop--; - if( loop > 0xFFFF ) loop = 0xFFFF; - w = (WORD)loop; -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&w); -#endif - io->write_proc((void *)"\x21\xFF\x0BNETSCAPE2.0\x03\x01", 16, 1, handle); - io->write_proc(&w, 2, 1, handle); - b = 0; - io->write_proc(&b, 1, 1, handle); - } - - //Comment Extension - FIMETADATA *mdhandle = NULL; - FITAG *tag = NULL; - mdhandle = FreeImage_FindFirstMetadata(FIMD_COMMENTS, dib, &tag); - if( mdhandle ) { - do { - if( FreeImage_GetTagType(tag) == FIDT_ASCII ) { - int length = FreeImage_GetTagLength(tag) - 1; - char *value = (char *)FreeImage_GetTagValue(tag); - io->write_proc((void *)"\x21\xFE", 2, 1, handle); - while( length > 0 ) { - b = (BYTE)(length >= 255 ? 255 : length); - io->write_proc(&b, 1, 1, handle); - io->write_proc(value, b, 1, handle); - value += b; - length -= b; - } - b = 0; - io->write_proc(&b, 1, 1, handle); - } - } while(FreeImage_FindNextMetadata(mdhandle, &tag)); - - FreeImage_FindCloseMetadata(mdhandle); - } - } - - //Graphic Control Extension - if( FreeImage_IsTransparent(dib) ) { - int count = FreeImage_GetTransparencyCount(dib); - BYTE *table = FreeImage_GetTransparencyTable(dib); - for( int i = 0; i < count; i++ ) { - if( table[i] == 0 ) { - have_transparent = true; - transparent_color = i; - break; - } - } - } - io->write_proc((void *)"\x21\xF9\x04", 3, 1, handle); - b = (BYTE)((disposal_method << 2) & GIF_PACKED_GCE_DISPOSAL); - if( have_transparent ) b |= GIF_PACKED_GCE_HAVETRANS; - io->write_proc(&b, 1, 1, handle); - //Notes about delay time for GIFs: - //IE5/IE6 have a minimum and default of 100ms - //Mozilla/Firefox/Netscape 6+/Opera have a minimum of 20ms and a default of 100ms if <20ms is specified or the GCE is absent - //Netscape 4 has a minimum of 10ms if 0ms is specified, but will use 0ms if the GCE is absent - w = (WORD)(delay_time / 10); //convert ms to cs -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&w); -#endif - io->write_proc(&w, 2, 1, handle); - b = (BYTE)transparent_color; - io->write_proc(&b, 1, 1, handle); - b = 0; - io->write_proc(&b, 1, 1, handle); - - //Image Descriptor - b = GIF_BLOCK_IMAGE_DESCRIPTOR; - io->write_proc(&b, 1, 1, handle); - io->write_proc(&left, 2, 1, handle); - io->write_proc(&top, 2, 1, handle); - io->write_proc(&width, 2, 1, handle); - io->write_proc(&height, 2, 1, handle); - packed = 0; - if( !no_local_palette ) packed |= GIF_PACKED_ID_HAVELCT | ((bpp - 1) & GIF_PACKED_ID_LCTSIZE); - if( interlaced ) packed |= GIF_PACKED_ID_INTERLACED; - io->write_proc(&packed, 1, 1, handle); - - //Local Color Table - if( !no_local_palette ) { - int palsize = 1 << bpp; - for( int i = 0; i < palsize; i++ ) { - io->write_proc(&pal[i].rgbRed, 1, 1, handle); - io->write_proc(&pal[i].rgbGreen, 1, 1, handle); - io->write_proc(&pal[i].rgbBlue, 1, 1, handle); - } - } - - - //LZW Minimum Code Size - b = (BYTE)(bpp == 1 ? 2 : bpp); - io->write_proc(&b, 1, 1, handle); - StringTable *stringtable = new(std::nothrow) StringTable; - stringtable->Initialize(b); - stringtable->CompressStart(bpp, width); - - //Image Data Sub-blocks - int y = 0, interlacepass = 0, line = FreeImage_GetLine(dib); - BYTE buf[255], *bufptr = buf; //255 is the max sub-block length - int size = sizeof(buf); - b = sizeof(buf); - while( y < output_height ) { - memcpy(stringtable->FillInputBuffer(line), FreeImage_GetScanLine(dib, output_height - y - 1), line); - while( stringtable->Compress(bufptr, &size) ) { - bufptr += size; - if( bufptr - buf == sizeof(buf) ) { - io->write_proc(&b, 1, 1, handle); - io->write_proc(buf, sizeof(buf), 1, handle); - size = sizeof(buf); - bufptr = buf; - } else { - size = (int)(sizeof(buf) - (bufptr - buf)); - } - } - if( interlaced ) { - y += g_GifInterlaceIncrement[interlacepass]; - if( y >= output_height && ++interlacepass < GIF_INTERLACE_PASSES ) { - y = g_GifInterlaceOffset[interlacepass]; - } - } else { - y++; - } - } - size = (int)(bufptr - buf); - BYTE last[4]; - w = (WORD)stringtable->CompressEnd(last); - if( size + w >= sizeof(buf) ) { - //one last full size sub-block - io->write_proc(&b, 1, 1, handle); - io->write_proc(buf, size, 1, handle); - io->write_proc(last, sizeof(buf) - size, 1, handle); - //and possibly a tiny additional sub-block - b = (BYTE)(w - (sizeof(buf) - size)); - if( b > 0 ) { - io->write_proc(&b, 1, 1, handle); - io->write_proc(last + w - b, b, 1, handle); - } - } else { - //last sub-block less than full size - b = (BYTE)(size + w); - io->write_proc(&b, 1, 1, handle); - io->write_proc(buf, size, 1, handle); - io->write_proc(last, w, 1, handle); - } - - //Block Terminator - b = 0; - io->write_proc(&b, 1, 1, handle); - - delete stringtable; - - } catch (const char *msg) { - FreeImage_OutputMessageProc(s_format_id, msg); - return FALSE; - } - - return TRUE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitGIF(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = PageCount; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginICO.cpp b/plugins/AdvaImg/src/FreeImage/PluginICO.cpp deleted file mode 100644 index 5c4673e4de..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginICO.cpp +++ /dev/null @@ -1,824 +0,0 @@ -// ========================================================== -// ICO Loader and Writer -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// Constants + headers -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -// These next two structs represent how the icon information is stored -// in an ICO file. - -typedef struct tagICONHEADER { - WORD idReserved; // reserved - WORD idType; // resource type (1 for icons) - WORD idCount; // how many images? -} ICONHEADER; - -typedef struct tagICONDIRECTORYENTRY { - BYTE bWidth; // width of the image - BYTE bHeight; // height of the image (times 2) - BYTE bColorCount; // number of colors in image (0 if >=8bpp) - BYTE bReserved; // reserved - WORD wPlanes; // color Planes - WORD wBitCount; // bits per pixel - DWORD dwBytesInRes; // how many bytes in this resource? - DWORD dwImageOffset; // where in the file is this image -} ICONDIRENTRY; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -// ========================================================== -// Static helpers -// ========================================================== - -/** How wide, in bytes, would this many bits be, DWORD aligned ? -*/ -static int -WidthBytes(int bits) { - return ((((bits) + 31)>>5)<<2); -} - -/** Calculates the size of a single icon image -@return Returns the size for that image -*/ -static DWORD -CalculateImageSize(FIBITMAP* icon_dib) { - DWORD dwNumBytes = 0; - - unsigned colors = FreeImage_GetColorsUsed(icon_dib); - unsigned width = FreeImage_GetWidth(icon_dib); - unsigned height = FreeImage_GetHeight(icon_dib); - unsigned pitch = FreeImage_GetPitch(icon_dib); - - dwNumBytes = sizeof( BITMAPINFOHEADER ); // header - dwNumBytes += colors * sizeof(RGBQUAD); // palette - dwNumBytes += height * pitch; // XOR mask - dwNumBytes += height * WidthBytes(width); // AND mask - - return dwNumBytes; -} - -/** Calculates the file offset for an icon image -@return Returns the file offset for that image -*/ -static DWORD -CalculateImageOffset(std::vector<FIBITMAP*>& vPages, int nIndex ) { - DWORD dwSize; - - // calculate the ICO header size - dwSize = sizeof(ICONHEADER); - // add the ICONDIRENTRY's - dwSize += (DWORD)( vPages.size() * sizeof(ICONDIRENTRY) ); - // add the sizes of the previous images - for(int k = 0; k < nIndex; k++) { - FIBITMAP *icon_dib = (FIBITMAP*)vPages[k]; - dwSize += CalculateImageSize(icon_dib); - } - - return dwSize; -} - -/** -Vista icon support -@return Returns TRUE if the bitmap data is stored in PNG format -*/ -static BOOL -IsPNG(FreeImageIO *io, fi_handle handle) { - BYTE png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; - BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - long tell = io->tell_proc(handle); - io->read_proc(&signature, 1, 8, handle); - BOOL bIsPNG = (memcmp(png_signature, signature, 8) == 0); - io->seek_proc(handle, tell, SEEK_SET); - - return bIsPNG; -} - -#ifdef FREEIMAGE_BIGENDIAN -static void -SwapInfoHeader(BITMAPINFOHEADER *header) { - SwapLong(&header->biSize); - SwapLong((DWORD *)&header->biWidth); - SwapLong((DWORD *)&header->biHeight); - SwapShort(&header->biPlanes); - SwapShort(&header->biBitCount); - SwapLong(&header->biCompression); - SwapLong(&header->biSizeImage); - SwapLong((DWORD *)&header->biXPelsPerMeter); - SwapLong((DWORD *)&header->biYPelsPerMeter); - SwapLong(&header->biClrUsed); - SwapLong(&header->biClrImportant); -} - -static void -SwapIconHeader(ICONHEADER *header) { - SwapShort(&header->idReserved); - SwapShort(&header->idType); - SwapShort(&header->idCount); -} - -static void -SwapIconDirEntries(ICONDIRENTRY *ent, int num) { - while(num) { - SwapShort(&ent->wPlanes); - SwapShort(&ent->wBitCount); - SwapLong(&ent->dwBytesInRes); - SwapLong(&ent->dwImageOffset); - num--; - ent++; - } -} -#endif - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "ICO"; -} - -static const char * DLL_CALLCONV -Description() { - return "Windows Icon"; -} - -static const char * DLL_CALLCONV -Extension() { - return "ico"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/vnd.microsoft.icon"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - ICONHEADER icon_header; - - io->read_proc(&icon_header, sizeof(ICONHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapIconHeader(&icon_header); -#endif - - return ((icon_header.idReserved == 0) && (icon_header.idType == 1) && (icon_header.idCount > 0)); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 1) || - (depth == 4) || - (depth == 8) || - (depth == 16) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - // Allocate memory for the header structure - ICONHEADER *lpIH = (ICONHEADER*)malloc(sizeof(ICONHEADER)); - if(lpIH == NULL) { - return NULL; - } - - if (read) { - // Read in the header - io->read_proc(lpIH, 1, sizeof(ICONHEADER), handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapIconHeader(lpIH); -#endif - - if(!(lpIH->idReserved == 0) || !(lpIH->idType == 1)) { - // Not an ICO file - free(lpIH); - return NULL; - } - } - else { - // Fill the header - lpIH->idReserved = 0; - lpIH->idType = 1; - lpIH->idCount = 0; - } - - return lpIH; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { - // free the header structure - ICONHEADER *lpIH = (ICONHEADER*)data; - free(lpIH); -} - -// ---------------------------------------------------------- - -static int DLL_CALLCONV -PageCount(FreeImageIO *io, fi_handle handle, void *data) { - ICONHEADER *lpIH = (ICONHEADER*)data; - - if(lpIH) { - return lpIH->idCount; - } - return 1; -} - -// ---------------------------------------------------------- - -static FIBITMAP* -LoadStandardIcon(FreeImageIO *io, fi_handle handle, int flags, BOOL header_only) { - FIBITMAP *dib = NULL; - - // load the BITMAPINFOHEADER - BITMAPINFOHEADER bmih; - io->read_proc(&bmih, sizeof(BITMAPINFOHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapInfoHeader(&bmih); -#endif - - // allocate the bitmap - int width = bmih.biWidth; - int height = bmih.biHeight / 2; // height == xor + and mask - unsigned bit_count = bmih.biBitCount; - unsigned line = CalculateLine(width, bit_count); - unsigned pitch = CalculatePitch(line); - - // allocate memory for one icon - - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count); - - if (dib == NULL) { - return NULL; - } - - if( bmih.biBitCount <= 8 ) { - // read the palette data - io->read_proc(FreeImage_GetPalette(dib), CalculateUsedPaletteEntries(bit_count) * sizeof(RGBQUAD), 1, handle); -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - RGBQUAD *pal = FreeImage_GetPalette(dib); - for(unsigned i = 0; i < CalculateUsedPaletteEntries(bit_count); i++) { - INPLACESWAP(pal[i].rgbRed, pal[i].rgbBlue); - } -#endif - } - - if(header_only) { - // header only mode - return dib; - } - - // read the icon - io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle); - -#ifdef FREEIMAGE_BIGENDIAN - if (bit_count == 16) { - for(int y = 0; y < height; y++) { - WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y); - for(int x = 0; x < width; x++) { - SwapShort(pixel); - pixel++; - } - } - } -#endif -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - if (bit_count == 24 || bit_count == 32) { - for(int y = 0; y < height; y++) { - BYTE *pixel = FreeImage_GetScanLine(dib, y); - for(int x = 0; x < width; x++) { - INPLACESWAP(pixel[0], pixel[2]); - pixel += (bit_count>>3); - } - } - } -#endif - // bitmap has been loaded successfully! - - // convert to 32bpp and generate an alpha channel - // apply the AND mask only if the image is not 32 bpp - if(((flags & ICO_MAKEALPHA) == ICO_MAKEALPHA) && (bit_count < 32)) { - FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(dib); - FreeImage_Unload(dib); - - if (dib32 == NULL) { - return NULL; - } - - int width_and = WidthBytes(width); - BYTE *line_and = (BYTE *)malloc(width_and); - - if( line_and == NULL ) { - FreeImage_Unload(dib32); - return NULL; - } - - //loop through each line of the AND-mask generating the alpha channel, invert XOR-mask - for(int y = 0; y < height; y++) { - RGBQUAD *quad = (RGBQUAD *)FreeImage_GetScanLine(dib32, y); - io->read_proc(line_and, width_and, 1, handle); - for(int x = 0; x < width; x++) { - quad->rgbReserved = (line_and[x>>3] & (0x80 >> (x & 0x07))) != 0 ? 0 : 0xFF; - if( quad->rgbReserved == 0 ) { - quad->rgbBlue ^= 0xFF; - quad->rgbGreen ^= 0xFF; - quad->rgbRed ^= 0xFF; - } - quad++; - } - } - free(line_and); - - return dib32; - } - - return dib; -} - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (page == -1) { - page = 0; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - if (handle != NULL) { - FIBITMAP *dib = NULL; - - // get the icon header - ICONHEADER *icon_header = (ICONHEADER*)data; - - if (icon_header) { - // load the icon descriptions - ICONDIRENTRY *icon_list = (ICONDIRENTRY*)malloc(icon_header->idCount * sizeof(ICONDIRENTRY)); - if(icon_list == NULL) { - return NULL; - } - io->seek_proc(handle, sizeof(ICONHEADER), SEEK_SET); - io->read_proc(icon_list, icon_header->idCount * sizeof(ICONDIRENTRY), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapIconDirEntries(icon_list, icon_header->idCount); -#endif - - // load the requested icon - if (page < icon_header->idCount) { - // seek to the start of the bitmap data for the icon - io->seek_proc(handle, icon_list[page].dwImageOffset, SEEK_SET); - - if( IsPNG(io, handle) ) { - // Vista icon support - // see http://blogs.msdn.com/b/oldnewthing/archive/2010/10/22/10079192.aspx - dib = FreeImage_LoadFromHandle(FIF_PNG, io, handle, header_only ? FIF_LOAD_NOPIXELS : PNG_DEFAULT); - } - else { - // standard icon support - // see http://msdn.microsoft.com/en-us/library/ms997538.aspx - // see http://blogs.msdn.com/b/oldnewthing/archive/2010/10/18/10077133.aspx - dib = LoadStandardIcon(io, handle, flags, header_only); - } - - free(icon_list); - - return dib; - - } else { - free(icon_list); - FreeImage_OutputMessageProc(s_format_id, "Page doesn't exist"); - } - } else { - FreeImage_OutputMessageProc(s_format_id, "File is not an ICO file"); - } - } - - return NULL; -} - -// ---------------------------------------------------------- - -static BOOL -SaveStandardIcon(FreeImageIO *io, FIBITMAP *dib, fi_handle handle) { - BITMAPINFOHEADER *bmih = NULL; - - // write the BITMAPINFOHEADER - bmih = FreeImage_GetInfoHeader(dib); - bmih->biHeight *= 2; // height == xor + and mask -#ifdef FREEIMAGE_BIGENDIAN - SwapInfoHeader(bmih); -#endif - io->write_proc(bmih, sizeof(BITMAPINFOHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapInfoHeader(bmih); -#endif - bmih->biHeight /= 2; - - // write the palette data - if (FreeImage_GetPalette(dib) != NULL) { - RGBQUAD *pal = FreeImage_GetPalette(dib); - FILE_BGRA bgra; - for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) { - bgra.b = pal[i].rgbBlue; - bgra.g = pal[i].rgbGreen; - bgra.r = pal[i].rgbRed; - bgra.a = pal[i].rgbReserved; - io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle); - } - } - - // write the bits - int width = bmih->biWidth; - int height = bmih->biHeight; - unsigned bit_count = bmih->biBitCount; - unsigned line = CalculateLine(width, bit_count); - unsigned pitch = CalculatePitch(line); - int size_xor = height * pitch; - int size_and = height * WidthBytes(width); - - // XOR mask -#ifdef FREEIMAGE_BIGENDIAN - if (bit_count == 16) { - WORD pixel; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { - pixel = ((WORD *)line)[x]; - SwapShort(&pixel); - if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1) - return FALSE; - } - } - } else -#endif -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - if (bit_count == 24) { - FILE_BGR bgr; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); 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) - return FALSE; - } - } - } else if (bit_count == 32) { - FILE_BGRA bgra; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned x = 0; x < FreeImage_GetWidth(dib); 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) - return FALSE; - } - } - } else -#endif -#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - { -#endif - BYTE *xor_mask = FreeImage_GetBits(dib); - io->write_proc(xor_mask, size_xor, 1, handle); -#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - } -#endif - // AND mask - BYTE *and_mask = (BYTE*)malloc(size_and); - if(!and_mask) { - return FALSE; - } - - if(FreeImage_IsTransparent(dib)) { - - if(bit_count == 32) { - // create the AND mask from the alpha channel - - int width_and = WidthBytes(width); - BYTE *and_bits = and_mask; - - // clear the mask - memset(and_mask, 0, size_and); - - for(int y = 0; y < height; y++) { - RGBQUAD *bits = (RGBQUAD*)FreeImage_GetScanLine(dib, y); - - for(int x = 0; x < width; x++) { - if(bits[x].rgbReserved != 0xFF) { - // set any transparent color to full transparency - and_bits[x >> 3] |= (0x80 >> (x & 0x7)); - } - } - - and_bits += width_and; - } - } - else if(bit_count <= 8) { - // create the AND mask from the transparency table - - BYTE *trns = FreeImage_GetTransparencyTable(dib); - - int width_and = WidthBytes(width); - BYTE *and_bits = and_mask; - - // clear the mask - memset(and_mask, 0, size_and); - - switch(FreeImage_GetBPP(dib)) { - case 1: - { - for(int y = 0; y < height; y++) { - BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y); - for(int x = 0; x < width; x++) { - // get pixel at (x, y) - BYTE index = (bits[x >> 3] & (0x80 >> (x & 0x07))) != 0; - if(trns[index] != 0xFF) { - // set any transparent color to full transparency - and_bits[x >> 3] |= (0x80 >> (x & 0x7)); - } - } - and_bits += width_and; - } - } - break; - - case 4: - { - for(int y = 0; y < height; y++) { - BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y); - for(int x = 0; x < width; x++) { - // get pixel at (x, y) - BYTE shift = (BYTE)((1 - x % 2) << 2); - BYTE index = (bits[x >> 1] & (0x0F << shift)) >> shift; - if(trns[index] != 0xFF) { - // set any transparent color to full transparency - and_bits[x >> 3] |= (0x80 >> (x & 0x7)); - } - } - and_bits += width_and; - } - } - break; - - case 8: - { - for(int y = 0; y < height; y++) { - BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y); - for(int x = 0; x < width; x++) { - // get pixel at (x, y) - BYTE index = bits[x]; - if(trns[index] != 0xFF) { - // set any transparent color to full transparency - and_bits[x >> 3] |= (0x80 >> (x & 0x7)); - } - } - and_bits += width_and; - } - } - break; - - } - } - } - else { - // empty AND mask - memset(and_mask, 0, size_and); - } - - io->write_proc(and_mask, size_and, 1, handle); - free(and_mask); - - return TRUE; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - ICONHEADER *icon_header = NULL; - std::vector<FIBITMAP*> vPages; - int k; - - if(!dib || !handle || !data) { - return FALSE; - } - - // check format limits - unsigned w = FreeImage_GetWidth(dib); - unsigned h = FreeImage_GetHeight(dib); - if((w < 16) || (w > 256) || (h < 16) || (h > 256) || (w != h)) { - FreeImage_OutputMessageProc(s_format_id, "Unsupported icon size: width x height = %d x %d", w, h); - return FALSE; - } - - if (page == -1) { - page = 0; - } - - // get the icon header - icon_header = (ICONHEADER*)data; - - try { - FIBITMAP *icon_dib = NULL; - - // load all icons - for(k = 0; k < icon_header->idCount; k++) { - icon_dib = Load(io, handle, k, flags, data); - if(!icon_dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - vPages.push_back(icon_dib); - } - - // add the page - icon_dib = FreeImage_Clone(dib); - vPages.push_back(icon_dib); - icon_header->idCount++; - - // write the header - io->seek_proc(handle, 0, SEEK_SET); -#ifdef FREEIMAGE_BIGENDIAN - SwapIconHeader(icon_header); -#endif - io->write_proc(icon_header, sizeof(ICONHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapIconHeader(icon_header); -#endif - - // write all icons - // ... - - // save the icon descriptions - - ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header->idCount * sizeof(ICONDIRENTRY)); - if(!icon_list) { - throw FI_MSG_ERROR_MEMORY; - } - memset(icon_list, 0, icon_header->idCount * sizeof(ICONDIRENTRY)); - - for(k = 0; k < icon_header->idCount; k++) { - icon_dib = (FIBITMAP*)vPages[k]; - - // convert internal format to ICONDIRENTRY - // take into account Vista icons whose size is 256x256 - const BITMAPINFOHEADER *bmih = FreeImage_GetInfoHeader(icon_dib); - icon_list[k].bWidth = (bmih->biWidth > 255) ? 0 : (BYTE)bmih->biWidth; - icon_list[k].bHeight = (bmih->biHeight > 255) ? 0 : (BYTE)bmih->biHeight; - icon_list[k].bReserved = 0; - icon_list[k].wPlanes = bmih->biPlanes; - icon_list[k].wBitCount = bmih->biBitCount; - if( (icon_list[k].wPlanes * icon_list[k].wBitCount) >= 8 ) { - icon_list[k].bColorCount = 0; - } else { - icon_list[k].bColorCount = (BYTE)(1 << (icon_list[k].wPlanes * icon_list[k].wBitCount)); - } - // initial guess (correct only for standard icons) - icon_list[k].dwBytesInRes = CalculateImageSize(icon_dib); - icon_list[k].dwImageOffset = CalculateImageOffset(vPages, k); - } - - // make a room for icon dir entries, until later update - const long directory_start = io->tell_proc(handle); - io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle); - - // write the image bits for each image - - DWORD dwImageOffset = (DWORD)io->tell_proc(handle); - - for(k = 0; k < icon_header->idCount; k++) { - icon_dib = (FIBITMAP*)vPages[k]; - - if((icon_list[k].bWidth == 0) && (icon_list[k].bHeight == 0)) { - // Vista icon support - FreeImage_SaveToHandle(FIF_PNG, icon_dib, io, handle, PNG_DEFAULT); - } - else { - // standard icon support - // see http://msdn.microsoft.com/en-us/library/ms997538.aspx - SaveStandardIcon(io, icon_dib, handle); - } - - // update ICONDIRENTRY members - DWORD dwBytesInRes = (DWORD)io->tell_proc(handle) - dwImageOffset; - icon_list[k].dwImageOffset = dwImageOffset; - icon_list[k].dwBytesInRes = dwBytesInRes; - dwImageOffset += dwBytesInRes; - } - - // update the icon descriptions - const long current_pos = io->tell_proc(handle); - io->seek_proc(handle, directory_start, SEEK_SET); -#ifdef FREEIMAGE_BIGENDIAN - SwapIconDirEntries(icon_list, icon_header->idCount); -#endif - io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle); - io->seek_proc(handle, current_pos, SEEK_SET); - - free(icon_list); - - // free the vector class - for(k = 0; k < icon_header->idCount; k++) { - icon_dib = (FIBITMAP*)vPages[k]; - FreeImage_Unload(icon_dib); - } - - return TRUE; - - } catch(const char *text) { - // free the vector class - for(size_t k = 0; k < vPages.size(); k++) { - FIBITMAP *icon_dib = (FIBITMAP*)vPages[k]; - FreeImage_Unload(icon_dib); - } - FreeImage_OutputMessageProc(s_format_id, text); - return FALSE; - } -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitICO(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = PageCount; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp b/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp deleted file mode 100644 index 19e4a070a5..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp +++ /dev/null @@ -1,1706 +0,0 @@ -// ========================================================== -// JPEG Loader and writer -// Based on code developed by The Independent JPEG Group -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Jan L. Nauta (jln@magentammt.com) -// - Markus Loibl (markus.loibl@epost.de) -// - Karl-Heinz Bussian (khbussian@moss.de) -// - Hervé Drolon (drolon@infonie.fr) -// - Jascha Wetzel (jascha@mainia.de) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -extern "C" { -#define XMD_H -#undef FAR -#include <setjmp.h> - -#include "../LibJPEG/jinclude.h" -#include "../LibJPEG/jpeglib.h" -#include "../LibJPEG/jerror.h" -} - -#include "FreeImage.h" -#include "Utilities.h" - -#include "../Metadata/FreeImageTag.h" - - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ---------------------------------------------------------- -// Constant declarations -// ---------------------------------------------------------- - -#define INPUT_BUF_SIZE 4096 // choose an efficiently fread'able size -#define OUTPUT_BUF_SIZE 4096 // choose an efficiently fwrite'able size - -#define EXIF_MARKER (JPEG_APP0+1) // EXIF marker / Adobe XMP marker -#define ICC_MARKER (JPEG_APP0+2) // ICC profile marker -#define IPTC_MARKER (JPEG_APP0+13) // IPTC marker / BIM marker - -#define ICC_HEADER_SIZE 14 // size of non-profile data in APP2 -#define MAX_BYTES_IN_MARKER 65533L // maximum data length of a JPEG marker -#define MAX_DATA_BYTES_IN_MARKER 65519L // maximum data length of a JPEG APP2 marker - -#define MAX_JFXX_THUMB_SIZE (MAX_BYTES_IN_MARKER - 5 - 1) - -#define JFXX_TYPE_JPEG 0x10 // JFIF extension marker: JPEG-compressed thumbnail image -#define JFXX_TYPE_8bit 0x11 // JFIF extension marker: palette thumbnail image -#define JFXX_TYPE_24bit 0x13 // JFIF extension marker: RGB thumbnail image - -// ---------------------------------------------------------- -// Typedef declarations -// ---------------------------------------------------------- - -typedef struct tagErrorManager { - /// "public" fields - struct jpeg_error_mgr pub; - /// for return to caller - jmp_buf setjmp_buffer; -} ErrorManager; - -typedef struct tagSourceManager { - /// public fields - struct jpeg_source_mgr pub; - /// source stream - fi_handle infile; - FreeImageIO *m_io; - /// start of buffer - JOCTET * buffer; - /// have we gotten any data yet ? - boolean start_of_file; -} SourceManager; - -typedef struct tagDestinationManager { - /// public fields - struct jpeg_destination_mgr pub; - /// destination stream - fi_handle outfile; - FreeImageIO *m_io; - /// start of buffer - JOCTET * buffer; -} DestinationManager; - -typedef SourceManager* freeimage_src_ptr; -typedef DestinationManager* freeimage_dst_ptr; -typedef ErrorManager* freeimage_error_ptr; - -// ---------------------------------------------------------- -// Error handling -// ---------------------------------------------------------- - -/** Fatal errors (print message and exit) */ -static inline void -JPEG_EXIT(j_common_ptr cinfo, int code) { - freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; - error_ptr->pub.msg_code = code; - error_ptr->pub.error_exit(cinfo); -} - -/** Nonfatal errors (we can keep going, but the data is probably corrupt) */ -static inline void -JPEG_WARNING(j_common_ptr cinfo, int code) { - freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; - error_ptr->pub.msg_code = code; - error_ptr->pub.emit_message(cinfo, -1); -} - -/** - Receives control for a fatal error. Information sufficient to - generate the error message has been stored in cinfo->err; call - output_message to display it. Control must NOT return to the caller; - generally this routine will exit() or longjmp() somewhere. -*/ -METHODDEF(void) -jpeg_error_exit (j_common_ptr cinfo) { - freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; - - // always display the message - error_ptr->pub.output_message(cinfo); - - // allow JPEG with unknown markers - if(error_ptr->pub.msg_code != JERR_UNKNOWN_MARKER) { - - // let the memory manager delete any temp files before we die - jpeg_destroy(cinfo); - - // return control to the setjmp point - longjmp(error_ptr->setjmp_buffer, 1); - } -} - -/** - Actual output of any JPEG message. Note that this method does not know - how to generate a message, only where to send it. -*/ -METHODDEF(void) -jpeg_output_message (j_common_ptr cinfo) { - char buffer[JMSG_LENGTH_MAX]; - freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; - - // create the message - error_ptr->pub.format_message(cinfo, buffer); - // send it to user's message proc - FreeImage_OutputMessageProc(s_format_id, buffer); -} - -// ---------------------------------------------------------- -// Destination manager -// ---------------------------------------------------------- - -/** - Initialize destination. This is called by jpeg_start_compress() - before any data is actually written. It must initialize - next_output_byte and free_in_buffer. free_in_buffer must be - initialized to a positive value. -*/ -METHODDEF(void) -init_destination (j_compress_ptr cinfo) { - freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest; - - dest->buffer = (JOCTET *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - OUTPUT_BUF_SIZE * sizeof(JOCTET)); - - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; -} - -/** - This is called whenever the buffer has filled (free_in_buffer - reaches zero). In typical applications, it should write out the - *entire* buffer (use the saved start address and buffer length; - ignore the current state of next_output_byte and free_in_buffer). - Then reset the pointer & count to the start of the buffer, and - return TRUE indicating that the buffer has been dumped. - free_in_buffer must be set to a positive value when TRUE is - returned. A FALSE return should only be used when I/O suspension is - desired. -*/ -METHODDEF(boolean) -empty_output_buffer (j_compress_ptr cinfo) { - freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest; - - if (dest->m_io->write_proc(dest->buffer, 1, OUTPUT_BUF_SIZE, dest->outfile) != OUTPUT_BUF_SIZE) { - // let the memory manager delete any temp files before we die - jpeg_destroy((j_common_ptr)cinfo); - - JPEG_EXIT((j_common_ptr)cinfo, JERR_FILE_WRITE); - } - - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - - return TRUE; -} - -/** - Terminate destination --- called by jpeg_finish_compress() after all - data has been written. In most applications, this must flush any - data remaining in the buffer. Use either next_output_byte or - free_in_buffer to determine how much data is in the buffer. -*/ -METHODDEF(void) -term_destination (j_compress_ptr cinfo) { - freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest; - - size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; - - // write any data remaining in the buffer - - if (datacount > 0) { - if (dest->m_io->write_proc(dest->buffer, 1, (unsigned int)datacount, dest->outfile) != datacount) { - // let the memory manager delete any temp files before we die - jpeg_destroy((j_common_ptr)cinfo); - - JPEG_EXIT((j_common_ptr)cinfo, JERR_FILE_WRITE); - } - } -} - -// ---------------------------------------------------------- -// Source manager -// ---------------------------------------------------------- - -/** - Initialize source. This is called by jpeg_read_header() before any - data is actually read. Unlike init_destination(), it may leave - bytes_in_buffer set to 0 (in which case a fill_input_buffer() call - will occur immediately). -*/ -METHODDEF(void) -init_source (j_decompress_ptr cinfo) { - freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src; - - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - - src->start_of_file = TRUE; -} - -/** - This is called whenever bytes_in_buffer has reached zero and more - data is wanted. In typical applications, it should read fresh data - into the buffer (ignoring the current state of next_input_byte and - bytes_in_buffer), reset the pointer & count to the start of the - buffer, and return TRUE indicating that the buffer has been reloaded. - It is not necessary to fill the buffer entirely, only to obtain at - least one more byte. bytes_in_buffer MUST be set to a positive value - if TRUE is returned. A FALSE return should only be used when I/O - suspension is desired. -*/ -METHODDEF(boolean) -fill_input_buffer (j_decompress_ptr cinfo) { - freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src; - - size_t nbytes = src->m_io->read_proc(src->buffer, 1, INPUT_BUF_SIZE, src->infile); - - if (nbytes <= 0) { - if (src->start_of_file) { - // treat empty input file as fatal error - - // let the memory manager delete any temp files before we die - jpeg_destroy((j_common_ptr)cinfo); - - JPEG_EXIT((j_common_ptr)cinfo, JERR_INPUT_EMPTY); - } - - JPEG_WARNING((j_common_ptr)cinfo, JWRN_JPEG_EOF); - - /* Insert a fake EOI marker */ - - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - - nbytes = 2; - } - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = FALSE; - - return TRUE; -} - -/** - Skip num_bytes worth of data. The buffer pointer and count should - be advanced over num_bytes input bytes, refilling the buffer as - needed. This is used to skip over a potentially large amount of - uninteresting data (such as an APPn marker). In some applications - it may be possible to optimize away the reading of the skipped data, - but it's not clear that being smart is worth much trouble; large - skips are uncommon. bytes_in_buffer may be zero on return. - A zero or negative skip count should be treated as a no-op. -*/ -METHODDEF(void) -skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src; - - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - - (void) fill_input_buffer(cinfo); - - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } -} - -/** - Terminate source --- called by jpeg_finish_decompress - after all data has been read. Often a no-op. - - NB: *not* called by jpeg_abort or jpeg_destroy; surrounding - application must deal with any cleanup that should happen even - for error exit. -*/ -METHODDEF(void) -term_source (j_decompress_ptr cinfo) { - // no work necessary here -} - -// ---------------------------------------------------------- -// Source manager & Destination manager setup -// ---------------------------------------------------------- - -/** - Prepare for input from a stdio stream. - The caller must have already opened the stream, and is responsible - for closing it after finishing decompression. -*/ -GLOBAL(void) -jpeg_freeimage_src (j_decompress_ptr cinfo, fi_handle infile, FreeImageIO *io) { - freeimage_src_ptr src; - - // allocate memory for the buffer. is released automatically in the end - - if (cinfo->src == NULL) { - cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(SourceManager)); - - src = (freeimage_src_ptr) cinfo->src; - - src->buffer = (JOCTET *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof(JOCTET)); - } - - // initialize the jpeg pointer struct with pointers to functions - - src = (freeimage_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method - src->pub.term_source = term_source; - src->infile = infile; - src->m_io = io; - src->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read - src->pub.next_input_byte = NULL; // until buffer loaded -} - -/** - Prepare for output to a stdio stream. - The caller must have already opened the stream, and is responsible - for closing it after finishing compression. -*/ -GLOBAL(void) -jpeg_freeimage_dst (j_compress_ptr cinfo, fi_handle outfile, FreeImageIO *io) { - freeimage_dst_ptr dest; - - if (cinfo->dest == NULL) { - cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(DestinationManager)); - } - - dest = (freeimage_dst_ptr) cinfo->dest; - dest->pub.init_destination = init_destination; - dest->pub.empty_output_buffer = empty_output_buffer; - dest->pub.term_destination = term_destination; - dest->outfile = outfile; - dest->m_io = io; -} - -// ---------------------------------------------------------- -// Special markers read functions -// ---------------------------------------------------------- - -/** - Read JPEG_COM marker (comment) -*/ -static BOOL -jpeg_read_comment(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { - size_t length = datalen; - BYTE *profile = (BYTE*)dataptr; - - // read the comment - char *value = (char*)malloc((length + 1) * sizeof(char)); - if(value == NULL) return FALSE; - memcpy(value, profile, length); - value[length] = '\0'; - - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - unsigned int count = (unsigned int)length + 1; // includes the null value - - FreeImage_SetTagID(tag, JPEG_COM); - FreeImage_SetTagKey(tag, "Comment"); - FreeImage_SetTagLength(tag, count); - FreeImage_SetTagCount(tag, count); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagValue(tag, value); - - // store the tag - FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag); - - // destroy the tag - FreeImage_DeleteTag(tag); - } - - free(value); - - return TRUE; -} - -/** - Read JPEG_APP2 marker (ICC profile) -*/ - -/** -Handy subroutine to test whether a saved marker is an ICC profile marker. -*/ -static BOOL -marker_is_icc(jpeg_saved_marker_ptr marker) { - // marker identifying string "ICC_PROFILE" (null-terminated) - const BYTE icc_signature[12] = { 0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00 }; - - if(marker->marker == ICC_MARKER) { - // verify the identifying string - if(marker->data_length >= ICC_HEADER_SIZE) { - if(memcmp(icc_signature, marker->data, sizeof(icc_signature)) == 0) { - return TRUE; - } - } - } - - return FALSE; -} - -/** - See if there was an ICC profile in the JPEG file being read; - if so, reassemble and return the profile data. - - TRUE is returned if an ICC profile was found, FALSE if not. - If TRUE is returned, *icc_data_ptr is set to point to the - returned data, and *icc_data_len is set to its length. - - IMPORTANT: the data at **icc_data_ptr has been allocated with malloc() - and must be freed by the caller with free() when the caller no longer - needs it. (Alternatively, we could write this routine to use the - IJG library's memory allocator, so that the data would be freed implicitly - at jpeg_finish_decompress() time. But it seems likely that many apps - will prefer to have the data stick around after decompression finishes.) - - NOTE: if the file contains invalid ICC APP2 markers, we just silently - return FALSE. You might want to issue an error message instead. -*/ -static BOOL -jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr, unsigned *icc_data_len) { - jpeg_saved_marker_ptr marker; - int num_markers = 0; - int seq_no; - JOCTET *icc_data; - unsigned total_length; - - const int MAX_SEQ_NO = 255; // sufficient since marker numbers are bytes - BYTE marker_present[MAX_SEQ_NO+1]; // 1 if marker found - unsigned data_length[MAX_SEQ_NO+1]; // size of profile data in marker - unsigned data_offset[MAX_SEQ_NO+1]; // offset for data in marker - - *icc_data_ptr = NULL; // avoid confusion if FALSE return - *icc_data_len = 0; - - /** - this first pass over the saved markers discovers whether there are - any ICC markers and verifies the consistency of the marker numbering. - */ - - memset(marker_present, 0, (MAX_SEQ_NO + 1)); - - for(marker = cinfo->marker_list; marker != NULL; marker = marker->next) { - if (marker_is_icc(marker)) { - if (num_markers == 0) { - // number of markers - num_markers = GETJOCTET(marker->data[13]); - } - else if (num_markers != GETJOCTET(marker->data[13])) { - return FALSE; // inconsistent num_markers fields - } - // sequence number - seq_no = GETJOCTET(marker->data[12]); - if (seq_no <= 0 || seq_no > num_markers) { - return FALSE; // bogus sequence number - } - if (marker_present[seq_no]) { - return FALSE; // duplicate sequence numbers - } - marker_present[seq_no] = 1; - data_length[seq_no] = marker->data_length - ICC_HEADER_SIZE; - } - } - - if (num_markers == 0) - return FALSE; - - /** - check for missing markers, count total space needed, - compute offset of each marker's part of the data. - */ - - total_length = 0; - for(seq_no = 1; seq_no <= num_markers; seq_no++) { - if (marker_present[seq_no] == 0) { - return FALSE; // missing sequence number - } - data_offset[seq_no] = total_length; - total_length += data_length[seq_no]; - } - - if (total_length <= 0) - return FALSE; // found only empty markers ? - - // allocate space for assembled data - icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET)); - if (icc_data == NULL) - return FALSE; // out of memory - - // and fill it in - for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { - if (marker_is_icc(marker)) { - JOCTET FAR *src_ptr; - JOCTET *dst_ptr; - unsigned length; - seq_no = GETJOCTET(marker->data[12]); - dst_ptr = icc_data + data_offset[seq_no]; - src_ptr = marker->data + ICC_HEADER_SIZE; - length = data_length[seq_no]; - while (length--) { - *dst_ptr++ = *src_ptr++; - } - } - } - - *icc_data_ptr = icc_data; - *icc_data_len = total_length; - - return TRUE; -} - -/** - Read JPEG_APPD marker (IPTC or Adobe Photoshop profile) -*/ -static BOOL -jpeg_read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { - return read_iptc_profile(dib, dataptr, datalen); -} - -/** - Read JPEG_APP1 marker (XMP profile) - @param dib Input FIBITMAP - @param dataptr Pointer to the APP1 marker - @param datalen APP1 marker length - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -jpeg_read_xmp_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { - // marker identifying string for XMP (null terminated) - const char *xmp_signature = "http://ns.adobe.com/xap/1.0/"; - // XMP signature is 29 bytes long - const size_t xmp_signature_size = strlen(xmp_signature) + 1; - - size_t length = datalen; - BYTE *profile = (BYTE*)dataptr; - - if(length <= xmp_signature_size) { - // avoid reading corrupted or empty data - return FALSE; - } - - // verify the identifying string - - if(memcmp(xmp_signature, profile, strlen(xmp_signature)) == 0) { - // XMP profile - - profile += xmp_signature_size; - length -= xmp_signature_size; - - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - FreeImage_SetTagID(tag, JPEG_APP0+1); // 0xFFE1 - FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName); - FreeImage_SetTagLength(tag, (DWORD)length); - FreeImage_SetTagCount(tag, (DWORD)length); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagValue(tag, profile); - - // store the tag - FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag); - - // destroy the tag - FreeImage_DeleteTag(tag); - } - - return TRUE; - } - - return FALSE; -} - -/** - Read JFIF "JFXX" extension APP0 marker - @param dib Input FIBITMAP - @param dataptr Pointer to the APP0 marker - @param datalen APP0 marker length - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -jpeg_read_jfxx(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { - if(datalen < 6) { - return FALSE; - } - - const int id_length = 5; - const BYTE *data = dataptr + id_length; - unsigned remaining = datalen - id_length; - - const BYTE type = *data; - ++data, --remaining; - - switch(type) { - case JFXX_TYPE_JPEG: - { - // load the thumbnail - FIMEMORY* hmem = FreeImage_OpenMemory(const_cast<BYTE*>(data), remaining); - FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem); - FreeImage_CloseMemory(hmem); - // store the thumbnail - FreeImage_SetThumbnail(dib, thumbnail); - // then delete it - FreeImage_Unload(thumbnail); - break; - } - case JFXX_TYPE_8bit: - // colormapped uncompressed thumbnail (no supported) - break; - case JFXX_TYPE_24bit: - // truecolor uncompressed thumbnail (no supported) - break; - default: - break; - } - - return TRUE; -} - - -/** - Read JPEG special markers -*/ -static BOOL -read_markers(j_decompress_ptr cinfo, FIBITMAP *dib) { - jpeg_saved_marker_ptr marker; - - for(marker = cinfo->marker_list; marker != NULL; marker = marker->next) { - switch(marker->marker) { - case JPEG_APP0: - // JFIF is handled by libjpeg already, handle JFXX - if(memcmp(marker->data, "JFIF" , 5) == 0) { - continue; - } - if(memcmp(marker->data, "JFXX" , 5) == 0) { - if(!cinfo->saw_JFIF_marker || cinfo->JFIF_minor_version < 2) { - FreeImage_OutputMessageProc(s_format_id, "Warning: non-standard JFXX segment"); - } - jpeg_read_jfxx(dib, marker->data, marker->data_length); - } - // other values such as 'Picasa' : ignore safely unknown APP0 marker - break; - case JPEG_COM: - // JPEG comment - jpeg_read_comment(dib, marker->data, marker->data_length); - break; - case EXIF_MARKER: - // Exif or Adobe XMP profile - jpeg_read_exif_profile(dib, marker->data, marker->data_length); - jpeg_read_xmp_profile(dib, marker->data, marker->data_length); - jpeg_read_exif_profile_raw(dib, marker->data, marker->data_length); - break; - case IPTC_MARKER: - // IPTC/NAA or Adobe Photoshop profile - jpeg_read_iptc_profile(dib, marker->data, marker->data_length); - break; - } - } - - // ICC profile - BYTE *icc_profile = NULL; - unsigned icc_length = 0; - - if( jpeg_read_icc_profile(cinfo, &icc_profile, &icc_length) ) { - // copy ICC profile data - FreeImage_CreateICCProfile(dib, icc_profile, icc_length); - // clean up - free(icc_profile); - } - - return TRUE; -} - -// ---------------------------------------------------------- -// Special markers write functions -// ---------------------------------------------------------- - -/** - Write JPEG_COM marker (comment) -*/ -static BOOL -jpeg_write_comment(j_compress_ptr cinfo, FIBITMAP *dib) { - FITAG *tag = NULL; - - // write user comment as a JPEG_COM marker - FreeImage_GetMetadata(FIMD_COMMENTS, dib, "Comment", &tag); - if(tag) { - const char *tag_value = (char*)FreeImage_GetTagValue(tag); - - if(NULL != tag_value) { - for(long i = 0; i < (long)strlen(tag_value); i+= MAX_BYTES_IN_MARKER) { - jpeg_write_marker(cinfo, JPEG_COM, (BYTE*)tag_value + i, MIN((long)strlen(tag_value + i), MAX_BYTES_IN_MARKER)); - } - return TRUE; - } - } - return FALSE; -} - -/** - Write JPEG_APP2 marker (ICC profile) -*/ -static BOOL -jpeg_write_icc_profile(j_compress_ptr cinfo, FIBITMAP *dib) { - // marker identifying string "ICC_PROFILE" (null-terminated) - BYTE icc_signature[12] = { 0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00 }; - - FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); - - if (iccProfile->size && iccProfile->data) { - // ICC_HEADER_SIZE: ICC signature is 'ICC_PROFILE' + 2 bytes - - BYTE *profile = (BYTE*)malloc((iccProfile->size + ICC_HEADER_SIZE) * sizeof(BYTE)); - if(profile == NULL) return FALSE; - memcpy(profile, icc_signature, 12); - - for(long i = 0; i < (long)iccProfile->size; i += MAX_DATA_BYTES_IN_MARKER) { - unsigned length = MIN((long)(iccProfile->size - i), MAX_DATA_BYTES_IN_MARKER); - // sequence number - profile[12] = (BYTE) ((i / MAX_DATA_BYTES_IN_MARKER) + 1); - // number of markers - profile[13] = (BYTE) (iccProfile->size / MAX_DATA_BYTES_IN_MARKER + 1); - - memcpy(profile + ICC_HEADER_SIZE, (BYTE*)iccProfile->data + i, length); - jpeg_write_marker(cinfo, ICC_MARKER, profile, (length + ICC_HEADER_SIZE)); - } - - free(profile); - - return TRUE; - } - - return FALSE; -} - -/** - Write JPEG_APPD marker (IPTC or Adobe Photoshop profile) - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -jpeg_write_iptc_profile(j_compress_ptr cinfo, FIBITMAP *dib) { - //const char *ps_header = "Photoshop 3.0\x08BIM\x04\x04\x0\x0\x0\x0"; - const unsigned tag_length = 26; - - if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) { - BYTE *profile = NULL; - unsigned profile_size = 0; - - // create a binary profile - if(write_iptc_profile(dib, &profile, &profile_size)) { - - // write the profile - for(long i = 0; i < (long)profile_size; i += 65517L) { - unsigned length = MIN((long)profile_size - i, 65517L); - unsigned roundup = length & 0x01; // needed for Photoshop - BYTE *iptc_profile = (BYTE*)malloc(length + roundup + tag_length); - if(iptc_profile == NULL) break; - // Photoshop identification string - memcpy(&iptc_profile[0], "Photoshop 3.0\x0", 14); - // 8BIM segment type - memcpy(&iptc_profile[14], "8BIM\x04\x04\x0\x0\x0\x0", 10); - // segment size - iptc_profile[24] = (BYTE)(length >> 8); - iptc_profile[25] = (BYTE)(length & 0xFF); - // segment data - memcpy(&iptc_profile[tag_length], &profile[i], length); - if(roundup) - iptc_profile[length + tag_length] = 0; - jpeg_write_marker(cinfo, IPTC_MARKER, iptc_profile, length + roundup + tag_length); - free(iptc_profile); - } - - // release profile - free(profile); - - return TRUE; - } - } - - return FALSE; -} - -/** - Write JPEG_APP1 marker (XMP profile) - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -jpeg_write_xmp_profile(j_compress_ptr cinfo, FIBITMAP *dib) { - // marker identifying string for XMP (null terminated) - const char *xmp_signature = "http://ns.adobe.com/xap/1.0/"; - - FITAG *tag_xmp = NULL; - FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp); - - if(tag_xmp) { - const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_xmp); - - if(NULL != tag_value) { - // XMP signature is 29 bytes long - unsigned int xmp_header_size = (unsigned int)strlen(xmp_signature) + 1; - - DWORD tag_length = FreeImage_GetTagLength(tag_xmp); - - BYTE *profile = (BYTE*)malloc((tag_length + xmp_header_size) * sizeof(BYTE)); - if(profile == NULL) return FALSE; - memcpy(profile, xmp_signature, xmp_header_size); - - for(DWORD i = 0; i < tag_length; i += 65504L) { - unsigned length = MIN((long)(tag_length - i), 65504L); - - memcpy(profile + xmp_header_size, tag_value + i, length); - jpeg_write_marker(cinfo, EXIF_MARKER, profile, (length + xmp_header_size)); - } - - free(profile); - - return TRUE; - } - } - - return FALSE; -} - -/** - Write JPEG_APP1 marker (Exif profile) - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -jpeg_write_exif_profile_raw(j_compress_ptr cinfo, FIBITMAP *dib) { - // marker identifying string for Exif = "Exif\0\0" - BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; - - FITAG *tag_exif = NULL; - FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag_exif); - - if(tag_exif) { - const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_exif); - - // verify the identifying string - if(memcmp(exif_signature, tag_value, sizeof(exif_signature)) != 0) { - // not an Exif profile - return FALSE; - } - - if(NULL != tag_value) { - DWORD tag_length = FreeImage_GetTagLength(tag_exif); - - BYTE *profile = (BYTE*)malloc(tag_length * sizeof(BYTE)); - if(profile == NULL) return FALSE; - - for(DWORD i = 0; i < tag_length; i += 65504L) { - unsigned length = MIN((long)(tag_length - i), 65504L); - - memcpy(profile, tag_value + i, length); - jpeg_write_marker(cinfo, EXIF_MARKER, profile, length); - } - - free(profile); - - return TRUE; - } - } - - return FALSE; -} - -/** - Write thumbnail (JFXX segment, JPEG compressed) -*/ -static BOOL -jpeg_write_jfxx(j_compress_ptr cinfo, FIBITMAP *dib) { - // get the thumbnail to be stored - FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); - if(!thumbnail) { - return TRUE; - } - // check for a compatible output format - if((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 8) && (FreeImage_GetBPP(thumbnail) != 24)) { - FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL); - return FALSE; - } - - // stores the thumbnail as a baseline JPEG into a memory block - // return the memory block only if its size is within JFXX marker size limit! - FIMEMORY *stream = FreeImage_OpenMemory(); - - if(FreeImage_SaveToMemory(FIF_JPEG, thumbnail, stream, JPEG_BASELINE)) { - // check that the memory block size is within JFXX marker size limit - FreeImage_SeekMemory(stream, 0, SEEK_END); - const long eof = FreeImage_TellMemory(stream); - if(eof > MAX_JFXX_THUMB_SIZE) { - FreeImage_OutputMessageProc(s_format_id, "Warning: attached thumbnail is %d bytes larger than maximum supported size - Thumbnail saving aborted", eof - MAX_JFXX_THUMB_SIZE); - FreeImage_CloseMemory(stream); - return FALSE; - } - } else { - FreeImage_CloseMemory(stream); - return FALSE; - } - - BYTE* thData = NULL; - DWORD thSize = 0; - - FreeImage_AcquireMemory(stream, &thData, &thSize); - - BYTE id_length = 5; //< "JFXX" - BYTE type = JFXX_TYPE_JPEG; - - DWORD totalsize = id_length + sizeof(type) + thSize; - jpeg_write_m_header(cinfo, JPEG_APP0, totalsize); - - jpeg_write_m_byte(cinfo, 'J'); - jpeg_write_m_byte(cinfo, 'F'); - jpeg_write_m_byte(cinfo, 'X'); - jpeg_write_m_byte(cinfo, 'X'); - jpeg_write_m_byte(cinfo, '\0'); - - jpeg_write_m_byte(cinfo, type); - - // write thumbnail to destination. - // We "cram it straight into the data destination module", because write_m_byte is slow - - freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest; - - BYTE* & out = dest->pub.next_output_byte; - size_t & bufRemain = dest->pub.free_in_buffer; - - const BYTE *thData_end = thData + thSize; - - while(thData < thData_end) { - *(out)++ = *(thData)++; - if (--bufRemain == 0) { - // buffer full - flush - if (!dest->pub.empty_output_buffer(cinfo)) { - break; - } - } - } - - FreeImage_CloseMemory(stream); - - return TRUE; -} - -/** - Write JPEG special markers -*/ -static BOOL -write_markers(j_compress_ptr cinfo, FIBITMAP *dib) { - // write thumbnail as a JFXX marker - jpeg_write_jfxx(cinfo, dib); - - // write user comment as a JPEG_COM marker - jpeg_write_comment(cinfo, dib); - - // write ICC profile - jpeg_write_icc_profile(cinfo, dib); - - // write IPTC profile - jpeg_write_iptc_profile(cinfo, dib); - - // write Adobe XMP profile - jpeg_write_xmp_profile(cinfo, dib); - - // write Exif raw data - jpeg_write_exif_profile_raw(cinfo, dib); - - return TRUE; -} - -// ------------------------------------------------------------ -// Keep original size info when using scale option on loading -// ------------------------------------------------------------ -static void -store_size_info(FIBITMAP *dib, JDIMENSION width, JDIMENSION height) { - char buffer[256]; - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - size_t length = 0; - // set the original width - sprintf(buffer, "%d", (int)width); - length = strlen(buffer) + 1; // include the NULL/0 value - FreeImage_SetTagKey(tag, "OriginalJPEGWidth"); - FreeImage_SetTagLength(tag, (DWORD)length); - FreeImage_SetTagCount(tag, (DWORD)length); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagValue(tag, buffer); - FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag); - // set the original height - sprintf(buffer, "%d", (int)height); - length = strlen(buffer) + 1; // include the NULL/0 value - FreeImage_SetTagKey(tag, "OriginalJPEGHeight"); - FreeImage_SetTagLength(tag, (DWORD)length); - FreeImage_SetTagCount(tag, (DWORD)length); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagValue(tag, buffer); - FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag); - // destroy the tag - FreeImage_DeleteTag(tag); - } -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "JPEG"; -} - -static const char * DLL_CALLCONV -Description() { - return "JPEG - JFIF Compliant"; -} - -static const char * DLL_CALLCONV -Extension() { - return "jpg,jif,jpeg,jpe"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return "^\377\330\377"; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/jpeg"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE jpeg_signature[] = { 0xFF, 0xD8 }; - BYTE signature[2] = { 0, 0 }; - - io->read_proc(signature, 1, sizeof(jpeg_signature), handle); - - return (memcmp(jpeg_signature, signature, sizeof(jpeg_signature)) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 8) || - (depth == 24) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (handle) { - FIBITMAP *dib = NULL; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // set up the jpeglib structures - - struct jpeg_decompress_struct cinfo; - ErrorManager fi_error_mgr; - - try { - - // step 1: allocate and initialize JPEG decompression object - - // we set up the normal JPEG error routines, then override error_exit & output_message - cinfo.err = jpeg_std_error(&fi_error_mgr.pub); - fi_error_mgr.pub.error_exit = jpeg_error_exit; - fi_error_mgr.pub.output_message = jpeg_output_message; - - // establish the setjmp return context for jpeg_error_exit to use - if (setjmp(fi_error_mgr.setjmp_buffer)) { - // If we get here, the JPEG code has signaled an error. - // We need to clean up the JPEG object, close the input file, and return. - jpeg_destroy_decompress(&cinfo); - throw (const char*)NULL; - } - - jpeg_create_decompress(&cinfo); - - // step 2a: specify data source (eg, a handle) - - jpeg_freeimage_src(&cinfo, handle, io); - - // step 2b: save special markers for later reading - - jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF); - for(int m = 0; m < 16; m++) { - jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF); - } - - // step 3: read handle parameters with jpeg_read_header() - - jpeg_read_header(&cinfo, TRUE); - - // step 4: set parameters for decompression - - unsigned int scale_denom = 1; // fraction by which to scale image - int requested_size = flags >> 16; // requested user size in pixels - if(requested_size > 0) { - // the JPEG codec can perform x2, x4 or x8 scaling on loading - // try to find the more appropriate scaling according to user's need - double scale = MAX((double)cinfo.image_width, (double)cinfo.image_height) / (double)requested_size; - if(scale >= 8) { - scale_denom = 8; - } else if(scale >= 4) { - scale_denom = 4; - } else if(scale >= 2) { - scale_denom = 2; - } - } - cinfo.scale_num = 1; - cinfo.scale_denom = scale_denom; - - if ((flags & JPEG_ACCURATE) != JPEG_ACCURATE) { - cinfo.dct_method = JDCT_IFAST; - cinfo.do_fancy_upsampling = FALSE; - } - - if ((flags & JPEG_GREYSCALE) == JPEG_GREYSCALE) { - // force loading as a 8-bit greyscale image - cinfo.out_color_space = JCS_GRAYSCALE; - } - - // step 5a: start decompressor and calculate output width and height - - jpeg_start_decompress(&cinfo); - - // step 5b: allocate dib and init header - - if((cinfo.output_components == 4) && (cinfo.out_color_space == JCS_CMYK)) { - // CMYK image - if((flags & JPEG_CMYK) == JPEG_CMYK) { - // load as CMYK - dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(!dib) throw FI_MSG_ERROR_DIB_MEMORY; - FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK; - } else { - // load as CMYK and convert to RGB - dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(!dib) throw FI_MSG_ERROR_DIB_MEMORY; - } - } else { - // RGB or greyscale image - dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 8 * cinfo.output_components, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(!dib) throw FI_MSG_ERROR_DIB_MEMORY; - - if (cinfo.output_components == 1) { - // build a greyscale palette - RGBQUAD *colors = FreeImage_GetPalette(dib); - - for (int i = 0; i < 256; i++) { - colors[i].rgbRed = (BYTE)i; - colors[i].rgbGreen = (BYTE)i; - colors[i].rgbBlue = (BYTE)i; - } - } - } - if(scale_denom != 1) { - // store original size info if a scaling was requested - store_size_info(dib, cinfo.image_width, cinfo.image_height); - } - - // step 5c: handle metrices - - if (cinfo.density_unit == 1) { - // dots/inch - FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)cinfo.X_density) / 0.0254000 + 0.5)); - FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)cinfo.Y_density) / 0.0254000 + 0.5)); - } else if (cinfo.density_unit == 2) { - // dots/cm - FreeImage_SetDotsPerMeterX(dib, (unsigned) (cinfo.X_density * 100)); - FreeImage_SetDotsPerMeterY(dib, (unsigned) (cinfo.Y_density * 100)); - } - - // step 6: read special markers - - read_markers(&cinfo, dib); - - // --- header only mode => clean-up and return - - if (header_only) { - // release JPEG decompression object - jpeg_destroy_decompress(&cinfo); - // return header data - return dib; - } - - // step 7a: while (scan lines remain to be read) jpeg_read_scanlines(...); - - if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) != JPEG_CMYK)) { - // convert from CMYK to RGB - - JSAMPARRAY buffer; // output row buffer - unsigned row_stride; // physical row width in output buffer - - // JSAMPLEs per row in output buffer - row_stride = cinfo.output_width * cinfo.output_components; - // make a one-row-high sample array that will go away when done with image - buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - - while (cinfo.output_scanline < cinfo.output_height) { - JSAMPROW src = buffer[0]; - JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1); - - jpeg_read_scanlines(&cinfo, buffer, 1); - - for(unsigned x = 0; x < cinfo.output_width; x++) { - WORD K = (WORD)src[3]; - dst[FI_RGBA_RED] = (BYTE)((K * src[0]) / 255); // C -> R - dst[FI_RGBA_GREEN] = (BYTE)((K * src[1]) / 255); // M -> G - dst[FI_RGBA_BLUE] = (BYTE)((K * src[2]) / 255); // Y -> B - src += 4; - dst += 3; - } - } - } else if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) == JPEG_CMYK)) { - // convert from LibJPEG CMYK to standard CMYK - - JSAMPARRAY buffer; // output row buffer - unsigned row_stride; // physical row width in output buffer - - // JSAMPLEs per row in output buffer - row_stride = cinfo.output_width * cinfo.output_components; - // make a one-row-high sample array that will go away when done with image - buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - - while (cinfo.output_scanline < cinfo.output_height) { - JSAMPROW src = buffer[0]; - JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1); - - jpeg_read_scanlines(&cinfo, buffer, 1); - - for(unsigned x = 0; x < cinfo.output_width; x++) { - // CMYK pixels are inverted - dst[0] = ~src[0]; // C - dst[1] = ~src[1]; // M - dst[2] = ~src[2]; // Y - dst[3] = ~src[3]; // K - src += 4; - dst += 4; - } - } - - } else { - // normal case (RGB or greyscale image) - - while (cinfo.output_scanline < cinfo.output_height) { - JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1); - - jpeg_read_scanlines(&cinfo, &dst, 1); - } - - // step 7b: swap red and blue components (see LibJPEG/jmorecfg.h: #define RGB_RED, ...) - // The default behavior of the JPEG library is kept "as is" because LibTIFF uses - // LibJPEG "as is". - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - SwapRedBlue32(dib); -#endif - } - - // step 8: finish decompression - - jpeg_finish_decompress(&cinfo); - - // step 9: release JPEG decompression object - - jpeg_destroy_decompress(&cinfo); - - // check for automatic Exif rotation - if(!header_only && ((flags & JPEG_EXIFROTATE) == JPEG_EXIFROTATE)) { - RotateExif(&dib); - } - - // everything went well. return the loaded dib - - return dib; - - } catch (const char *text) { - jpeg_destroy_decompress(&cinfo); - if(NULL != dib) { - FreeImage_Unload(dib); - } - if(NULL != text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - } - } - - return NULL; -} - -// ---------------------------------------------------------- - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - if ((dib) && (handle)) { - try { - // Check dib format - - const char *sError = "only 24-bit highcolor or 8-bit greyscale/palette 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)) { - throw sError; - } - - if(bpp == 8) { - // allow grey, reverse grey and palette - if ((color_type != FIC_MINISBLACK) && (color_type != FIC_MINISWHITE) && (color_type != FIC_PALETTE)) { - throw sError; - } - } - - - struct jpeg_compress_struct cinfo; - ErrorManager fi_error_mgr; - - // Step 1: allocate and initialize JPEG compression object - - // we set up the normal JPEG error routines, then override error_exit & output_message - cinfo.err = jpeg_std_error(&fi_error_mgr.pub); - fi_error_mgr.pub.error_exit = jpeg_error_exit; - fi_error_mgr.pub.output_message = jpeg_output_message; - - // establish the setjmp return context for jpeg_error_exit to use - if (setjmp(fi_error_mgr.setjmp_buffer)) { - // If we get here, the JPEG code has signaled an error. - // We need to clean up the JPEG object, close the input file, and return. - jpeg_destroy_compress(&cinfo); - throw (const char*)NULL; - } - - // Now we can initialize the JPEG compression object - - jpeg_create_compress(&cinfo); - - // Step 2: specify data destination (eg, a file) - - jpeg_freeimage_dst(&cinfo, handle, io); - - // Step 3: set parameters for compression - - cinfo.image_width = FreeImage_GetWidth(dib); - cinfo.image_height = FreeImage_GetHeight(dib); - - switch(color_type) { - case FIC_MINISBLACK : - case FIC_MINISWHITE : - cinfo.in_color_space = JCS_GRAYSCALE; - cinfo.input_components = 1; - break; - - default : - cinfo.in_color_space = JCS_RGB; - cinfo.input_components = 3; - break; - } - - jpeg_set_defaults(&cinfo); - - // progressive-JPEG support - if((flags & JPEG_PROGRESSIVE) == JPEG_PROGRESSIVE) { - jpeg_simple_progression(&cinfo); - } - - // compute optimal Huffman coding tables for the image - if((flags & JPEG_OPTIMIZE) == JPEG_OPTIMIZE) { - cinfo.optimize_coding = TRUE; - } - - // Set JFIF density parameters from the DIB data - - cinfo.X_density = (UINT16) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib)); - cinfo.Y_density = (UINT16) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib)); - cinfo.density_unit = 1; // dots / inch - - // 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.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 - } - - // set subsampling options if required - - if(cinfo.in_color_space == JCS_RGB) { - if((flags & JPEG_SUBSAMPLING_411) == JPEG_SUBSAMPLING_411) { - // 4:1:1 (4x1 1x1 1x1) - CrH 25% - CbH 25% - CrV 100% - CbV 100% - // the horizontal color resolution is quartered - cinfo.comp_info[0].h_samp_factor = 4; // Y - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; // Cb - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; // Cr - cinfo.comp_info[2].v_samp_factor = 1; - } else if((flags & JPEG_SUBSAMPLING_420) == JPEG_SUBSAMPLING_420) { - // 4:2:0 (2x2 1x1 1x1) - CrH 50% - CbH 50% - CrV 50% - CbV 50% - // the chrominance resolution in both the horizontal and vertical directions is cut in half - cinfo.comp_info[0].h_samp_factor = 2; // Y - cinfo.comp_info[0].v_samp_factor = 2; - cinfo.comp_info[1].h_samp_factor = 1; // Cb - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; // Cr - cinfo.comp_info[2].v_samp_factor = 1; - } else if((flags & JPEG_SUBSAMPLING_422) == JPEG_SUBSAMPLING_422){ //2x1 (low) - // 4:2:2 (2x1 1x1 1x1) - CrH 50% - CbH 50% - CrV 100% - CbV 100% - // half of the horizontal resolution in the chrominance is dropped (Cb & Cr), - // while the full resolution is retained in the vertical direction, with respect to the luminance - cinfo.comp_info[0].h_samp_factor = 2; // Y - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; // Cb - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; // Cr - cinfo.comp_info[2].v_samp_factor = 1; - } - else if((flags & JPEG_SUBSAMPLING_444) == JPEG_SUBSAMPLING_444){ //1x1 (no subsampling) - // 4:4:4 (1x1 1x1 1x1) - CrH 100% - CbH 100% - CrV 100% - CbV 100% - // the resolution of chrominance information (Cb & Cr) is preserved - // at the same rate as the luminance (Y) information - cinfo.comp_info[0].h_samp_factor = 1; // Y - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; // Cb - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; // Cr - cinfo.comp_info[2].v_samp_factor = 1; - } - } - - // Step 4: set quality - // the first 7 bits are reserved for low level quality settings - // the other bits are high level (i.e. enum-ish) - - int quality; - - if ((flags & JPEG_QUALITYBAD) == JPEG_QUALITYBAD) { - quality = 10; - } else if ((flags & JPEG_QUALITYAVERAGE) == JPEG_QUALITYAVERAGE) { - quality = 25; - } else if ((flags & JPEG_QUALITYNORMAL) == JPEG_QUALITYNORMAL) { - quality = 50; - } else if ((flags & JPEG_QUALITYGOOD) == JPEG_QUALITYGOOD) { - quality = 75; - } else if ((flags & JPEG_QUALITYSUPERB) == JPEG_QUALITYSUPERB) { - quality = 100; - } else { - if ((flags & 0x7F) == 0) { - quality = 75; - } else { - quality = flags & 0x7F; - } - } - - jpeg_set_quality(&cinfo, quality, TRUE); /* limit to baseline-JPEG values */ - - // Step 5: Start compressor - - jpeg_start_compress(&cinfo, TRUE); - - // Step 6: Write special markers - - if ((flags & JPEG_BASELINE) != JPEG_BASELINE) { - write_markers(&cinfo, dib); - } - - // Step 7: while (scan lines remain to be written) - - if(color_type == FIC_RGB) { - // 24-bit RGB image : need to swap red and blue channels - 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); -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - // swap R and B channels - BYTE *target_p = target; - for(unsigned x = 0; x < cinfo.image_width; x++) { - INPLACESWAP(target_p[0], target_p[2]); - target_p += 3; - } -#endif - // 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) { - JSAMPROW b = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1); - - jpeg_write_scanlines(&cinfo, &b, 1); - } - } - else if(color_type == FIC_PALETTE) { - // 8-bit palettized images are converted to 24-bit images - RGBQUAD *palette = FreeImage_GetPalette(dib); - BYTE *target = (BYTE*)malloc(cinfo.image_width * 3); - if (target == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - while (cinfo.next_scanline < cinfo.image_height) { - BYTE *source = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1); - FreeImage_ConvertLine8To24(target, source, cinfo.image_width, palette); - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - // swap R and B channels - BYTE *target_p = target; - for(unsigned x = 0; x < cinfo.image_width; x++) { - INPLACESWAP(target_p[0], target_p[2]); - target_p += 3; - } -#endif - - - jpeg_write_scanlines(&cinfo, &target, 1); - } - - free(target); - } - else if(color_type == FIC_MINISWHITE) { - // reverse 8-bit greyscale image, so reverse grey value on the fly - unsigned i; - BYTE reverse[256]; - BYTE *target = (BYTE *)malloc(cinfo.image_width); - if (target == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for(i = 0; i < 256; i++) { - reverse[i] = (BYTE)(255 - i); - } - - while(cinfo.next_scanline < cinfo.image_height) { - BYTE *source = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1); - for(i = 0; i < cinfo.image_width; i++) { - target[i] = reverse[ source[i] ]; - } - jpeg_write_scanlines(&cinfo, &target, 1); - } - - free(target); - } - - // Step 8: Finish compression - - jpeg_finish_compress(&cinfo); - - // Step 9: release JPEG compression object - - jpeg_destroy_compress(&cinfo); - - return TRUE; - - } catch (const char *text) { - if(text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - return FALSE; - } - } - - return FALSE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitJPEG(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp b/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp deleted file mode 100644 index fe80a2b533..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp +++ /dev/null @@ -1,1115 +0,0 @@ -// ========================================================== -// PNG Loader and Writer -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Herve Drolon (drolon@infonie.fr) -// - Detlev Vendt (detlev.vendt@brillit.de) -// - Aaron Shumate (trek@startreker.com) -// - Tanner Helland (tannerhelland@users.sf.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#include "FreeImage.h" -#include "Utilities.h" - -#include "../Metadata/FreeImageTag.h" - -// ---------------------------------------------------------- - -#define PNG_BYTES_TO_CHECK 8 - -#undef PNG_Z_DEFAULT_COMPRESSION // already used in ../LibPNG/pnglibconf.h - -// ---------------------------------------------------------- - -#include "zlib.h" -#include "../LibPNG/png.h" - -// ---------------------------------------------------------- - -typedef struct { - FreeImageIO *s_io; - fi_handle s_handle; -} fi_ioStructure, *pfi_ioStructure; - -// ========================================================== -// libpng interface -// ========================================================== - -static void -_ReadProc(png_structp png_ptr, unsigned char *data, png_size_t size) { - pfi_ioStructure pfio = (pfi_ioStructure)png_get_io_ptr(png_ptr); - unsigned n = pfio->s_io->read_proc(data, (unsigned int)size, 1, pfio->s_handle); - if(size && (n == 0)) { - throw "Read error: invalid or corrupted PNG file"; - } -} - -static void -_WriteProc(png_structp png_ptr, unsigned char *data, png_size_t size) { - pfi_ioStructure pfio = (pfi_ioStructure)png_get_io_ptr(png_ptr); - pfio->s_io->write_proc(data, (unsigned int)size, 1, pfio->s_handle); -} - -static void -_FlushProc(png_structp png_ptr) { - (png_structp)png_ptr; - // empty flush implementation -} - -static void -error_handler(png_structp png_ptr, const char *error) { - (png_structp)png_ptr; - throw error; -} - -// in FreeImage warnings disabled - -static void -warning_handler(png_structp png_ptr, const char *warning) { - (png_structp)png_ptr; - (char*)warning; -} - -// ========================================================== -// Metadata routines -// ========================================================== - -static BOOL -ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) { - // XMP keyword - const char *g_png_xmp_keyword = "XML:com.adobe.xmp"; - - FITAG *tag = NULL; - png_textp text_ptr = NULL; - png_timep mod_time = NULL; - int num_text = 0; - - // iTXt/tEXt/zTXt chuncks - if(png_get_text(png_ptr, info_ptr, &text_ptr, &num_text) > 0) { - for(int i = 0; i < num_text; i++) { - // create a tag - tag = FreeImage_CreateTag(); - if(!tag) return FALSE; - - DWORD tag_length = (DWORD) MAX(text_ptr[i].text_length, text_ptr[i].itxt_length); - - FreeImage_SetTagLength(tag, tag_length); - FreeImage_SetTagCount(tag, tag_length); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagValue(tag, text_ptr[i].text); - - if(strcmp(text_ptr[i].key, g_png_xmp_keyword) == 0) { - // store the tag as XMP - FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName); - FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag); - } else { - // store the tag as a comment - FreeImage_SetTagKey(tag, text_ptr[i].key); - FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag); - } - - // destroy the tag - FreeImage_DeleteTag(tag); - } - } - - // timestamp chunk - if(png_get_tIME(png_ptr, info_ptr, &mod_time)) { - char timestamp[32]; - // create a tag - tag = FreeImage_CreateTag(); - if(!tag) return FALSE; - - // convert as 'yyyy:MM:dd hh:mm:ss' - sprintf(timestamp, "%4d:%02d:%02d %2d:%02d:%02d", mod_time->year, mod_time->month, mod_time->day, mod_time->hour, mod_time->minute, mod_time->second); - - DWORD tag_length = (DWORD)strlen(timestamp) + 1; - FreeImage_SetTagLength(tag, tag_length); - FreeImage_SetTagCount(tag, tag_length); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagID(tag, TAG_DATETIME); - FreeImage_SetTagValue(tag, timestamp); - - // store the tag as Exif-TIFF - FreeImage_SetTagKey(tag, "DateTime"); - FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, FreeImage_GetTagKey(tag), tag); - - // destroy the tag - FreeImage_DeleteTag(tag); - } - - return TRUE; -} - -static BOOL -WriteMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) { - // XMP keyword - const char *g_png_xmp_keyword = "XML:com.adobe.xmp"; - - FITAG *tag = NULL; - FIMETADATA *mdhandle = NULL; - BOOL bResult = TRUE; - - png_text text_metadata; - png_time mod_time; - - // set the 'Comments' metadata as iTXt chuncks - - mdhandle = FreeImage_FindFirstMetadata(FIMD_COMMENTS, dib, &tag); - - if(mdhandle) { - do { - memset(&text_metadata, 0, sizeof(png_text)); - text_metadata.compression = 1; // iTXt, none - text_metadata.key = (char*)FreeImage_GetTagKey(tag); // keyword, 1-79 character description of "text" - text_metadata.text = (char*)FreeImage_GetTagValue(tag); // comment, may be an empty string (ie "") - text_metadata.text_length = FreeImage_GetTagLength(tag);// length of the text string - text_metadata.itxt_length = FreeImage_GetTagLength(tag);// length of the itxt string - text_metadata.lang = 0; // language code, 0-79 characters or a NULL pointer - text_metadata.lang_key = 0; // keyword translated UTF-8 string, 0 or more chars or a NULL pointer - - // set the tag - png_set_text(png_ptr, info_ptr, &text_metadata, 1); - - } while(FreeImage_FindNextMetadata(mdhandle, &tag)); - - FreeImage_FindCloseMetadata(mdhandle); - bResult &= TRUE; - } - - // set the 'XMP' metadata as iTXt chuncks - tag = NULL; - FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag); - if(tag && FreeImage_GetTagLength(tag)) { - memset(&text_metadata, 0, sizeof(png_text)); - text_metadata.compression = 1; // iTXt, none - text_metadata.key = (char*)g_png_xmp_keyword; // keyword, 1-79 character description of "text" - text_metadata.text = (char*)FreeImage_GetTagValue(tag); // comment, may be an empty string (ie "") - text_metadata.text_length = FreeImage_GetTagLength(tag);// length of the text string - text_metadata.itxt_length = FreeImage_GetTagLength(tag);// length of the itxt string - text_metadata.lang = 0; // language code, 0-79 characters or a NULL pointer - text_metadata.lang_key = 0; // keyword translated UTF-8 string, 0 or more chars or a NULL pointer - - // set the tag - png_set_text(png_ptr, info_ptr, &text_metadata, 1); - bResult &= TRUE; - } - - // set the Exif-TIFF 'DateTime' metadata as a tIME chunk - tag = NULL; - FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "DateTime", &tag); - if(tag && FreeImage_GetTagLength(tag)) { - int year, month, day, hour, minute, second; - const char *value = (char*)FreeImage_GetTagValue(tag); - if(sscanf(value, "%4d:%02d:%02d %2d:%02d:%02d", &year, &month, &day, &hour, &minute, &second) == 6) { - mod_time.year = (png_uint_16)year; - mod_time.month = (png_byte)month; - mod_time.day = (png_byte)day; - mod_time.hour = (png_byte)hour; - mod_time.minute = (png_byte)minute; - mod_time.second = (png_byte)second; - png_set_tIME (png_ptr, info_ptr, &mod_time); - } - } - - return bResult; -} - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "PNG"; -} - -static const char * DLL_CALLCONV -Description() { - return "Portable Network Graphics"; -} - -static const char * DLL_CALLCONV -Extension() { - return "png"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return "^.PNG\r"; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/png"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; - BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - io->read_proc(&signature, 1, 8, handle); - - return (memcmp(png_signature, signature, 8) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 1) || - (depth == 4) || - (depth == 8) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return ( - (type == FIT_BITMAP) || - (type == FIT_UINT16) || - (type == FIT_RGB16) || - (type == FIT_RGBA16) - ); -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// -------------------------------------------------------------------------- - -/** -Configure the decoder so that decoded pixels are compatible with a FREE_IMAGE_TYPE format. -Set conversion instructions as needed. -@param png_ptr PNG handle -@param info_ptr PNG info handle -@param flags Decoder flags -@param output_image_type Returned FreeImage converted image type -@return Returns TRUE if successful, returns FALSE otherwise -@see png_read_update_info -*/ -static BOOL -ConfigureDecoder(png_structp png_ptr, png_infop info_ptr, int flags, FREE_IMAGE_TYPE *output_image_type) { - // get original image info - const int color_type = png_get_color_type(png_ptr, info_ptr); - const int bit_depth = png_get_bit_depth(png_ptr, info_ptr); - const int pixel_depth = bit_depth * png_get_channels(png_ptr, info_ptr); - - FREE_IMAGE_TYPE image_type = FIT_BITMAP; // assume standard image type - - // check for transparency table or single transparent color - BOOL bIsTransparent = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) == PNG_INFO_tRNS ? TRUE : FALSE; - - // check allowed combinations of colour type and bit depth - // then get converted FreeImage type - - switch(color_type) { - case PNG_COLOR_TYPE_GRAY: // color type '0', bitdepth = 1, 2, 4, 8, 16 - switch(bit_depth) { - case 1: - case 2: - case 4: - case 8: - // expand grayscale images to the full 8-bit from 2-bit/pixel - if (pixel_depth == 2) { - png_set_expand_gray_1_2_4_to_8(png_ptr); - } - - // if a tRNS chunk is provided, we must also expand the grayscale data to 8-bits, - // this allows us to make use of the transparency table with existing FreeImage methods - if (bIsTransparent && (pixel_depth < 8)) { - png_set_expand_gray_1_2_4_to_8(png_ptr); - } - break; - - case 16: - image_type = (pixel_depth == 16) ? FIT_UINT16 : FIT_UNKNOWN; - - // 16-bit grayscale images can contain a transparent value (shade) - // if found, expand the transparent value to a full alpha channel - if (bIsTransparent && (image_type != FIT_UNKNOWN)) { - // expand tRNS to a full alpha channel - png_set_tRNS_to_alpha(png_ptr); - - // expand new 16-bit gray + 16-bit alpha to full 64-bit RGBA - png_set_gray_to_rgb(png_ptr); - - image_type = FIT_RGBA16; - } - break; - - default: - image_type = FIT_UNKNOWN; - break; - } - break; - - case PNG_COLOR_TYPE_RGB: // color type '2', bitdepth = 8, 16 - switch(bit_depth) { - case 8: - image_type = (pixel_depth == 24) ? FIT_BITMAP : FIT_UNKNOWN; - break; - case 16: - image_type = (pixel_depth == 48) ? FIT_RGB16 : FIT_UNKNOWN; - break; - default: - image_type = FIT_UNKNOWN; - break; - } - // sometimes, 24- or 48-bit images may contain transparency information - // check for this use case and convert to an alpha-compatible format - if (bIsTransparent && (image_type != FIT_UNKNOWN)) { - // if the image is 24-bit RGB, mark it as 32-bit; if it is 48-bit, mark it as 64-bit - image_type = (pixel_depth == 24) ? FIT_BITMAP : (pixel_depth == 48) ? FIT_RGBA16 : FIT_UNKNOWN; - // expand tRNS chunk to alpha channel - png_set_tRNS_to_alpha(png_ptr); - } - break; - - case PNG_COLOR_TYPE_PALETTE: // color type '3', bitdepth = 1, 2, 4, 8 - switch(bit_depth) { - case 1: - case 2: - case 4: - case 8: - // expand palette images to the full 8 bits from 2 bits/pixel - if (pixel_depth == 2) { - png_set_packing(png_ptr); - } - - // if a tRNS chunk is provided, we must also expand the palletized data to 8-bits, - // this allows us to make use of the transparency table with existing FreeImage methods - if (bIsTransparent && (pixel_depth < 8)) { - png_set_packing(png_ptr); - } - break; - - default: - image_type = FIT_UNKNOWN; - break; - } - break; - - case PNG_COLOR_TYPE_GRAY_ALPHA: // color type '4', bitdepth = 8, 16 - switch(bit_depth) { - case 8: - // 8-bit grayscale + 8-bit alpha => convert to 32-bit RGBA - image_type = (pixel_depth == 16) ? FIT_BITMAP : FIT_UNKNOWN; - break; - case 16: - // 16-bit grayscale + 16-bit alpha => convert to 64-bit RGBA - image_type = (pixel_depth == 32) ? FIT_RGBA16 : FIT_UNKNOWN; - break; - default: - image_type = FIT_UNKNOWN; - break; - } - // expand 8-bit greyscale + 8-bit alpha to 32-bit - // expand 16-bit greyscale + 16-bit alpha to 64-bit - png_set_gray_to_rgb(png_ptr); - break; - - case PNG_COLOR_TYPE_RGB_ALPHA: // color type '6', bitdepth = 8, 16 - switch(bit_depth) { - case 8: - break; - case 16: - image_type = (pixel_depth == 64) ? FIT_RGBA16 : FIT_UNKNOWN; - break; - default: - image_type = FIT_UNKNOWN; - break; - } - break; - } - - // check for unknown or invalid formats - if(image_type == FIT_UNKNOWN) { - *output_image_type = image_type; - return FALSE; - } - -#ifndef FREEIMAGE_BIGENDIAN - if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) { - // turn on 16-bit byte swapping - png_set_swap(png_ptr); - } -#endif - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - if((image_type == FIT_BITMAP) && ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA))) { - // flip the RGB pixels to BGR (or RGBA to BGRA) - png_set_bgr(png_ptr); - } -#endif - - // gamma correction - // unlike the example in the libpng documentation, we have *no* idea where - // this file may have come from--so if it doesn't have a file gamma, don't - // do any correction ("do no harm") - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { - double gamma = 0; - double screen_gamma = 2.2; - - if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA) { - png_set_gamma(png_ptr, screen_gamma, gamma); - } - } - - // all transformations have been registered; now update info_ptr data - png_read_update_info(png_ptr, info_ptr); - - // return the output image type - *output_image_type = image_type; - - return TRUE; -} - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - png_uint_32 width, height; - int color_type; - int bit_depth; - int pixel_depth = 0; // pixel_depth = bit_depth * channels - - FIBITMAP *dib = NULL; - png_bytepp row_pointers = NULL; - - fi_ioStructure fio; - fio.s_handle = handle; - fio.s_io = io; - - if (handle) { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - // check to see if the file is in fact a PNG file - - BYTE png_check[PNG_BYTES_TO_CHECK]; - - io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle); - - if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) { - return NULL; // Bad signature - } - - // create the chunk manage structure - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler); - - if (!png_ptr) { - return NULL; - } - - // create the info structure - - info_ptr = png_create_info_struct(png_ptr); - - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - return NULL; - } - - // init the IO - - png_set_read_fn(png_ptr, &fio, _ReadProc); - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return NULL; - } - - // because we have already read the signature... - - png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); - - // read the IHDR chunk - - png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); - - // configure the decoder - - FREE_IMAGE_TYPE image_type = FIT_BITMAP; - - if(!ConfigureDecoder(png_ptr, info_ptr, flags, &image_type)) { - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - // update image info - - color_type = png_get_color_type(png_ptr, info_ptr); - bit_depth = png_get_bit_depth(png_ptr, info_ptr); - pixel_depth = bit_depth * png_get_channels(png_ptr, info_ptr); - - // create a dib and write the bitmap header - // set up the dib palette, if needed - - switch (color_type) { - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - break; - - case PNG_COLOR_TYPE_PALETTE: - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(dib) { - png_colorp png_palette = NULL; - int palette_entries = 0; - - png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries); - - palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib)); - - // store the palette - - RGBQUAD *palette = FreeImage_GetPalette(dib); - for(int i = 0; i < palette_entries; i++) { - palette[i].rgbRed = png_palette[i].red; - palette[i].rgbGreen = png_palette[i].green; - palette[i].rgbBlue = png_palette[i].blue; - } - } - break; - - case PNG_COLOR_TYPE_GRAY: - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - - if(dib && (pixel_depth <= 8)) { - RGBQUAD *palette = FreeImage_GetPalette(dib); - const int palette_entries = 1 << pixel_depth; - - for(int i = 0; i < palette_entries; i++) { - palette[i].rgbRed = - palette[i].rgbGreen = - palette[i].rgbBlue = (BYTE)((i * 255) / (palette_entries - 1)); - } - } - break; - - default: - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // store the transparency table - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - // array of alpha (transparency) entries for palette - png_bytep trans_alpha = NULL; - // number of transparent entries - int num_trans = 0; - // graylevel or color sample values of the single transparent color for non-paletted images - png_color_16p trans_color = NULL; - - png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color); - - if((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) { - // single transparent color - if (trans_color->gray < 256) { - BYTE table[256]; - memset(table, 0xFF, 256); - table[trans_color->gray] = 0; - FreeImage_SetTransparencyTable(dib, table, 256); - } - // check for a full transparency table, too - else if ((trans_alpha) && (pixel_depth <= 8)) { - FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); - } - - } else if((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) { - // transparency table - FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); - } - } - - // store the background color (only supported for FIT_BITMAP types) - - if ((image_type == FIT_BITMAP) && png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) { - // Get the background color to draw transparent and alpha images over. - // Note that even if the PNG file supplies a background, you are not required to - // use it - you should use the (solid) application background if it has one. - - png_color_16p image_background = NULL; - RGBQUAD rgbBkColor; - - if (png_get_bKGD(png_ptr, info_ptr, &image_background)) { - rgbBkColor.rgbRed = (BYTE)image_background->red; - rgbBkColor.rgbGreen = (BYTE)image_background->green; - rgbBkColor.rgbBlue = (BYTE)image_background->blue; - rgbBkColor.rgbReserved = 0; - - FreeImage_SetBackgroundColor(dib, &rgbBkColor); - } - } - - // get physical resolution - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { - png_uint_32 res_x, res_y; - - // we'll overload this var and use 0 to mean no phys data, - // since if it's not in meters we can't use it anyway - - int res_unit_type = PNG_RESOLUTION_UNKNOWN; - - png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type); - - if (res_unit_type == PNG_RESOLUTION_METER) { - FreeImage_SetDotsPerMeterX(dib, res_x); - FreeImage_SetDotsPerMeterY(dib, res_y); - } - } - - // get possible ICC profile - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { - png_charp profile_name = NULL; - png_bytep profile_data = NULL; - png_uint_32 profile_length = 0; - int compression_type; - - png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length); - - // copy ICC profile data (must be done after FreeImage_AllocateHeader) - - FreeImage_CreateICCProfile(dib, profile_data, profile_length); - } - - // --- header only mode => clean-up and return - - if (header_only) { - // get possible metadata (it can be located both before and after the image data) - ReadMetadata(png_ptr, info_ptr, dib); - if (png_ptr) { - // clean up after the read, and free any memory allocated - REQUIRED - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - } - return dib; - } - - // set the individual row_pointers to point at the correct offsets - - row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); - - if (!row_pointers) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - FreeImage_Unload(dib); - return NULL; - } - - // read in the bitmap bits via the pointer table - // allow loading of PNG with minor errors (such as images with several IDAT chunks) - - for (png_uint_32 k = 0; k < height; k++) { - row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k); - } - - png_set_benign_errors(png_ptr, 1); - png_read_image(png_ptr, row_pointers); - - // check if the bitmap contains transparency, if so enable it in the header - - if (FreeImage_GetBPP(dib) == 32) { - if (FreeImage_GetColorType(dib) == FIC_RGBALPHA) { - FreeImage_SetTransparent(dib, TRUE); - } else { - FreeImage_SetTransparent(dib, FALSE); - } - } - - // cleanup - - if (row_pointers) { - free(row_pointers); - row_pointers = NULL; - } - - // read the rest of the file, getting any additional chunks in info_ptr - - png_read_end(png_ptr, info_ptr); - - // get possible metadata (it can be located both before and after the image data) - - ReadMetadata(png_ptr, info_ptr, dib); - - if (png_ptr) { - // clean up after the read, and free any memory allocated - REQUIRED - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - } - - return dib; - - } catch (const char *text) { - if (png_ptr) { - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); - } - if (row_pointers) { - free(row_pointers); - } - if (dib) { - FreeImage_Unload(dib); - } - FreeImage_OutputMessageProc(s_format_id, text); - - return NULL; - } - } - - return NULL; -} - -// -------------------------------------------------------------------------- - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - png_structp png_ptr; - png_infop info_ptr; - png_colorp palette = NULL; - png_uint_32 width, height; - BOOL has_alpha_channel = FALSE; - - RGBQUAD *pal; // pointer to dib palette - int bit_depth, pixel_depth; // pixel_depth = bit_depth * channels - int palette_entries; - int interlace_type; - - fi_ioStructure fio; - fio.s_handle = handle; - fio.s_io = io; - - if ((dib) && (handle)) { - try { - // create the chunk manage structure - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler); - - if (!png_ptr) { - return FALSE; - } - - // allocate/initialize the image information data. - - info_ptr = png_create_info_struct(png_ptr); - - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - return FALSE; - } - - // Set error handling. REQUIRED if you aren't supplying your own - // error handling functions in the png_create_write_struct() call. - - if (setjmp(png_jmpbuf(png_ptr))) { - // if we get here, we had a problem reading the file - - png_destroy_write_struct(&png_ptr, &info_ptr); - - return FALSE; - } - - // init the IO - - png_set_write_fn(png_ptr, &fio, _WriteProc, _FlushProc); - - // set physical resolution - - png_uint_32 res_x = (png_uint_32)FreeImage_GetDotsPerMeterX(dib); - png_uint_32 res_y = (png_uint_32)FreeImage_GetDotsPerMeterY(dib); - - if ((res_x > 0) && (res_y > 0)) { - png_set_pHYs(png_ptr, info_ptr, res_x, res_y, PNG_RESOLUTION_METER); - } - - // Set the image information here. Width and height are up to 2^31, - // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on - // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, - // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, - // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or - // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST - // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED - - width = FreeImage_GetWidth(dib); - height = FreeImage_GetHeight(dib); - pixel_depth = FreeImage_GetBPP(dib); - - BOOL bInterlaced = FALSE; - if( (flags & PNG_INTERLACED) == PNG_INTERLACED) { - interlace_type = PNG_INTERLACE_ADAM7; - bInterlaced = TRUE; - } else { - interlace_type = PNG_INTERLACE_NONE; - } - - // set the ZLIB compression level or default to PNG default compression level (ZLIB level = 6) - int zlib_level = flags & 0x0F; - if((zlib_level >= 1) && (zlib_level <= 9)) { - png_set_compression_level(png_ptr, zlib_level); - } else if((flags & PNG_Z_NO_COMPRESSION) == PNG_Z_NO_COMPRESSION) { - png_set_compression_level(png_ptr, Z_NO_COMPRESSION); - } - - // filtered strategy works better for high color images - if(pixel_depth >= 16){ - png_set_compression_strategy(png_ptr, Z_FILTERED); - png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH); - } else { - png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); - } - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - if(image_type == FIT_BITMAP) { - // standard image type - bit_depth = (pixel_depth > 8) ? 8 : pixel_depth; - } else { - // 16-bit greyscale or 16-bit RGB(A) - bit_depth = 16; - } - - // check for transparent images - BOOL bIsTransparent = - (image_type == FIT_BITMAP) && FreeImage_IsTransparent(dib) && (FreeImage_GetTransparencyCount(dib) > 0) ? TRUE : FALSE; - - switch (FreeImage_GetColorType(dib)) { - case FIC_MINISWHITE: - if(!bIsTransparent) { - // Invert monochrome files to have 0 as black and 1 as white (no break here) - png_set_invert_mono(png_ptr); - } - // (fall through) - - case FIC_MINISBLACK: - if(!bIsTransparent) { - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - PNG_COLOR_TYPE_GRAY, interlace_type, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - break; - } - // If a monochrome image is transparent, save it with a palette - // (fall through) - - case FIC_PALETTE: - { - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - PNG_COLOR_TYPE_PALETTE, interlace_type, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - // set the palette - - palette_entries = 1 << bit_depth; - palette = (png_colorp)png_malloc(png_ptr, palette_entries * sizeof (png_color)); - pal = FreeImage_GetPalette(dib); - - for (int i = 0; i < palette_entries; i++) { - palette[i].red = pal[i].rgbRed; - palette[i].green = pal[i].rgbGreen; - palette[i].blue = pal[i].rgbBlue; - } - - png_set_PLTE(png_ptr, info_ptr, palette, palette_entries); - - // You must not free palette here, because png_set_PLTE only makes a link to - // the palette that you malloced. Wait until you are about to destroy - // the png structure. - - break; - } - - case FIC_RGBALPHA : - has_alpha_channel = TRUE; - - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - PNG_COLOR_TYPE_RGBA, interlace_type, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - // flip BGR pixels to RGB - if(image_type == FIT_BITMAP) { - png_set_bgr(png_ptr); - } -#endif - break; - - case FIC_RGB: - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - PNG_COLOR_TYPE_RGB, interlace_type, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - // flip BGR pixels to RGB - if(image_type == FIT_BITMAP) { - png_set_bgr(png_ptr); - } -#endif - break; - - case FIC_CMYK: - break; - } - - // write possible ICC profile - - FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); - if (iccProfile->size && iccProfile->data) { - png_set_iCCP(png_ptr, info_ptr, "Embedded Profile", 0, (png_const_bytep)iccProfile->data, iccProfile->size); - } - - // write metadata - - WriteMetadata(png_ptr, info_ptr, dib); - - // Optional gamma chunk is strongly suggested if you have any guess - // as to the correct gamma of the image. - // png_set_gAMA(png_ptr, info_ptr, gamma); - - // set the transparency table - - if (bIsTransparent) { - png_set_tRNS(png_ptr, info_ptr, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), NULL); - } - - // set the background color - - if(FreeImage_HasBackgroundColor(dib)) { - png_color_16 image_background; - RGBQUAD rgbBkColor; - - FreeImage_GetBackgroundColor(dib, &rgbBkColor); - memset(&image_background, 0, sizeof(png_color_16)); - image_background.blue = rgbBkColor.rgbBlue; - image_background.green = rgbBkColor.rgbGreen; - image_background.red = rgbBkColor.rgbRed; - image_background.index = rgbBkColor.rgbReserved; - - png_set_bKGD(png_ptr, info_ptr, &image_background); - } - - // Write the file header information. - - png_write_info(png_ptr, info_ptr); - - // write out the image data - -#ifndef FREEIMAGE_BIGENDIAN - if (bit_depth == 16) { - // turn on 16 bit byte swapping - png_set_swap(png_ptr); - } -#endif - - int number_passes = 1; - if (bInterlaced) { - number_passes = png_set_interlace_handling(png_ptr); - } - - if ((pixel_depth == 32) && (!has_alpha_channel)) { - BYTE *buffer = (BYTE *)malloc(width * 3); - - // transparent conversion to 24-bit - // the number of passes is either 1 for non-interlaced images, or 7 for interlaced images - for (int pass = 0; pass < number_passes; pass++) { - for (png_uint_32 k = 0; k < height; k++) { - FreeImage_ConvertLine32To24(buffer, FreeImage_GetScanLine(dib, height - k - 1), width); - png_write_row(png_ptr, buffer); - } - } - free(buffer); - } else { - // the number of passes is either 1 for non-interlaced images, or 7 for interlaced images - for (int pass = 0; pass < number_passes; pass++) { - for (png_uint_32 k = 0; k < height; k++) { - png_write_row(png_ptr, FreeImage_GetScanLine(dib, height - k - 1)); - } - } - } - - // It is REQUIRED to call this to finish writing the rest of the file - // Bug with png_flush - - png_write_end(png_ptr, info_ptr); - - // clean up after the write, and free any memory allocated - if (palette) { - png_free(png_ptr, palette); - } - - png_destroy_write_struct(&png_ptr, &info_ptr); - - return TRUE; - - } catch (const char *text) { - if(png_ptr) { - png_destroy_write_struct(&png_ptr, &info_ptr); - } - FreeImage_OutputMessageProc(s_format_id, text); - } - } - - return FALSE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitPNG(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/TIFFLogLuv.cpp b/plugins/AdvaImg/src/FreeImage/TIFFLogLuv.cpp deleted file mode 100644 index 3f313232c4..0000000000 --- a/plugins/AdvaImg/src/FreeImage/TIFFLogLuv.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// ========================================================== -// XYZ to RGB TIFF conversion routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -void tiff_ConvertLineXYZToRGB(BYTE *target, BYTE *source, double stonits, int width_in_pixels) { - FIRGBF *rgbf = (FIRGBF*)target; - float *xyz = (float*)source; - - for (int cols = 0; cols < width_in_pixels; cols++) { - // assume CCIR-709 primaries (matrix from tif_luv.c) - // LOG Luv XYZ (D65) -> sRGB (CIE Illuminant E) - rgbf->red = (float)( 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2]); - rgbf->green = (float)(-1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2]); - rgbf->blue = (float)( 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2]); - - /* - if (stonits != 0.0) { - rgbf->red = (float)(rgbf->red * stonits); - rgbf->green = (float)(rgbf->green * stonits); - rgbf->blue = (float)(rgbf->blue * stonits); - } - */ - - rgbf++; - xyz += 3; - } -} - -void tiff_ConvertLineRGBToXYZ(BYTE *target, BYTE *source, int width_in_pixels) { - FIRGBF *rgbf = (FIRGBF*)source; - float *xyz = (float*)target; - - for (int cols = 0; cols < width_in_pixels; cols++) { - // assume CCIR-709 primaries, whitepoint x = 1/3 y = 1/3 (D_E) - // "The LogLuv Encoding for Full Gamut, High Dynamic Range Images" <G.Ward> - // sRGB ( CIE Illuminant E ) -> LOG Luv XYZ (D65) - xyz[0] = (float)(0.497*rgbf->red + 0.339*rgbf->green + 0.164*rgbf->blue); - xyz[1] = (float)(0.256*rgbf->red + 0.678*rgbf->green + 0.066*rgbf->blue); - xyz[2] = (float)(0.023*rgbf->red + 0.113*rgbf->green + 0.864*rgbf->blue); - - rgbf++; - xyz += 3; - } -} - diff --git a/plugins/AdvaImg/src/FreeImage/ToneMapping.cpp b/plugins/AdvaImg/src/FreeImage/ToneMapping.cpp deleted file mode 100644 index aca7961647..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ToneMapping.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// ========================================================== -// Tone mapping operators -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -/** -Performs a tone mapping on a 48-bit RGB or a 96-bit RGBF image and returns a 24-bit image. -The meaning of the parameters depends on the choosen algorithm. -When both parameters are set to zero, a default set of parameters is used. -@param dib Input RGB/RGBF image -@param tmo Tone mapping operator -@param first_param First parameter of the algorithm -@param second_param Second parameter of the algorithm -return Returns a 24-bit tone mapped image if successful, returns NULL otherwise -*/ -FIBITMAP * DLL_CALLCONV -FreeImage_ToneMapping(FIBITMAP *dib, FREE_IMAGE_TMO tmo, double first_param, double second_param) { - if(FreeImage_HasPixels(dib)) { - switch(tmo) { - // Adaptive logarithmic mapping (F. Drago, 2003) - case FITMO_DRAGO03: - if((first_param == 0) && (second_param == 0)) { - // use default values (gamma = 2.2, exposure = 0) - return FreeImage_TmoDrago03(dib, 2.2, 0); - } else { - // use user's value - return FreeImage_TmoDrago03(dib, first_param, second_param); - } - break; - // Dynamic range reduction inspired by photoreceptor phhysiology (E. Reinhard, 2005) - case FITMO_REINHARD05: - if((first_param == 0) && (second_param == 0)) { - // use default values by setting intensity to 0 and contrast to 0 - return FreeImage_TmoReinhard05(dib, 0, 0); - } else { - // use user's value - return FreeImage_TmoReinhard05(dib, first_param, second_param); - } - break; - // Gradient Domain HDR Compression (R. Fattal, 2002) - case FITMO_FATTAL02: - if((first_param == 0) && (second_param == 0)) { - // use default values by setting color saturation to 0.5 and attenuation to 0.85 - return FreeImage_TmoFattal02(dib, 0.5, 0.85); - } else { - // use user's value - return FreeImage_TmoFattal02(dib, first_param, second_param); - } - break; - } - } - - return NULL; -} - - diff --git a/plugins/AdvaImg/src/FreeImage/WuQuantizer.cpp b/plugins/AdvaImg/src/FreeImage/WuQuantizer.cpp deleted file mode 100644 index e092f228cc..0000000000 --- a/plugins/AdvaImg/src/FreeImage/WuQuantizer.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/////////////////////////////////////////////////////////////////////// -// C Implementation of Wu's Color Quantizer (v. 2) -// (see Graphics Gems vol. II, pp. 126-133) -// -// Author: Xiaolin Wu -// Dept. of Computer Science -// Univ. of Western Ontario -// London, Ontario N6A 5B7 -// wu@csd.uwo.ca -// -// Algorithm: Greedy orthogonal bipartition of RGB space for variance -// minimization aided by inclusion-exclusion tricks. -// For speed no nearest neighbor search is done. Slightly -// better performance can be expected by more sophisticated -// but more expensive versions. -// -// The author thanks Tom Lane at Tom_Lane@G.GP.CS.CMU.EDU for much of -// additional documentation and a cure to a previous bug. -// -// Free to distribute, comments and suggestions are appreciated. -/////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////// -// History -// ------- -// July 2000: C++ Implementation of Wu's Color Quantizer -// and adaptation for the FreeImage 2 Library -// Author: Hervé Drolon (drolon@infonie.fr) -// March 2004: Adaptation for the FreeImage 3 library (port to big endian processors) -// Author: Hervé Drolon (drolon@infonie.fr) -/////////////////////////////////////////////////////////////////////// - -#include "Quantizers.h" -#include "FreeImage.h" -#include "Utilities.h" - -/////////////////////////////////////////////////////////////////////// - -// Size of a 3D array : 33 x 33 x 33 -#define SIZE_3D 35937 - -// 3D array indexation -#define INDEX(r, g, b) ((r << 10) + (r << 6) + r + (g << 5) + g + b) - -#define MAXCOLOR 256 - -// Constructor / Destructor - -WuQuantizer::WuQuantizer(FIBITMAP *dib) { - width = FreeImage_GetWidth(dib); - height = FreeImage_GetHeight(dib); - pitch = FreeImage_GetPitch(dib); - m_dib = dib; - - gm2 = NULL; - wt = mr = mg = mb = NULL; - Qadd = NULL; - - // Allocate 3D arrays - gm2 = (float*)malloc(SIZE_3D * sizeof(float)); - wt = (LONG*)malloc(SIZE_3D * sizeof(LONG)); - mr = (LONG*)malloc(SIZE_3D * sizeof(LONG)); - mg = (LONG*)malloc(SIZE_3D * sizeof(LONG)); - mb = (LONG*)malloc(SIZE_3D * sizeof(LONG)); - - // Allocate Qadd - Qadd = (WORD *)malloc(sizeof(WORD) * width * height); - - if(!gm2 || !wt || !mr || !mg || !mb || !Qadd) { - if(gm2) free(gm2); - if(wt) free(wt); - if(mr) free(mr); - if(mg) free(mg); - if(mb) free(mb); - if(Qadd) free(Qadd); - throw FI_MSG_ERROR_MEMORY; - } - memset(gm2, 0, SIZE_3D * sizeof(float)); - memset(wt, 0, SIZE_3D * sizeof(LONG)); - memset(mr, 0, SIZE_3D * sizeof(LONG)); - memset(mg, 0, SIZE_3D * sizeof(LONG)); - memset(mb, 0, SIZE_3D * sizeof(LONG)); - memset(Qadd, 0, sizeof(WORD) * width * height); -} - -WuQuantizer::~WuQuantizer() { - if(gm2) free(gm2); - if(wt) free(wt); - if(mr) free(mr); - if(mg) free(mg); - if(mb) free(mb); - if(Qadd) free(Qadd); -} - - -// Histogram is in elements 1..HISTSIZE along each axis, -// element 0 is for base or marginal value -// NB: these must start out 0! - -// Build 3-D color histogram of counts, r/g/b, c^2 -void -WuQuantizer::Hist3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2, int ReserveSize, RGBQUAD *ReservePalette) { - int ind = 0; - int inr, ing, inb, table[256]; - int i; - unsigned y, x; - - for(i = 0; i < 256; i++) - table[i] = i * i; - - if (FreeImage_GetBPP(m_dib) == 24) { - for(y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(m_dib, y); - - for(x = 0; x < width; x++) { - inr = (bits[FI_RGBA_RED] >> 3) + 1; - ing = (bits[FI_RGBA_GREEN] >> 3) + 1; - inb = (bits[FI_RGBA_BLUE] >> 3) + 1; - ind = INDEX(inr, ing, inb); - Qadd[y*width + x] = (WORD)ind; - // [inr][ing][inb] - vwt[ind]++; - vmr[ind] += bits[FI_RGBA_RED]; - vmg[ind] += bits[FI_RGBA_GREEN]; - vmb[ind] += bits[FI_RGBA_BLUE]; - m2[ind] += (float)(table[bits[FI_RGBA_RED]] + table[bits[FI_RGBA_GREEN]] + table[bits[FI_RGBA_BLUE]]); - bits += 3; - } - } - } else { - for(y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(m_dib, y); - - for(x = 0; x < width; x++) { - inr = (bits[FI_RGBA_RED] >> 3) + 1; - ing = (bits[FI_RGBA_GREEN] >> 3) + 1; - inb = (bits[FI_RGBA_BLUE] >> 3) + 1; - ind = INDEX(inr, ing, inb); - Qadd[y*width + x] = (WORD)ind; - // [inr][ing][inb] - vwt[ind]++; - vmr[ind] += bits[FI_RGBA_RED]; - vmg[ind] += bits[FI_RGBA_GREEN]; - vmb[ind] += bits[FI_RGBA_BLUE]; - m2[ind] += (float)(table[bits[FI_RGBA_RED]] + table[bits[FI_RGBA_GREEN]] + table[bits[FI_RGBA_BLUE]]); - bits += 4; - } - } - } - - if( ReserveSize > 0 ) { - int max = 0; - for(i = 0; i < SIZE_3D; i++) { - if( vwt[i] > max ) max = vwt[i]; - } - max++; - for(i = 0; i < ReserveSize; i++) { - inr = (ReservePalette[i].rgbRed >> 3) + 1; - ing = (ReservePalette[i].rgbGreen >> 3) + 1; - inb = (ReservePalette[i].rgbBlue >> 3) + 1; - ind = INDEX(inr, ing, inb); - wt[ind] = max; - mr[ind] = max * ReservePalette[i].rgbRed; - mg[ind] = max * ReservePalette[i].rgbGreen; - mb[ind] = max * ReservePalette[i].rgbBlue; - gm2[ind] = (float)max * (float)(table[ReservePalette[i].rgbRed] + table[ReservePalette[i].rgbGreen] + table[ReservePalette[i].rgbBlue]); - } - } -} - - -// At conclusion of the histogram step, we can interpret -// wt[r][g][b] = sum over voxel of P(c) -// mr[r][g][b] = sum over voxel of r*P(c) , similarly for mg, mb -// m2[r][g][b] = sum over voxel of c^2*P(c) -// Actually each of these should be divided by 'ImageSize' to give the usual -// interpretation of P() as ranging from 0 to 1, but we needn't do that here. - - -// We now convert histogram into moments so that we can rapidly calculate -// the sums of the above quantities over any desired box. - -// Compute cumulative moments -void -WuQuantizer::M3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2) { - unsigned ind1, ind2; - BYTE i, r, g, b; - LONG line, line_r, line_g, line_b; - LONG area[33], area_r[33], area_g[33], area_b[33]; - float line2, area2[33]; - - for(r = 1; r <= 32; r++) { - for(i = 0; i <= 32; i++) { - area2[i] = 0; - area[i] = area_r[i] = area_g[i] = area_b[i] = 0; - } - for(g = 1; g <= 32; g++) { - line2 = 0; - line = line_r = line_g = line_b = 0; - for(b = 1; b <= 32; b++) { - ind1 = INDEX(r, g, b); // [r][g][b] - line += vwt[ind1]; - line_r += vmr[ind1]; - line_g += vmg[ind1]; - line_b += vmb[ind1]; - line2 += m2[ind1]; - area[b] += line; - area_r[b] += line_r; - area_g[b] += line_g; - area_b[b] += line_b; - area2[b] += line2; - ind2 = ind1 - 1089; // [r-1][g][b] - vwt[ind1] = vwt[ind2] + area[b]; - vmr[ind1] = vmr[ind2] + area_r[b]; - vmg[ind1] = vmg[ind2] + area_g[b]; - vmb[ind1] = vmb[ind2] + area_b[b]; - m2[ind1] = m2[ind2] + area2[b]; - } - } - } -} - -// Compute sum over a box of any given statistic -LONG -WuQuantizer::Vol( Box *cube, LONG *mmt ) { - return( mmt[INDEX(cube->r1, cube->g1, cube->b1)] - - mmt[INDEX(cube->r1, cube->g1, cube->b0)] - - mmt[INDEX(cube->r1, cube->g0, cube->b1)] - + mmt[INDEX(cube->r1, cube->g0, cube->b0)] - - mmt[INDEX(cube->r0, cube->g1, cube->b1)] - + mmt[INDEX(cube->r0, cube->g1, cube->b0)] - + mmt[INDEX(cube->r0, cube->g0, cube->b1)] - - mmt[INDEX(cube->r0, cube->g0, cube->b0)] ); -} - -// The next two routines allow a slightly more efficient calculation -// of Vol() for a proposed subbox of a given box. The sum of Top() -// and Bottom() is the Vol() of a subbox split in the given direction -// and with the specified new upper bound. - - -// Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1 -// (depending on dir) - -LONG -WuQuantizer::Bottom(Box *cube, BYTE dir, LONG *mmt) { - switch(dir) - { - case FI_RGBA_RED: - return( - mmt[INDEX(cube->r0, cube->g1, cube->b1)] - + mmt[INDEX(cube->r0, cube->g1, cube->b0)] - + mmt[INDEX(cube->r0, cube->g0, cube->b1)] - - mmt[INDEX(cube->r0, cube->g0, cube->b0)] ); - break; - case FI_RGBA_GREEN: - return( - mmt[INDEX(cube->r1, cube->g0, cube->b1)] - + mmt[INDEX(cube->r1, cube->g0, cube->b0)] - + mmt[INDEX(cube->r0, cube->g0, cube->b1)] - - mmt[INDEX(cube->r0, cube->g0, cube->b0)] ); - break; - case FI_RGBA_BLUE: - return( - mmt[INDEX(cube->r1, cube->g1, cube->b0)] - + mmt[INDEX(cube->r1, cube->g0, cube->b0)] - + mmt[INDEX(cube->r0, cube->g1, cube->b0)] - - mmt[INDEX(cube->r0, cube->g0, cube->b0)] ); - break; - } - - return 0; -} - - -// Compute remainder of Vol(cube, mmt), substituting pos for -// r1, g1, or b1 (depending on dir) - -LONG -WuQuantizer::Top(Box *cube, BYTE dir, int pos, LONG *mmt) { - switch(dir) - { - case FI_RGBA_RED: - return( mmt[INDEX(pos, cube->g1, cube->b1)] - -mmt[INDEX(pos, cube->g1, cube->b0)] - -mmt[INDEX(pos, cube->g0, cube->b1)] - +mmt[INDEX(pos, cube->g0, cube->b0)] ); - break; - case FI_RGBA_GREEN: - return( mmt[INDEX(cube->r1, pos, cube->b1)] - -mmt[INDEX(cube->r1, pos, cube->b0)] - -mmt[INDEX(cube->r0, pos, cube->b1)] - +mmt[INDEX(cube->r0, pos, cube->b0)] ); - break; - case FI_RGBA_BLUE: - return( mmt[INDEX(cube->r1, cube->g1, pos)] - -mmt[INDEX(cube->r1, cube->g0, pos)] - -mmt[INDEX(cube->r0, cube->g1, pos)] - +mmt[INDEX(cube->r0, cube->g0, pos)] ); - break; - } - - return 0; -} - -// Compute the weighted variance of a box -// NB: as with the raw statistics, this is really the variance * ImageSize - -float -WuQuantizer::Var(Box *cube) { - float dr = (float) Vol(cube, mr); - float dg = (float) Vol(cube, mg); - float db = (float) Vol(cube, mb); - float xx = gm2[INDEX(cube->r1, cube->g1, cube->b1)] - -gm2[INDEX(cube->r1, cube->g1, cube->b0)] - -gm2[INDEX(cube->r1, cube->g0, cube->b1)] - +gm2[INDEX(cube->r1, cube->g0, cube->b0)] - -gm2[INDEX(cube->r0, cube->g1, cube->b1)] - +gm2[INDEX(cube->r0, cube->g1, cube->b0)] - +gm2[INDEX(cube->r0, cube->g0, cube->b1)] - -gm2[INDEX(cube->r0, cube->g0, cube->b0)]; - - return (xx - (dr*dr+dg*dg+db*db)/(float)Vol(cube,wt)); -} - -// We want to minimize the sum of the variances of two subboxes. -// The sum(c^2) terms can be ignored since their sum over both subboxes -// is the same (the sum for the whole box) no matter where we split. -// The remaining terms have a minus sign in the variance formula, -// so we drop the minus sign and MAXIMIZE the sum of the two terms. - -float -WuQuantizer::Maximize(Box *cube, BYTE dir, int first, int last , int *cut, LONG whole_r, LONG whole_g, LONG whole_b, LONG whole_w) { - LONG half_r, half_g, half_b, half_w; - int i; - float temp; - - LONG base_r = Bottom(cube, dir, mr); - LONG base_g = Bottom(cube, dir, mg); - LONG base_b = Bottom(cube, dir, mb); - LONG base_w = Bottom(cube, dir, wt); - - float max = 0.0; - - *cut = -1; - - for (i = first; i < last; i++) { - half_r = base_r + Top(cube, dir, i, mr); - half_g = base_g + Top(cube, dir, i, mg); - half_b = base_b + Top(cube, dir, i, mb); - half_w = base_w + Top(cube, dir, i, wt); - - // now half_x is sum over lower half of box, if split at i - - if (half_w == 0) { // subbox could be empty of pixels! - continue; // never split into an empty box - } else { - temp = ((float)half_r*half_r + (float)half_g*half_g + (float)half_b*half_b)/half_w; - } - - half_r = whole_r - half_r; - half_g = whole_g - half_g; - half_b = whole_b - half_b; - half_w = whole_w - half_w; - - if (half_w == 0) { // subbox could be empty of pixels! - continue; // never split into an empty box - } else { - temp += ((float)half_r*half_r + (float)half_g*half_g + (float)half_b*half_b)/half_w; - } - - if (temp > max) { - max=temp; - *cut=i; - } - } - - return max; -} - -bool -WuQuantizer::Cut(Box *set1, Box *set2) { - BYTE dir; - int cutr, cutg, cutb; - - LONG whole_r = Vol(set1, mr); - LONG whole_g = Vol(set1, mg); - LONG whole_b = Vol(set1, mb); - LONG whole_w = Vol(set1, wt); - - float maxr = Maximize(set1, FI_RGBA_RED, set1->r0+1, set1->r1, &cutr, whole_r, whole_g, whole_b, whole_w); - float maxg = Maximize(set1, FI_RGBA_GREEN, set1->g0+1, set1->g1, &cutg, whole_r, whole_g, whole_b, whole_w); - float maxb = Maximize(set1, FI_RGBA_BLUE, set1->b0+1, set1->b1, &cutb, whole_r, whole_g, whole_b, whole_w); - - if ((maxr >= maxg) && (maxr >= maxb)) { - dir = FI_RGBA_RED; - - if (cutr < 0) { - return false; // can't split the box - } - } else if ((maxg >= maxr) && (maxg>=maxb)) { - dir = FI_RGBA_GREEN; - } else { - dir = FI_RGBA_BLUE; - } - - set2->r1 = set1->r1; - set2->g1 = set1->g1; - set2->b1 = set1->b1; - - switch (dir) { - case FI_RGBA_RED: - set2->r0 = set1->r1 = cutr; - set2->g0 = set1->g0; - set2->b0 = set1->b0; - break; - - case FI_RGBA_GREEN: - set2->g0 = set1->g1 = cutg; - set2->r0 = set1->r0; - set2->b0 = set1->b0; - break; - - case FI_RGBA_BLUE: - set2->b0 = set1->b1 = cutb; - set2->r0 = set1->r0; - set2->g0 = set1->g0; - break; - } - - set1->vol = (set1->r1-set1->r0)*(set1->g1-set1->g0)*(set1->b1-set1->b0); - set2->vol = (set2->r1-set2->r0)*(set2->g1-set2->g0)*(set2->b1-set2->b0); - - return true; -} - - -void -WuQuantizer::Mark(Box *cube, int label, BYTE *tag) { - for (int r = cube->r0 + 1; r <= cube->r1; r++) { - for (int g = cube->g0 + 1; g <= cube->g1; g++) { - for (int b = cube->b0 + 1; b <= cube->b1; b++) { - tag[INDEX(r, g, b)] = (BYTE)label; - } - } - } -} - -// Wu Quantization algorithm -FIBITMAP * -WuQuantizer::Quantize(int PaletteSize, int ReserveSize, RGBQUAD *ReservePalette) { - BYTE *tag = NULL; - - try { - Box cube[MAXCOLOR]; - int next; - LONG i, weight; - int k; - float vv[MAXCOLOR], temp; - - // Compute 3D histogram - - Hist3D(wt, mr, mg, mb, gm2, ReserveSize, ReservePalette); - - // Compute moments - - M3D(wt, mr, mg, mb, gm2); - - cube[0].r0 = cube[0].g0 = cube[0].b0 = 0; - cube[0].r1 = cube[0].g1 = cube[0].b1 = 32; - next = 0; - - for (i = 1; i < PaletteSize; i++) { - if(Cut(&cube[next], &cube[i])) { - // volume test ensures we won't try to cut one-cell box - vv[next] = (cube[next].vol > 1) ? Var(&cube[next]) : 0; - vv[i] = (cube[i].vol > 1) ? Var(&cube[i]) : 0; - } else { - vv[next] = 0.0; // don't try to split this box again - i--; // didn't create box i - } - - next = 0; temp = vv[0]; - - for (k = 1; k <= i; k++) { - if (vv[k] > temp) { - temp = vv[k]; next = k; - } - } - - if (temp <= 0.0) { - PaletteSize = i + 1; - - // Error: "Only got 'PaletteSize' boxes" - - break; - } - } - - // Partition done - - // the space for array gm2 can be freed now - - free(gm2); - - gm2 = NULL; - - // Allocate a new dib - - FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8); - - if (new_dib == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // create an optimized palette - - RGBQUAD *new_pal = FreeImage_GetPalette(new_dib); - - tag = (BYTE*) malloc(SIZE_3D * sizeof(BYTE)); - if (tag == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - memset(tag, 0, SIZE_3D * sizeof(BYTE)); - - for (k = 0; k < PaletteSize ; k++) { - Mark(&cube[k], k, tag); - weight = Vol(&cube[k], wt); - - if (weight) { - new_pal[k].rgbRed = (BYTE)(((float)Vol(&cube[k], mr) / (float)weight) + 0.5f); - new_pal[k].rgbGreen = (BYTE)(((float)Vol(&cube[k], mg) / (float)weight) + 0.5f); - new_pal[k].rgbBlue = (BYTE)(((float)Vol(&cube[k], mb) / (float)weight) + 0.5f); - } else { - // Error: bogus box 'k' - - new_pal[k].rgbRed = new_pal[k].rgbGreen = new_pal[k].rgbBlue = 0; - } - } - - int npitch = FreeImage_GetPitch(new_dib); - - for (unsigned y = 0; y < height; y++) { - BYTE *new_bits = FreeImage_GetBits(new_dib) + (y * npitch); - - for (unsigned x = 0; x < width; x++) { - new_bits[x] = tag[Qadd[y*width + x]]; - } - } - - // output 'new_pal' as color look-up table contents, - // 'new_bits' as the quantized image (array of table addresses). - - free(tag); - - return (FIBITMAP*) new_dib; - } catch(...) { - free(tag); - } - - return NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/ZLibInterface.cpp b/plugins/AdvaImg/src/FreeImage/ZLibInterface.cpp deleted file mode 100644 index 39c7ac0ecc..0000000000 --- a/plugins/AdvaImg/src/FreeImage/ZLibInterface.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// ========================================================== -// ZLib library interface -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "zlib.h" -#include "FreeImage.h" -#include "Utilities.h" -#include "zutil.h" /* must be the last header because of error C3163 in VS2008 (_vsnprintf defined in stdio.h) */ - -/** -Compresses a source buffer into a target buffer, using the ZLib library. -Upon entry, target_size is the total size of the destination buffer, -which must be at least 0.1% larger than source_size plus 12 bytes. - -@param target Destination buffer -@param target_size Size of the destination buffer, in bytes -@param source Source buffer -@param source_size Size of the source buffer, in bytes -@return Returns the actual size of the compressed buffer, returns 0 if an error occured -@see FreeImage_ZLibUncompress -*/ -DWORD DLL_CALLCONV -FreeImage_ZLibCompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) { - uLongf dest_len = (uLongf)target_size; - - int zerr = compress(target, &dest_len, source, source_size); - switch(zerr) { - case Z_MEM_ERROR: // not enough memory - case Z_BUF_ERROR: // not enough room in the output buffer - FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr)); - return 0; - case Z_OK: - return dest_len; - } - - return 0; -} - -/** -Decompresses a source buffer into a target buffer, using the ZLib library. -Upon entry, target_size is the total size of the destination buffer, -which must be large enough to hold the entire uncompressed data. -The size of the uncompressed data must have been saved previously by the compressor -and transmitted to the decompressor by some mechanism outside the scope of this -compression library. - -@param target Destination buffer -@param target_size Size of the destination buffer, in bytes -@param source Source buffer -@param source_size Size of the source buffer, in bytes -@return Returns the actual size of the uncompressed buffer, returns 0 if an error occured -@see FreeImage_ZLibCompress -*/ -DWORD DLL_CALLCONV -FreeImage_ZLibUncompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) { - uLongf dest_len = (uLongf)target_size; - - int zerr = uncompress(target, &dest_len, source, source_size); - switch(zerr) { - case Z_MEM_ERROR: // not enough memory - case Z_BUF_ERROR: // not enough room in the output buffer - case Z_DATA_ERROR: // input data was corrupted - FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr)); - return 0; - case Z_OK: - return dest_len; - } - - return 0; -} - -/** -Compresses a source buffer into a target buffer, using the ZLib library. -On success, the target buffer contains a GZIP compatible layout. -Upon entry, target_size is the total size of the destination buffer, -which must be at least 0.1% larger than source_size plus 24 bytes. - -@param target Destination buffer -@param target_size Size of the destination buffer, in bytes -@param source Source buffer -@param source_size Size of the source buffer, in bytes -@return Returns the actual size of the compressed buffer, returns 0 if an error occured -@see FreeImage_ZLibCompress -*/ -DWORD DLL_CALLCONV -FreeImage_ZLibGZip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) { - uLongf dest_len = (uLongf)target_size - 12; - DWORD crc = crc32(0L, NULL, 0); - - // set up header (stolen from zlib/gzio.c) - sprintf((char *)target, "%c%c%c%c%c%c%c%c", 0x1f, 0x8b, - Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/); - int zerr = compress2(target + 8, &dest_len, source, source_size, Z_BEST_COMPRESSION); - switch(zerr) { - case Z_MEM_ERROR: // not enough memory - case Z_BUF_ERROR: // not enough room in the output buffer - FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr)); - return 0; - case Z_OK: { - // patch header, setup crc and length (stolen from mod_trace_output) - BYTE *p = target + 8; *p++ = 2; *p = OS_CODE; // xflags, os_code - crc = crc32(crc, source, source_size); - memcpy(target + 4 + dest_len, &crc, 4); - memcpy(target + 8 + dest_len, &source_size, 4); - return dest_len + 12; - } - } - return 0; -} - -/** -Decompresses a gzipped source buffer into a target buffer, using the ZLib library. -Upon entry, target_size is the total size of the destination buffer, -which must be large enough to hold the entire uncompressed data. -The size of the uncompressed data must have been saved previously by the compressor -and transmitted to the decompressor by some mechanism outside the scope of this -compression library. - -@param target Destination buffer -@param target_size Size of the destination buffer, in bytes -@param source Source buffer -@param source_size Size of the source buffer, in bytes -@return Returns the actual size of the uncompressed buffer, returns 0 if an error occured -@see FreeImage_ZLibGZip -*/ - -static int get_byte(z_stream *stream) { - if (stream->avail_in <= 0) return EOF; - stream->avail_in--; - return *(stream->next_in)++; -} - -static int checkheader(z_stream *stream) { - int flags, c; - DWORD len; - - if (get_byte(stream) != 0x1f || get_byte(stream) != 0x8b) - return Z_DATA_ERROR; - if (get_byte(stream) != Z_DEFLATED || ((flags = get_byte(stream)) & 0xE0) != 0) - return Z_DATA_ERROR; - for (len = 0; len < 6; len++) (void)get_byte(stream); - - if ((flags & 0x04) != 0) { /* skip the extra field */ - len = (DWORD)get_byte(stream); - len += ((DWORD)get_byte(stream)) << 8; - /* len is garbage if EOF but the loop below will quit anyway */ - while (len-- != 0 && get_byte(stream) != EOF) ; - } - if ((flags & 0x08) != 0) { /* skip the original file name */ - while ((c = get_byte(stream)) != 0 && c != EOF) ; - } - if ((flags & 0x10) != 0) { /* skip the .gz file comment */ - while ((c = get_byte(stream)) != 0 && c != EOF) ; - } - if ((flags & 0x02) != 0) { /* skip the header crc */ - for (len = 0; len < 2; len++) (void)get_byte(stream); - } - return Z_OK; -} - -DWORD DLL_CALLCONV -FreeImage_ZLibGUnzip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) { - DWORD src_len = source_size; - DWORD dest_len = target_size; - int zerr = Z_DATA_ERROR; - - if (src_len > 0) { - z_stream stream; - memset(&stream, 0, sizeof (stream)); - if ((zerr = inflateInit2(&stream, -MAX_WBITS)) == Z_OK) { - stream.next_in = source; - stream.avail_in = source_size; - - stream.next_out = target; - stream.avail_out = target_size; - - if ((zerr = checkheader(&stream)) == Z_OK) { - zerr = inflate (&stream, Z_NO_FLUSH); - dest_len = target_size - stream.avail_out; - - if (zerr == Z_OK || zerr == Z_STREAM_END) - inflateEnd(&stream); - } - } - } - if (zerr != Z_OK && zerr != Z_STREAM_END) { - FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr)); - return 0; - } - return dest_len; -} - -/** -Update a running crc from source and return the updated crc, using the ZLib library. -If source is NULL, this function returns the required initial value for the crc. - -@param crc Running crc value -@param source Source buffer -@param source_size Size of the source buffer, in bytes -@return Returns the new crc value -*/ -DWORD DLL_CALLCONV -FreeImage_ZLibCRC32(DWORD crc, BYTE *source, DWORD source_size) { - - return crc32(crc, source, source_size); -} diff --git a/plugins/AdvaImg/src/FreeImage/tmoColorConvert.cpp b/plugins/AdvaImg/src/FreeImage/tmoColorConvert.cpp deleted file mode 100644 index 8770c6f4bf..0000000000 --- a/plugins/AdvaImg/src/FreeImage/tmoColorConvert.cpp +++ /dev/null @@ -1,479 +0,0 @@ -// ========================================================== -// High Dynamic Range bitmap conversion routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "ToneMapping.h" - -// ---------------------------------------------------------- -// Convert RGB to and from Yxy, same as in Reinhard et al. SIGGRAPH 2002 -// References : -// [1] Radiance Home Page [Online] http://radsite.lbl.gov/radiance/HOME.html -// [2] E. Reinhard, M. Stark, P. Shirley, and J. Ferwerda, -// Photographic Tone Reproduction for Digital Images, ACM Transactions on Graphics, -// 21(3):267-276, 2002 (Proceedings of SIGGRAPH 2002). -// [3] J. Tumblin and H.E. Rushmeier, -// Tone Reproduction for Realistic Images. IEEE Computer Graphics and Applications, -// 13(6):42-48, 1993. -// ---------------------------------------------------------- - -/** -nominal CRT primaries -*/ -/* -static const float CIE_x_r = 0.640F; -static const float CIE_y_r = 0.330F; -static const float CIE_x_g = 0.290F; -static const float CIE_y_g = 0.600F; -static const float CIE_x_b = 0.150F; -static const float CIE_y_b = 0.060F; -static const float CIE_x_w = 0.3333F; // use true white -static const float CIE_y_w = 0.3333F; -*/ -/** -sRGB primaries -*/ -static const float CIE_x_r = 0.640F; -static const float CIE_y_r = 0.330F; -static const float CIE_x_g = 0.300F; -static const float CIE_y_g = 0.600F; -static const float CIE_x_b = 0.150F; -static const float CIE_y_b = 0.060F; -static const float CIE_x_w = 0.3127F; // Illuminant D65 -static const float CIE_y_w = 0.3290F; - -static const float CIE_D = ( CIE_x_r*(CIE_y_g - CIE_y_b) + CIE_x_g*(CIE_y_b - CIE_y_r) + CIE_x_b*(CIE_y_r - CIE_y_g) ); -static const float CIE_C_rD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_g - CIE_y_b) - CIE_y_w*(CIE_x_g - CIE_x_b) + CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g) ); -static const float CIE_C_gD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_b - CIE_y_r) - CIE_y_w*(CIE_x_b - CIE_x_r) - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r) ); -static const float CIE_C_bD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_r - CIE_y_g) - CIE_y_w*(CIE_x_r - CIE_x_g) + CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r) ); - -/** -RGB to XYZ (no white balance) -*/ -static const float RGB2XYZ[3][3] = { - { CIE_x_r*CIE_C_rD / CIE_D, - CIE_x_g*CIE_C_gD / CIE_D, - CIE_x_b*CIE_C_bD / CIE_D - }, - { CIE_y_r*CIE_C_rD / CIE_D, - CIE_y_g*CIE_C_gD / CIE_D, - CIE_y_b*CIE_C_bD / CIE_D - }, - { (1 - CIE_x_r-CIE_y_r)*CIE_C_rD / CIE_D, - (1 - CIE_x_g-CIE_y_g)*CIE_C_gD / CIE_D, - (1 - CIE_x_b-CIE_y_b)*CIE_C_bD / CIE_D - } -}; - -/** -XYZ to RGB (no white balance) -*/ -static const float XYZ2RGB[3][3] = { - {(CIE_y_g - CIE_y_b - CIE_x_b*CIE_y_g + CIE_y_b*CIE_x_g) / CIE_C_rD, - (CIE_x_b - CIE_x_g - CIE_x_b*CIE_y_g + CIE_x_g*CIE_y_b) / CIE_C_rD, - (CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g) / CIE_C_rD - }, - {(CIE_y_b - CIE_y_r - CIE_y_b*CIE_x_r + CIE_y_r*CIE_x_b) / CIE_C_gD, - (CIE_x_r - CIE_x_b - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r) / CIE_C_gD, - (CIE_x_b*CIE_y_r - CIE_x_r*CIE_y_b) / CIE_C_gD - }, - {(CIE_y_r - CIE_y_g - CIE_y_r*CIE_x_g + CIE_y_g*CIE_x_r) / CIE_C_bD, - (CIE_x_g - CIE_x_r - CIE_x_g*CIE_y_r + CIE_x_r*CIE_y_g) / CIE_C_bD, - (CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r) / CIE_C_bD - } -}; - -/** -This gives approximately the following matrices : - -static const float RGB2XYZ[3][3] = { - { 0.41239083F, 0.35758433F, 0.18048081F }, - { 0.21263903F, 0.71516865F, 0.072192319F }, - { 0.019330820F, 0.11919473F, 0.95053220F } -}; -static const float XYZ2RGB[3][3] = { - { 3.2409699F, -1.5373832F, -0.49861079F }, - { -0.96924376F, 1.8759676F, 0.041555084F }, - { 0.055630036F, -0.20397687F, 1.0569715F } -}; -*/ - -// ---------------------------------------------------------- - -static const float EPSILON = 1e-06F; -static const float INF = 1e+10F; - -/** -Convert in-place floating point RGB data to Yxy.<br> -On output, pixel->red == Y, pixel->green == x, pixel->blue == y -@param dib Input RGBF / Output Yxy image -@return Returns TRUE if successful, returns FALSE otherwise -*/ -BOOL -ConvertInPlaceRGBFToYxy(FIBITMAP *dib) { - float result[3]; - - if(FreeImage_GetImageType(dib) != FIT_RGBF) - return FALSE; - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - - BYTE *bits = (BYTE*)FreeImage_GetBits(dib); - for(unsigned y = 0; y < height; y++) { - FIRGBF *pixel = (FIRGBF*)bits; - for(unsigned x = 0; x < width; x++) { - result[0] = result[1] = result[2] = 0; - for (int i = 0; i < 3; i++) { - result[i] += RGB2XYZ[i][0] * pixel[x].red; - result[i] += RGB2XYZ[i][1] * pixel[x].green; - result[i] += RGB2XYZ[i][2] * pixel[x].blue; - } - const float W = result[0] + result[1] + result[2]; - const float Y = result[1]; - if(W > 0) { - pixel[x].red = Y; // Y - pixel[x].green = result[0] / W; // x - pixel[x].blue = result[1] / W; // y - } else { - pixel[x].red = pixel[x].green = pixel[x].blue = 0; - } - } - // next line - bits += pitch; - } - - return TRUE; -} - -/** -Convert in-place Yxy image to floating point RGB data.<br> -On input, pixel->red == Y, pixel->green == x, pixel->blue == y -@param dib Input Yxy / Output RGBF image -@return Returns TRUE if successful, returns FALSE otherwise -*/ -BOOL -ConvertInPlaceYxyToRGBF(FIBITMAP *dib) { - float result[3]; - float X, Y, Z; - - if(FreeImage_GetImageType(dib) != FIT_RGBF) - return FALSE; - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - - BYTE *bits = (BYTE*)FreeImage_GetBits(dib); - for(unsigned y = 0; y < height; y++) { - FIRGBF *pixel = (FIRGBF*)bits; - for(unsigned x = 0; x < width; x++) { - Y = pixel[x].red; // Y - result[1] = pixel[x].green; // x - result[2] = pixel[x].blue; // y - if ((Y > EPSILON) && (result[1] > EPSILON) && (result[2] > EPSILON)) { - X = (result[1] * Y) / result[2]; - Z = (X / result[1]) - X - Y; - } else { - X = Z = EPSILON; - } - pixel[x].red = X; - pixel[x].green = Y; - pixel[x].blue = Z; - result[0] = result[1] = result[2] = 0; - for (int i = 0; i < 3; i++) { - result[i] += XYZ2RGB[i][0] * pixel[x].red; - result[i] += XYZ2RGB[i][1] * pixel[x].green; - result[i] += XYZ2RGB[i][2] * pixel[x].blue; - } - pixel[x].red = result[0]; // R - pixel[x].green = result[1]; // G - pixel[x].blue = result[2]; // B - } - // next line - bits += pitch; - } - - return TRUE; -} - -/** -Get the maximum, minimum and average luminance.<br> -On input, pixel->red == Y, pixel->green == x, pixel->blue == y -@param Yxy Source Yxy image to analyze -@param maxLum Maximum luminance -@param minLum Minimum luminance -@param worldLum Average luminance (world adaptation luminance) -@return Returns TRUE if successful, returns FALSE otherwise -*/ -BOOL -LuminanceFromYxy(FIBITMAP *Yxy, float *maxLum, float *minLum, float *worldLum) { - if(FreeImage_GetImageType(Yxy) != FIT_RGBF) - return FALSE; - - const unsigned width = FreeImage_GetWidth(Yxy); - const unsigned height = FreeImage_GetHeight(Yxy); - const unsigned pitch = FreeImage_GetPitch(Yxy); - - float max_lum = 0, min_lum = 0; - double sum = 0; - - BYTE *bits = (BYTE*)FreeImage_GetBits(Yxy); - for(unsigned y = 0; y < height; y++) { - const FIRGBF *pixel = (FIRGBF*)bits; - for(unsigned x = 0; x < width; x++) { - const float Y = MAX(0.0F, pixel[x].red);// avoid negative values - max_lum = (max_lum < Y) ? Y : max_lum; // max Luminance in the scene - min_lum = (min_lum < Y) ? min_lum : Y; // min Luminance in the scene - sum += log(2.3e-5F + Y); // contrast constant in Tumblin paper - } - // next line - bits += pitch; - } - // maximum luminance - *maxLum = max_lum; - // minimum luminance - *minLum = min_lum; - // average log luminance - double avgLogLum = (sum / (width * height)); - // world adaptation luminance - *worldLum = (float)exp(avgLogLum); - - return TRUE; -} - -/** -Clamp RGBF image highest values to display white, -then convert to 24-bit RGB -*/ -FIBITMAP* -ClampConvertRGBFTo24(FIBITMAP *src) { - if(FreeImage_GetImageType(src) != FIT_RGBF) - return FALSE; - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - FIBITMAP *dst = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(!dst) return NULL; - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const FIRGBF *src_pixel = (FIRGBF*)src_bits; - BYTE *dst_pixel = (BYTE*)dst_bits; - for(unsigned x = 0; x < width; x++) { - const float red = (src_pixel[x].red > 1) ? 1 : src_pixel[x].red; - const float green = (src_pixel[x].green > 1) ? 1 : src_pixel[x].green; - const float blue = (src_pixel[x].blue > 1) ? 1 : src_pixel[x].blue; - - dst_pixel[FI_RGBA_RED] = (BYTE)(255.0F * red + 0.5F); - dst_pixel[FI_RGBA_GREEN] = (BYTE)(255.0F * green + 0.5F); - dst_pixel[FI_RGBA_BLUE] = (BYTE)(255.0F * blue + 0.5F); - dst_pixel += 3; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - - return dst; -} - -/** -Extract the luminance channel L from a RGBF image. -Luminance is calculated from the sRGB model (RGB2XYZ matrix) -using a D65 white point : -L = ( 0.2126 * r ) + ( 0.7152 * g ) + ( 0.0722 * b ) -Reference : -A Standard Default Color Space for the Internet - sRGB. -[online] http://www.w3.org/Graphics/Color/sRGB -*/ -FIBITMAP* -ConvertRGBFToY(FIBITMAP *src) { - if(FreeImage_GetImageType(src) != FIT_RGBF) - return FALSE; - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - FIBITMAP *dst = FreeImage_AllocateT(FIT_FLOAT, width, height); - if(!dst) return NULL; - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - - BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const FIRGBF *src_pixel = (FIRGBF*)src_bits; - float *dst_pixel = (float*)dst_bits; - for(unsigned x = 0; x < width; x++) { - const float L = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); - dst_pixel[x] = (L > 0) ? L : 0; - } - // next line - src_bits += src_pitch; - dst_bits += dst_pitch; - } - - return dst; -} - -/** -Get the maximum, minimum, average luminance and log average luminance from a Y image -@param dib Source Y image to analyze -@param maxLum Maximum luminance -@param minLum Minimum luminance -@param Lav Average luminance -@param Llav Log average luminance (also known as 'world adaptation luminance') -@return Returns TRUE if successful, returns FALSE otherwise -@see ConvertRGBFToY, FreeImage_TmoReinhard05Ex -*/ -BOOL -LuminanceFromY(FIBITMAP *dib, float *maxLum, float *minLum, float *Lav, float *Llav) { - if(FreeImage_GetImageType(dib) != FIT_FLOAT) - return FALSE; - - unsigned width = FreeImage_GetWidth(dib); - unsigned height = FreeImage_GetHeight(dib); - unsigned pitch = FreeImage_GetPitch(dib); - - float max_lum = -1e20F, min_lum = 1e20F; - double sumLum = 0, sumLogLum = 0; - - BYTE *bits = (BYTE*)FreeImage_GetBits(dib); - for(unsigned y = 0; y < height; y++) { - const float *pixel = (float*)bits; - for(unsigned x = 0; x < width; x++) { - const float Y = pixel[x]; - max_lum = (max_lum < Y) ? Y : max_lum; // max Luminance in the scene - min_lum = ((Y > 0) && (min_lum < Y)) ? min_lum : Y; // min Luminance in the scene - sumLum += Y; // average luminance - sumLogLum += log(2.3e-5F + Y); // contrast constant in Tumblin paper - } - // next line - bits += pitch; - } - - // maximum luminance - *maxLum = max_lum; - // minimum luminance - *minLum = min_lum; - // average luminance - *Lav = (float)(sumLum / (width * height)); - // average log luminance, a.k.a. world adaptation luminance - *Llav = (float)exp(sumLogLum / (width * height)); - - return TRUE; -} -// -------------------------------------------------------------------------- - -static void findMaxMinPercentile(FIBITMAP *Y, float minPrct, float *minLum, float maxPrct, float *maxLum) { - int x, y; - int width = FreeImage_GetWidth(Y); - int height = FreeImage_GetHeight(Y); - int pitch = FreeImage_GetPitch(Y); - - std::vector<float> vY(width * height); - - BYTE *bits = (BYTE*)FreeImage_GetBits(Y); - for(y = 0; y < height; y++) { - float *pixel = (float*)bits; - for(x = 0; x < width; x++) { - if(pixel[x] != 0) { - vY.push_back(pixel[x]); - } - } - bits += pitch; - } - - std::sort(vY.begin(), vY.end()); - - *minLum = vY.at( int(minPrct * vY.size()) ); - *maxLum = vY.at( int(maxPrct * vY.size()) ); -} - -/** -Clipping function<br> -Remove any extremely bright and/or extremely dark pixels -and normalize between 0 and 1. -@param Y Input/Output image -@param minPrct Minimum percentile -@param maxPrct Maximum percentile -*/ -void -NormalizeY(FIBITMAP *Y, float minPrct, float maxPrct) { - int x, y; - float maxLum, minLum; - - if(minPrct > maxPrct) { - // swap values - float t = minPrct; minPrct = maxPrct; maxPrct = t; - } - if(minPrct < 0) minPrct = 0; - if(maxPrct > 1) maxPrct = 1; - - int width = FreeImage_GetWidth(Y); - int height = FreeImage_GetHeight(Y); - int pitch = FreeImage_GetPitch(Y); - - // find max & min luminance values - if((minPrct > 0) || (maxPrct < 1)) { - maxLum = 0, minLum = 0; - findMaxMinPercentile(Y, minPrct, &minLum, maxPrct, &maxLum); - } else { - maxLum = -1e20F, minLum = 1e20F; - BYTE *bits = (BYTE*)FreeImage_GetBits(Y); - for(y = 0; y < height; y++) { - const float *pixel = (float*)bits; - for(x = 0; x < width; x++) { - const float value = pixel[x]; - maxLum = (maxLum < value) ? value : maxLum; // max Luminance in the scene - minLum = (minLum < value) ? minLum : value; // min Luminance in the scene - } - // next line - bits += pitch; - } - } - if(maxLum == minLum) return; - - // normalize to range 0..1 - const float divider = maxLum - minLum; - BYTE *bits = (BYTE*)FreeImage_GetBits(Y); - for(y = 0; y < height; y++) { - float *pixel = (float*)bits; - for(x = 0; x < width; x++) { - pixel[x] = (pixel[x] - minLum) / divider; - if(pixel[x] <= 0) pixel[x] = EPSILON; - if(pixel[x] > 1) pixel[x] = 1; - } - // next line - bits += pitch; - } -} diff --git a/plugins/AdvaImg/src/FreeImage/tmoDrago03.cpp b/plugins/AdvaImg/src/FreeImage/tmoDrago03.cpp deleted file mode 100644 index d1efe9486b..0000000000 --- a/plugins/AdvaImg/src/FreeImage/tmoDrago03.cpp +++ /dev/null @@ -1,295 +0,0 @@ -// ========================================================== -// Tone mapping operator (Drago, 2003) -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "ToneMapping.h" - -// ---------------------------------------------------------- -// Logarithmic mapping operator -// Reference: -// [1] F. Drago, K. Myszkowski, T. Annen, and N. Chiba, -// Adaptive Logarithmic Mapping for Displaying High Contrast Scenes, -// Eurographics 2003. -// ---------------------------------------------------------- - -/** -Bias function -*/ -static inline double -biasFunction(const double b, const double x) { - return pow (x, b); // pow(x, log(bias)/log(0.5) -} - -/** -Padé approximation of log(x + 1) -x(6+x)/(6+4x) good if x < 1 -x*(6 + 0.7662x)/(5.9897 + 3.7658x) between 1 and 2 -See http://www.nezumi.demon.co.uk/consult/logx.htm -*/ -static inline double -pade_log(const double x) { - if(x < 1) { - return (x * (6 + x) / (6 + 4 * x)); - } else if(x < 2) { - return (x * (6 + 0.7662 * x) / (5.9897 + 3.7658 * x)); - } - return log(x + 1); -} - -/** -Log mapping operator -@param dib Input / Output Yxy image -@param maxLum Maximum luminance -@param avgLum Average luminance (world adaptation luminance) -@param biasParam Bias parameter (a zero value default to 0.85) -@param exposure Exposure parameter (default to 0) -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -ToneMappingDrago03(FIBITMAP *dib, const float maxLum, const float avgLum, float biasParam, const float exposure) { - const float LOG05 = -0.693147F; // log(0.5) - - double Lmax, divider, interpol, biasP; - unsigned x, y; - double L; - - if(FreeImage_GetImageType(dib) != FIT_RGBF) - return FALSE; - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - - - // arbitrary Bias Parameter - if(biasParam == 0) - biasParam = 0.85F; - - // normalize maximum luminance by average luminance - Lmax = maxLum / avgLum; - - divider = log10(Lmax+1); - biasP = log(biasParam)/LOG05; - -#if !defined(DRAGO03_FAST) - - /** - Normal tone mapping of every pixel - further acceleration is obtained by a Padé approximation of log(x + 1) - */ - BYTE *bits = (BYTE*)FreeImage_GetBits(dib); - for(y = 0; y < height; y++) { - FIRGBF *pixel = (FIRGBF*)bits; - for(x = 0; x < width; x++) { - double Yw = pixel[x].red / avgLum; - Yw *= exposure; - interpol = log(2 + biasFunction(biasP, Yw / Lmax) * 8); - L = pade_log(Yw);// log(Yw + 1) - pixel[x].red = (float)((L / interpol) / divider); - } - // next line - bits += pitch; - } - -#else - unsigned index; - int i, j; - - unsigned max_width = width - (width % 3); - unsigned max_height = height - (height % 3); - unsigned fpitch = pitch / sizeof(FIRGBF); - - /** - fast tone mapping - split the image into 3x3 pixel tiles and perform the computation for each group of 9 pixels - further acceleration is obtained by a Padé approximation of log(x + 1) - => produce artifacts and not so faster, so the code has been disabled - */ -#define PIXEL(x, y) image[y*fpitch + x].red - - FIRGBF *image = (FIRGBF*)FreeImage_GetBits(dib); - for(y = 0; y < max_height; y += 3) { - for(x = 0; x < max_width; x += 3) { - double average = 0; - for(i = 0; i < 3; i++) { - for(j = 0; j < 3; j++) { - index = (y + i)*fpitch + (x + j); - image[index].red /= (float)avgLum; - image[index].red *= exposure; - average += image[index].red; - } - } - average = average / 9 - PIXEL(x, y); - if(average > -1 && average < 1) { - interpol = log(2 + pow(PIXEL(x + 1, y + 1) / Lmax, biasP) * 8); - for(i = 0; i < 3; i++) { - for(j = 0; j < 3; j++) { - index = (y + i)*fpitch + (x + j); - L = pade_log(image[index].red);// log(image[index].red + 1) - image[index].red = (float)((L / interpol) / divider); - } - } - } - else { - for(i = 0; i < 3; i++) { - for(j = 0; j < 3; j++) { - index = (y + i)*fpitch + (x + j); - interpol = log(2 + pow(image[index].red / Lmax, biasP) * 8); - L = pade_log(image[index].red);// log(image[index].red + 1) - image[index].red = (float)((L / interpol) / divider); - } - } - } - } //x - } // y - - /** - Normal tone mapping of every pixel for the remaining right and bottom bands - */ - BYTE *bits; - - // right band - bits = (BYTE*)FreeImage_GetBits(dib); - for(y = 0; y < height; y++) { - FIRGBF *pixel = (FIRGBF*)bits; - for(x = max_width; x < width; x++) { - double Yw = pixel[x].red / avgLum; - Yw *= exposure; - interpol = log(2 + biasFunction(biasP, Yw / Lmax) * 8); - L = pade_log(Yw);// log(Yw + 1) - pixel[x].red = (float)((L / interpol) / divider); - } - // next line - bits += pitch; - } - // bottom band - bits = (BYTE*)FreeImage_GetBits(dib); - for(y = max_height; y < height; y++) { - FIRGBF *pixel = (FIRGBF*)bits; - for(x = 0; x < max_width; x++) { - double Yw = pixel[x].red / avgLum; - Yw *= exposure; - interpol = log(2 + biasFunction(biasP, Yw / Lmax) * 8); - L = pade_log(Yw);// log(Yw + 1) - pixel[x].red = (float)((L / interpol) / divider); - } - // next line - bits += pitch; - } - -#endif // DRAGO03_FAST - - return TRUE; -} - -/** -Custom gamma correction based on the ITU-R BT.709 standard -@param dib RGBF image to be corrected -@param gammaval Gamma value (2.2 is a good default value) -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -REC709GammaCorrection(FIBITMAP *dib, const float gammaval) { - if(FreeImage_GetImageType(dib) != FIT_RGBF) - return FALSE; - - float slope = 4.5F; - float start = 0.018F; - - const float fgamma = (float)((0.45 / gammaval) * 2); - if(gammaval >= 2.1F) { - start = (float)(0.018 / ((gammaval - 2) * 7.5)); - slope = (float)(4.5 * ((gammaval - 2) * 7.5)); - } else if (gammaval <= 1.9F) { - start = (float)(0.018 * ((2 - gammaval) * 7.5)); - slope = (float)(4.5 / ((2 - gammaval) * 7.5)); - } - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - - BYTE *bits = (BYTE*)FreeImage_GetBits(dib); - for(unsigned y = 0; y < height; y++) { - float *pixel = (float*)bits; - for(unsigned x = 0; x < width; x++) { - for(int i = 0; i < 3; i++) { - *pixel = (*pixel <= start) ? *pixel * slope : (1.099F * pow(*pixel, fgamma) - 0.099F); - pixel++; - } - } - bits += pitch; - } - - return TRUE; -} - -// ---------------------------------------------------------- -// Main algorithm -// ---------------------------------------------------------- - -/** -Apply the Adaptive Logarithmic Mapping operator to a HDR image and convert to 24-bit RGB -@param src Input RGB16 or RGB[A]F image -@param gamma Gamma correction (gamma > 0). 1 means no correction, 2.2 in the original paper. -@param exposure Exposure parameter (0 means no correction, 0 in the original paper) -@return Returns a 24-bit RGB image if successful, returns NULL otherwise -*/ -FIBITMAP* DLL_CALLCONV -FreeImage_TmoDrago03(FIBITMAP *src, double gamma, double exposure) { - float maxLum, minLum, avgLum; - - if(!FreeImage_HasPixels(src)) return NULL; - - // working RGBF variable - FIBITMAP *dib = NULL; - - dib = FreeImage_ConvertToRGBF(src); - if(!dib) return NULL; - - // default algorithm parameters - const float biasParam = 0.85F; - const float expoParam = (float)pow(2.0, exposure); //default exposure is 1, 2^0 - - // convert to Yxy - ConvertInPlaceRGBFToYxy(dib); - // get the luminance - LuminanceFromYxy(dib, &maxLum, &minLum, &avgLum); - // perform the tone mapping - ToneMappingDrago03(dib, maxLum, avgLum, biasParam, expoParam); - // convert back to RGBF - ConvertInPlaceYxyToRGBF(dib); - if(gamma != 1) { - // perform gamma correction - REC709GammaCorrection(dib, (float)gamma); - } - // clamp image highest values to display white, then convert to 24-bit RGB - FIBITMAP *dst = ClampConvertRGBFTo24(dib); - - // clean-up and return - FreeImage_Unload(dib); - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - return dst; -} diff --git a/plugins/AdvaImg/src/FreeImage/tmoFattal02.cpp b/plugins/AdvaImg/src/FreeImage/tmoFattal02.cpp deleted file mode 100644 index 27448fce8a..0000000000 --- a/plugins/AdvaImg/src/FreeImage/tmoFattal02.cpp +++ /dev/null @@ -1,689 +0,0 @@ -// ========================================================== -// Tone mapping operator (Fattal, 2002) -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "ToneMapping.h" - -// ---------------------------------------------------------- -// Gradient domain HDR compression -// Reference: -// [1] R. Fattal, D. Lischinski, and M.Werman, -// Gradient domain high dynamic range compression, -// ACM Transactions on Graphics, special issue on Proc. of ACM SIGGRAPH 2002, -// San Antonio, Texas, vol. 21(3), pp. 257-266, 2002. -// ---------------------------------------------------------- - -static const float EPSILON = 1e-4F; - -/** -Performs a 5 by 5 gaussian filtering using two 1D convolutions, -followed by a subsampling by 2. -@param dib Input image -@return Returns a blurred image of size SIZE(dib)/2 -@see GaussianPyramid -*/ -static FIBITMAP* GaussianLevel5x5(FIBITMAP *dib) { - FIBITMAP *h_dib = NULL, *v_dib = NULL, *dst = NULL; - float *src_pixel, *dst_pixel; - - try { - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - if(image_type != FIT_FLOAT) throw(1); - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - - h_dib = FreeImage_AllocateT(image_type, width, height); - v_dib = FreeImage_AllocateT(image_type, width, height); - if(!h_dib || !v_dib) throw(1); - - const unsigned pitch = FreeImage_GetPitch(dib) / sizeof(float); - - // horizontal convolution dib -> h_dib - - src_pixel = (float*)FreeImage_GetBits(dib); - dst_pixel = (float*)FreeImage_GetBits(h_dib); - - for(unsigned y = 0; y < height; y++) { - // work on line y - for(unsigned x = 2; x < width - 2; x++) { - dst_pixel[x] = src_pixel[x-2] + src_pixel[x+2] + 4 * (src_pixel[x-1] + src_pixel[x+1]) + 6 * src_pixel[x]; - dst_pixel[x] /= 16; - } - // boundary mirroring - dst_pixel[0] = (2 * src_pixel[2] + 8 * src_pixel[1] + 6 * src_pixel[0]) / 16; - dst_pixel[1] = (src_pixel[3] + 4 * (src_pixel[0] + src_pixel[2]) + 7 * src_pixel[1]) / 16; - dst_pixel[width-2] = (src_pixel[width-4] + 5 * src_pixel[width-1] + 4 * src_pixel[width-3] + 6 * src_pixel[width-2]) / 16; - dst_pixel[width-1] = (src_pixel[width-3] + 5 * src_pixel[width-2] + 10 * src_pixel[width-1]) / 16; - - // next line - src_pixel += pitch; - dst_pixel += pitch; - } - - // vertical convolution h_dib -> v_dib - - src_pixel = (float*)FreeImage_GetBits(h_dib); - dst_pixel = (float*)FreeImage_GetBits(v_dib); - - for(unsigned x = 0; x < width; x++) { - // work on column x - for(unsigned y = 2; y < height - 2; y++) { - const unsigned index = y*pitch + x; - dst_pixel[index] = src_pixel[index-2*pitch] + src_pixel[index+2*pitch] + 4 * (src_pixel[index-pitch] + src_pixel[index+pitch]) + 6 * src_pixel[index]; - dst_pixel[index] /= 16; - } - // boundary mirroring - dst_pixel[x] = (2 * src_pixel[x+2*pitch] + 8 * src_pixel[x+pitch] + 6 * src_pixel[x]) / 16; - dst_pixel[x+pitch] = (src_pixel[x+3*pitch] + 4 * (src_pixel[x] + src_pixel[x+2*pitch]) + 7 * src_pixel[x+pitch]) / 16; - dst_pixel[(height-2)*pitch+x] = (src_pixel[(height-4)*pitch+x] + 5 * src_pixel[(height-1)*pitch+x] + 4 * src_pixel[(height-3)*pitch+x] + 6 * src_pixel[(height-2)*pitch+x]) / 16; - dst_pixel[(height-1)*pitch+x] = (src_pixel[(height-3)*pitch+x] + 5 * src_pixel[(height-2)*pitch+x] + 10 * src_pixel[(height-1)*pitch+x]) / 16; - } - - FreeImage_Unload(h_dib); h_dib = NULL; - - // perform downsampling - - dst = FreeImage_Rescale(v_dib, width/2, height/2, FILTER_BILINEAR); - - FreeImage_Unload(v_dib); - - return dst; - - } catch(int) { - if(h_dib) FreeImage_Unload(h_dib); - if(v_dib) FreeImage_Unload(v_dib); - if(dst) FreeImage_Unload(dst); - return NULL; - } -} - -/** -Compute a Gaussian pyramid using the specified number of levels. -@param H Original bitmap -@param pyramid Resulting pyramid array -@param nlevels Number of resolution levels -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL GaussianPyramid(FIBITMAP *H, FIBITMAP **pyramid, int nlevels) { - try { - // first level is the original image - pyramid[0] = FreeImage_Clone(H); - if(pyramid[0] == NULL) throw(1); - // compute next levels - for(int k = 1; k < nlevels; k++) { - pyramid[k] = GaussianLevel5x5(pyramid[k-1]); - if(pyramid[k] == NULL) throw(1); - } - return TRUE; - } catch(int) { - for(int k = 0; k < nlevels; k++) { - if(pyramid[k] != NULL) { - FreeImage_Unload(pyramid[k]); - pyramid[k] = NULL; - } - } - return FALSE; - } -} - -/** -Compute the gradient magnitude of an input image H using central differences, -and returns the average gradient. -@param H Input image -@param avgGrad [out] Average gradient -@param k Level number -@return Returns the gradient magnitude if successful, returns NULL otherwise -@see GradientPyramid -*/ -static FIBITMAP* GradientLevel(FIBITMAP *H, float *avgGrad, int k) { - FIBITMAP *G = NULL; - - try { - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(H); - if(image_type != FIT_FLOAT) throw(1); - - const unsigned width = FreeImage_GetWidth(H); - const unsigned height = FreeImage_GetHeight(H); - - G = FreeImage_AllocateT(image_type, width, height); - if(!G) throw(1); - - const unsigned pitch = FreeImage_GetPitch(H) / sizeof(float); - - const float divider = (float)(1 << (k + 1)); - float average = 0; - - float *src_pixel = (float*)FreeImage_GetBits(H); - float *dst_pixel = (float*)FreeImage_GetBits(G); - - for(unsigned y = 0; y < height; y++) { - const unsigned n = (y == 0 ? 0 : y-1); - const unsigned s = (y+1 == height ? y : y+1); - for(unsigned x = 0; x < width; x++) { - const unsigned w = (x == 0 ? 0 : x-1); - const unsigned e = (x+1 == width ? x : x+1); - // central difference - const float gx = (src_pixel[y*pitch+e] - src_pixel[y*pitch+w]) / divider; // [Hk(x+1, y) - Hk(x-1, y)] / 2**(k+1) - const float gy = (src_pixel[s*pitch+x] - src_pixel[n*pitch+x]) / divider; // [Hk(x, y+1) - Hk(x, y-1)] / 2**(k+1) - // gradient - dst_pixel[x] = sqrt(gx*gx + gy*gy); - // average gradient - average += dst_pixel[x]; - } - // next line - dst_pixel += pitch; - } - - *avgGrad = average / (width * height); - - return G; - - } catch(int) { - if(G) FreeImage_Unload(G); - return NULL; - } -} - -/** -Calculate gradient magnitude and its average value on each pyramid level -@param pyramid Gaussian pyramid (nlevels levels) -@param nlevels Number of levels -@param gradients [out] Gradient pyramid (nlevels levels) -@param avgGrad [out] Average gradient on each level (array of size nlevels) -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL GradientPyramid(FIBITMAP **pyramid, int nlevels, FIBITMAP **gradients, float *avgGrad) { - try { - for(int k = 0; k < nlevels; k++) { - FIBITMAP *Hk = pyramid[k]; - gradients[k] = GradientLevel(Hk, &avgGrad[k], k); - if(gradients[k] == NULL) throw(1); - } - return TRUE; - } catch(int) { - for(int k = 0; k < nlevels; k++) { - if(gradients[k] != NULL) { - FreeImage_Unload(gradients[k]); - gradients[k] = NULL; - } - } - return FALSE; - } -} - -/** -Compute the gradient attenuation function PHI(x, y) -@param gradients Gradient pyramid (nlevels levels) -@param avgGrad Average gradient on each level (array of size nlevels) -@param nlevels Number of levels -@param alpha Parameter alpha in the paper -@param beta Parameter beta in the paper -@return Returns the attenuation matrix Phi if successful, returns NULL otherwise -*/ -static FIBITMAP* PhiMatrix(FIBITMAP **gradients, float *avgGrad, int nlevels, float alpha, float beta) { - float *src_pixel, *dst_pixel; - FIBITMAP **phi = NULL; - - try { - phi = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*)); - if(!phi) throw(1); - memset(phi, 0, nlevels * sizeof(FIBITMAP*)); - - for(int k = nlevels-1; k >= 0; k--) { - // compute phi(k) - - FIBITMAP *Gk = gradients[k]; - - const unsigned width = FreeImage_GetWidth(Gk); - const unsigned height = FreeImage_GetHeight(Gk); - const unsigned pitch = FreeImage_GetPitch(Gk) / sizeof(float); - - // parameter alpha is 0.1 times the average gradient magnitude - // also, note the factor of 2**k in the denominator; - // that is there to correct for the fact that an average gradient avgGrad(H) over 2**k pixels - // in the original image will appear as a gradient grad(Hk) = 2**k*avgGrad(H) over a single pixel in Hk. - float ALPHA = alpha * avgGrad[k] * (float)((int)1 << k); - if(ALPHA == 0) ALPHA = EPSILON; - - phi[k] = FreeImage_AllocateT(FIT_FLOAT, width, height); - if(!phi[k]) throw(1); - - src_pixel = (float*)FreeImage_GetBits(Gk); - dst_pixel = (float*)FreeImage_GetBits(phi[k]); - for(unsigned y = 0; y < height; y++) { - for(unsigned x = 0; x < width; x++) { - // compute (alpha / grad) * (grad / alpha) ** beta - const float v = src_pixel[x] / ALPHA; - const float value = (float)pow((float)v, (float)(beta-1)); - dst_pixel[x] = (value > 1) ? 1 : value; - } - // next line - src_pixel += pitch; - dst_pixel += pitch; - } - - if(k < nlevels-1) { - // compute PHI(k) = L( PHI(k+1) ) * phi(k) - FIBITMAP *L = FreeImage_Rescale(phi[k+1], width, height, FILTER_BILINEAR); - if(!L) throw(1); - - src_pixel = (float*)FreeImage_GetBits(L); - dst_pixel = (float*)FreeImage_GetBits(phi[k]); - for(unsigned y = 0; y < height; y++) { - for(unsigned x = 0; x < width; x++) { - dst_pixel[x] *= src_pixel[x]; - } - // next line - src_pixel += pitch; - dst_pixel += pitch; - } - - FreeImage_Unload(L); - - // PHI(k+1) is no longer needed - FreeImage_Unload(phi[k+1]); - phi[k+1] = NULL; - } - - // next level - } - - // get the final result and return - FIBITMAP *dst = phi[0]; - - free(phi); - - return dst; - - } catch(int) { - if(phi) { - for(int k = nlevels-1; k >= 0; k--) { - if(phi[k]) FreeImage_Unload(phi[k]); - } - free(phi); - } - return NULL; - } -} - -/** -Compute gradients in x and y directions, attenuate them with the attenuation matrix, -then compute the divergence div G from the attenuated gradient. -@param H Normalized luminance -@param PHI Attenuation matrix -@return Returns the divergence matrix if successful, returns NULL otherwise -*/ -static FIBITMAP* Divergence(FIBITMAP *H, FIBITMAP *PHI) { - FIBITMAP *Gx = NULL, *Gy = NULL, *divG = NULL; - float *phi, *h, *gx, *gy, *divg; - - try { - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(H); - if(image_type != FIT_FLOAT) throw(1); - - const unsigned width = FreeImage_GetWidth(H); - const unsigned height = FreeImage_GetHeight(H); - - Gx = FreeImage_AllocateT(image_type, width, height); - if(!Gx) throw(1); - Gy = FreeImage_AllocateT(image_type, width, height); - if(!Gy) throw(1); - - const unsigned pitch = FreeImage_GetPitch(H) / sizeof(float); - - // perform gradient attenuation - - phi = (float*)FreeImage_GetBits(PHI); - h = (float*)FreeImage_GetBits(H); - gx = (float*)FreeImage_GetBits(Gx); - gy = (float*)FreeImage_GetBits(Gy); - - for(unsigned y = 0; y < height; y++) { - const unsigned s = (y+1 == height ? y : y+1); - for(unsigned x = 0; x < width; x++) { - const unsigned e = (x+1 == width ? x : x+1); - // forward difference - const unsigned index = y*pitch + x; - const float phi_xy = phi[index]; - const float h_xy = h[index]; - gx[x] = (h[y*pitch+e] - h_xy) * phi_xy; // [H(x+1, y) - H(x, y)] * PHI(x, y) - gy[x] = (h[s*pitch+x] - h_xy) * phi_xy; // [H(x, y+1) - H(x, y)] * PHI(x, y) - } - // next line - gx += pitch; - gy += pitch; - } - - // calculate the divergence - - divG = FreeImage_AllocateT(image_type, width, height); - if(!divG) throw(1); - - gx = (float*)FreeImage_GetBits(Gx); - gy = (float*)FreeImage_GetBits(Gy); - divg = (float*)FreeImage_GetBits(divG); - - for(unsigned y = 0; y < height; y++) { - for(unsigned x = 0; x < width; x++) { - // backward difference approximation - // divG = Gx(x, y) - Gx(x-1, y) + Gy(x, y) - Gy(x, y-1) - const unsigned index = y*pitch + x; - divg[index] = gx[index] + gy[index]; - if(x > 0) divg[index] -= gx[index-1]; - if(y > 0) divg[index] -= gy[index-pitch]; - } - } - - // no longer needed ... - FreeImage_Unload(Gx); - FreeImage_Unload(Gy); - - // return the divergence - return divG; - - } catch(int) { - if(Gx) FreeImage_Unload(Gx); - if(Gy) FreeImage_Unload(Gy); - if(divG) FreeImage_Unload(divG); - return NULL; - } -} - -/** -Given the luminance channel, find max & min luminance values, -normalize to range 0..100 and take the logarithm. -@param Y Image luminance -@return Returns the normalized luminance H if successful, returns NULL otherwise -*/ -static FIBITMAP* LogLuminance(FIBITMAP *Y) { - FIBITMAP *H = NULL; - - try { - // get the luminance channel - FIBITMAP *H = FreeImage_Clone(Y); - if(!H) throw(1); - - const unsigned width = FreeImage_GetWidth(H); - const unsigned height = FreeImage_GetHeight(H); - const unsigned pitch = FreeImage_GetPitch(H); - - // find max & min luminance values - float maxLum = -1e20F, minLum = 1e20F; - - BYTE *bits = (BYTE*)FreeImage_GetBits(H); - for(unsigned y = 0; y < height; y++) { - const float *pixel = (float*)bits; - for(unsigned x = 0; x < width; x++) { - const float value = pixel[x]; - maxLum = (maxLum < value) ? value : maxLum; // max Luminance in the scene - minLum = (minLum < value) ? minLum : value; // min Luminance in the scene - } - // next line - bits += pitch; - } - if(maxLum == minLum) throw(1); - - // normalize to range 0..100 and take the logarithm - const float scale = 100.F / (maxLum - minLum); - bits = (BYTE*)FreeImage_GetBits(H); - for(unsigned y = 0; y < height; y++) { - float *pixel = (float*)bits; - for(unsigned x = 0; x < width; x++) { - const float value = (pixel[x] - minLum) * scale; - pixel[x] = log(value + EPSILON); - } - // next line - bits += pitch; - } - - return H; - - } catch(int) { - if(H) FreeImage_Unload(H); - return NULL; - } -} - -/** -Given a normalized luminance, perform exponentiation and recover the log compressed image -@param Y Input/Output luminance image -*/ -static void ExpLuminance(FIBITMAP *Y) { - const unsigned width = FreeImage_GetWidth(Y); - const unsigned height = FreeImage_GetHeight(Y); - const unsigned pitch = FreeImage_GetPitch(Y); - - BYTE *bits = (BYTE*)FreeImage_GetBits(Y); - for(unsigned y = 0; y < height; y++) { - float *pixel = (float*)bits; - for(unsigned x = 0; x < width; x++) { - pixel[x] = exp(pixel[x]) - EPSILON; - } - bits += pitch; - } -} - -// -------------------------------------------------------------------------- - -/** -Gradient Domain HDR tone mapping operator -@param Y Image luminance values -@param alpha Parameter alpha of the paper (suggested value is 0.1) -@param beta Parameter beta of the paper (suggested value is between 0.8 and 0.9) -@return returns the tone mapped luminance -*/ -static FIBITMAP* tmoFattal02(FIBITMAP *Y, float alpha, float beta) { - const unsigned MIN_PYRAMID_SIZE = 32; // minimun size (width or height) of the coarsest level of the pyramid - - FIBITMAP *H = NULL; - FIBITMAP **pyramid = NULL; - FIBITMAP **gradients = NULL; - FIBITMAP *phy = NULL; - FIBITMAP *divG = NULL; - FIBITMAP *U = NULL; - float *avgGrad = NULL; - - int k; - int nlevels = 0; - - try { - // get the normalized luminance - FIBITMAP *H = LogLuminance(Y); - if(!H) throw(1); - - // get the number of levels for the pyramid - const unsigned width = FreeImage_GetWidth(H); - const unsigned height = FreeImage_GetHeight(H); - unsigned minsize = MIN(width, height); - while(minsize >= MIN_PYRAMID_SIZE) { - nlevels++; - minsize /= 2; - } - - // create the Gaussian pyramid - pyramid = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*)); - if(!pyramid) throw(1); - memset(pyramid, 0, nlevels * sizeof(FIBITMAP*)); - - if(!GaussianPyramid(H, pyramid, nlevels)) throw(1); - - // calculate gradient magnitude and its average value on each pyramid level - gradients = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*)); - if(!gradients) throw(1); - memset(gradients, 0, nlevels * sizeof(FIBITMAP*)); - avgGrad = (float*)malloc(nlevels * sizeof(float)); - if(!avgGrad) throw(1); - - if(!GradientPyramid(pyramid, nlevels, gradients, avgGrad)) throw(1); - - // free the Gaussian pyramid - for(k = 0; k < nlevels; k++) { - if(pyramid[k]) FreeImage_Unload(pyramid[k]); - } - free(pyramid); pyramid = NULL; - - // compute the gradient attenuation function PHI(x, y) - phy = PhiMatrix(gradients, avgGrad, nlevels, alpha, beta); - if(!phy) throw(1); - - // free the gradient pyramid - for(k = 0; k < nlevels; k++) { - if(gradients[k]) FreeImage_Unload(gradients[k]); - } - free(gradients); gradients = NULL; - free(avgGrad); avgGrad = NULL; - - // compute gradients in x and y directions, attenuate them with the attenuation matrix, - // then compute the divergence div G from the attenuated gradient. - divG = Divergence(H, phy); - if(!divG) throw(1); - - // H & phy no longer needed - FreeImage_Unload(H); H = NULL; - FreeImage_Unload(phy); phy = NULL; - - // solve the PDE (Poisson equation) using a multigrid solver and 3 cycles - FIBITMAP *U = FreeImage_MultigridPoissonSolver(divG, 3); - if(!U) throw(1); - - FreeImage_Unload(divG); - - // perform exponentiation and recover the log compressed image - ExpLuminance(U); - - return U; - - } catch(int) { - if(H) FreeImage_Unload(H); - if(pyramid) { - for(int i = 0; i < nlevels; i++) { - if(pyramid[i]) FreeImage_Unload(pyramid[i]); - } - free(pyramid); - } - if(gradients) { - for(int i = 0; i < nlevels; i++) { - if(gradients[i]) FreeImage_Unload(gradients[i]); - } - free(gradients); - } - if(avgGrad) free(avgGrad); - if(phy) FreeImage_Unload(phy); - if(divG) FreeImage_Unload(divG); - if(U) FreeImage_Unload(U); - - return NULL; - } -} - -// ---------------------------------------------------------- -// Main algorithm -// ---------------------------------------------------------- - -/** -Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB -@param dib Input RGBF / RGB16 image -@param color_saturation Color saturation (s parameter in the paper) in [0.4..0.6] -@param attenuation Atenuation factor (beta parameter in the paper) in [0.8..0.9] -@return Returns a 24-bit RGB image if successful, returns NULL otherwise -*/ -FIBITMAP* DLL_CALLCONV -FreeImage_TmoFattal02(FIBITMAP *dib, double color_saturation, double attenuation) { - const float alpha = 0.1F; // parameter alpha = 0.1 - const float beta = (float)MAX(0.8, MIN(0.9, attenuation)); // parameter beta = [0.8..0.9] - const float s = (float)MAX(0.4, MIN(0.6, color_saturation));// exponent s controls color saturation = [0.4..0.6] - - FIBITMAP *src = NULL; - FIBITMAP *Yin = NULL; - FIBITMAP *Yout = NULL; - FIBITMAP *dst = NULL; - - if(!FreeImage_HasPixels(dib)) return NULL; - - try { - - // convert to RGBF - src = FreeImage_ConvertToRGBF(dib); - if(!src) throw(1); - - // get the luminance channel - Yin = ConvertRGBFToY(src); - if(!Yin) throw(1); - - // perform the tone mapping - Yout = tmoFattal02(Yin, alpha, beta); - if(!Yout) throw(1); - - // clip low and high values and normalize to [0..1] - //NormalizeY(Yout, 0.001F, 0.995F); - NormalizeY(Yout, 0, 1); - - // compress the dynamic range - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - const unsigned rgb_pitch = FreeImage_GetPitch(src); - const unsigned y_pitch = FreeImage_GetPitch(Yin); - - BYTE *bits = (BYTE*)FreeImage_GetBits(src); - BYTE *bits_yin = (BYTE*)FreeImage_GetBits(Yin); - BYTE *bits_yout = (BYTE*)FreeImage_GetBits(Yout); - - for(unsigned y = 0; y < height; y++) { - float *Lin = (float*)bits_yin; - float *Lout = (float*)bits_yout; - float *color = (float*)bits; - for(unsigned x = 0; x < width; x++) { - for(unsigned c = 0; c < 3; c++) { - *color = (Lin[x] > 0) ? pow(*color/Lin[x], s) * Lout[x] : 0; - color++; - } - } - bits += rgb_pitch; - bits_yin += y_pitch; - bits_yout += y_pitch; - } - - // not needed anymore - FreeImage_Unload(Yin); Yin = NULL; - FreeImage_Unload(Yout); Yout = NULL; - - // clamp image highest values to display white, then convert to 24-bit RGB - dst = ClampConvertRGBFTo24(src); - - // clean-up and return - FreeImage_Unload(src); src = NULL; - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, dib); - - return dst; - - } catch(int) { - if(src) FreeImage_Unload(src); - if(Yin) FreeImage_Unload(Yin); - if(Yout) FreeImage_Unload(Yout); - return NULL; - } -} diff --git a/plugins/AdvaImg/src/FreeImage/tmoReinhard05.cpp b/plugins/AdvaImg/src/FreeImage/tmoReinhard05.cpp deleted file mode 100644 index 64607dd5aa..0000000000 --- a/plugins/AdvaImg/src/FreeImage/tmoReinhard05.cpp +++ /dev/null @@ -1,260 +0,0 @@ -// ========================================================== -// Tone mapping operator (Reinhard, 2005) -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// 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 your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "ToneMapping.h" - -// ---------------------------------------------------------- -// Global and/or local tone mapping operator -// References: -// [1] Erik Reinhard and Kate Devlin, 'Dynamic Range Reduction Inspired by Photoreceptor Physiology', -// IEEE Transactions on Visualization and Computer Graphics, 11(1), Jan/Feb 2005. -// [2] Erik Reinhard, 'Parameter estimation for photographic tone reproduction', -// Journal of Graphics Tools, vol. 7, no. 1, pp. 45–51, 2003. -// ---------------------------------------------------------- - -/** -Tone mapping operator -@param dib Input / Output RGBF image -@param Y Input luminance image version of dib -@param f Overall intensity in range [-8:8] : default to 0 -@param m Contrast in range [0.3:1) : default to 0 -@param a Adaptation in range [0:1] : default to 1 -@param c Color correction in range [0:1] : default to 0 -@return Returns TRUE if successful, returns FALSE otherwise -@see LuminanceFromY -*/ -static BOOL -ToneMappingReinhard05(FIBITMAP *dib, FIBITMAP *Y, float f, float m, float a, float c) { - float Cav[3]; // channel average - float Lav = 0; // average luminance - float Llav = 0; // log average luminance - float minLum = 1; // min luminance - float maxLum = 1; // max luminance - - float L; // pixel luminance - float I_g, I_l; // global and local light adaptation - float I_a; // interpolated pixel light adaptation - float k; // key (low-key means overall dark image, high-key means overall light image) - - // check input parameters - - if((FreeImage_GetImageType(dib) != FIT_RGBF) || (FreeImage_GetImageType(Y) != FIT_FLOAT)) { - return FALSE; - } - - if(f < -8) f = -8; if(f > 8) f = 8; - if(m < 0) m = 0; if(m > 1) m = 1; - if(a < 0) a = 0; if(a > 1) a = 1; - if(c < 0) c = 0; if(c > 1) c = 1; - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - - const unsigned dib_pitch = FreeImage_GetPitch(dib); - const unsigned y_pitch = FreeImage_GetPitch(Y); - - int i; - unsigned x, y; - BYTE *bits = NULL, *Ybits = NULL; - - // get statistics about the data (but only if its really needed) - - f = exp(-f); - if((m == 0) || (a != 1) && (c != 1)) { - // avoid these calculations if its not needed after ... - LuminanceFromY(Y, &maxLum, &minLum, &Lav, &Llav); - k = (log(maxLum) - Llav) / (log(maxLum) - log(minLum)); - if(k < 0) { - // pow(k, 1.4F) is undefined ... - // there's an ambiguity about the calculation of Llav between Reinhard papers and the various implementations ... - // try another world adaptation luminance formula using instead 'worldLum = log(Llav)' - k = (log(maxLum) - log(Llav)) / (log(maxLum) - log(minLum)); - if(k < 0) m = 0.3F; - } - } - m = (m > 0) ? m : (float)(0.3 + 0.7 * pow(k, 1.4F)); - - float max_color = -1e6F; - float min_color = +1e6F; - - // tone map image - - bits = (BYTE*)FreeImage_GetBits(dib); - Ybits = (BYTE*)FreeImage_GetBits(Y); - - if((a == 1) && (c == 0)) { - // when using default values, use a fastest code - - for(y = 0; y < height; y++) { - float *Y = (float*)Ybits; - float *color = (float*)bits; - - for(x = 0; x < width; x++) { - I_a = Y[x]; // luminance(x, y) - for (i = 0; i < 3; i++) { - *color /= ( *color + pow(f * I_a, m) ); - - max_color = (*color > max_color) ? *color : max_color; - min_color = (*color < min_color) ? *color : min_color; - - color++; - } - } - // next line - bits += dib_pitch; - Ybits += y_pitch; - } - } else { - // complete algorithm - - // channel averages - - Cav[0] = Cav[1] = Cav[2] = 0; - if((a != 1) && (c != 0)) { - // channel averages are not needed when (a == 1) or (c == 0) - bits = (BYTE*)FreeImage_GetBits(dib); - for(y = 0; y < height; y++) { - float *color = (float*)bits; - for(x = 0; x < width; x++) { - for(i = 0; i < 3; i++) { - Cav[i] += *color; - color++; - } - } - // next line - bits += dib_pitch; - } - const float image_size = (float)width * height; - for(i = 0; i < 3; i++) { - Cav[i] /= image_size; - } - } - - // perform tone mapping - - bits = (BYTE*)FreeImage_GetBits(dib); - for(y = 0; y < height; y++) { - const float *Y = (float*)Ybits; - float *color = (float*)bits; - - for(x = 0; x < width; x++) { - L = Y[x]; // luminance(x, y) - for (i = 0; i < 3; i++) { - I_l = c * *color + (1-c) * L; - I_g = c * Cav[i] + (1-c) * Lav; - I_a = a * I_l + (1-a) * I_g; - *color /= ( *color + pow(f * I_a, m) ); - - max_color = (*color > max_color) ? *color : max_color; - min_color = (*color < min_color) ? *color : min_color; - - color++; - } - } - // next line - bits += dib_pitch; - Ybits += y_pitch; - } - } - - // normalize intensities - - if(max_color != min_color) { - bits = (BYTE*)FreeImage_GetBits(dib); - const float range = max_color - min_color; - for(y = 0; y < height; y++) { - float *color = (float*)bits; - for(x = 0; x < width; x++) { - for(i = 0; i < 3; i++) { - *color = (*color - min_color) / range; - color++; - } - } - // next line - bits += dib_pitch; - } - } - - return TRUE; -} - -// ---------------------------------------------------------- -// Main algorithm -// ---------------------------------------------------------- - -/** -Apply the global/local tone mapping operator to a RGBF image and convert to 24-bit RGB<br> -User parameters control intensity, contrast, and level of adaptation -@param src Input RGBF image -@param intensity Overall intensity in range [-8:8] : default to 0 -@param contrast Contrast in range [0.3:1) : default to 0 -@param adaptation Adaptation in range [0:1] : default to 1 -@param color_correction Color correction in range [0:1] : default to 0 -@return Returns a 24-bit RGB image if successful, returns NULL otherwise -*/ -FIBITMAP* DLL_CALLCONV -FreeImage_TmoReinhard05Ex(FIBITMAP *src, double intensity, double contrast, double adaptation, double color_correction) { - if(!FreeImage_HasPixels(src)) return NULL; - - // working RGBF variable - FIBITMAP *dib = NULL, *Y = NULL; - - dib = FreeImage_ConvertToRGBF(src); - if(!dib) return NULL; - - // get the Luminance channel - Y = ConvertRGBFToY(dib); - if(!Y) { - FreeImage_Unload(dib); - return NULL; - } - - // perform the tone mapping - ToneMappingReinhard05(dib, Y, (float)intensity, (float)contrast, (float)adaptation, (float)color_correction); - // not needed anymore - FreeImage_Unload(Y); - // clamp image highest values to display white, then convert to 24-bit RGB - FIBITMAP *dst = ClampConvertRGBFTo24(dib); - - // clean-up and return - FreeImage_Unload(dib); - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - return dst; -} - -/** -Apply the global tone mapping operator to a RGBF image and convert to 24-bit RGB<br> -User parameters control intensity and contrast -@param src Input RGBF image -@param intensity Overall intensity in range [-8:8] : default to 0 -@param contrast Contrast in range [0.3:1) : default to 0 -@return Returns a 24-bit RGB image if successful, returns NULL otherwise -*/ -FIBITMAP* DLL_CALLCONV -FreeImage_TmoReinhard05(FIBITMAP *src, double intensity, double contrast) { - return FreeImage_TmoReinhard05Ex(src, intensity, contrast, 1, 0); -} |