summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/FreeImage
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage')
-rw-r--r--plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp427
-rw-r--r--plugins/AdvaImg/src/FreeImage/ColorLookup.cpp337
-rw-r--r--plugins/AdvaImg/src/FreeImage/Conversion.cpp66
-rw-r--r--plugins/AdvaImg/src/FreeImage/ConversionType.cpp10
-rw-r--r--plugins/AdvaImg/src/FreeImage/FreeImageIO.cpp49
-rw-r--r--plugins/AdvaImg/src/FreeImage/LFPQuantizer.cpp208
-rw-r--r--plugins/AdvaImg/src/FreeImage/MNGHelper.cpp27
-rw-r--r--plugins/AdvaImg/src/FreeImage/MemoryIO.cpp4
-rw-r--r--plugins/AdvaImg/src/FreeImage/MultiPage.cpp22
-rw-r--r--plugins/AdvaImg/src/FreeImage/PixelAccess.cpp13
-rw-r--r--plugins/AdvaImg/src/FreeImage/Plugin.cpp22
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginEXR.cpp111
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginG3.cpp2
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginGIF.cpp13
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginHDR.cpp3
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginICO.cpp24
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp27
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginJP2.cpp29
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp27
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginJXR.cpp184
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginPFM.cpp31
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginPICT.cpp19
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginPNG.cpp442
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginPNM.cpp31
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginRAW.cpp250
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp46
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp62
-rw-r--r--plugins/AdvaImg/src/FreeImage/WuQuantizer.cpp53
28 files changed, 1801 insertions, 738 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp b/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp
index 2ba5539d4c..347ad1f3e5 100644
--- a/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp
+++ b/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp
@@ -36,10 +36,18 @@
#include "FreeImage.h"
#include "FreeImageIO.h"
#include "Utilities.h"
+#include "MapIntrospector.h"
#include "../Metadata/FreeImageTag.h"
-/** Constants for the BITMAPINFOHEADER::biCompression field */
+/**
+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
@@ -49,38 +57,66 @@
// Metadata definitions
// ----------------------------------------------------------
-// helper for map<key, value> where value is a pointer to a FreeImage tag
+/** 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*>
+/** helper for map<FREE_IMAGE_MDMODEL, TAGMAP*> */
typedef std::map<int, TAGMAP*> METADATAMAP;
-// helper for metadata iterator
+/** helper for metadata iterator */
FI_STRUCT (METADATAHEADER) {
- long pos; // current position when iterating the map
- TAGMAP *tagmap; // pointer to the tag map
+ long pos; //! current position when iterating the map
+ TAGMAP *tagmap; //! pointer to the tag map
};
// ----------------------------------------------------------
// FIBITMAP definition
// ----------------------------------------------------------
+/**
+FreeImage header structure
+*/
FI_STRUCT (FREEIMAGEHEADER) {
- FREE_IMAGE_TYPE type; // data type - bitmap, array of long, double, complex, etc
+ /** 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;
+ //@}
- RGBQUAD bkgnd_color; // background color used for RGB transparency
+ /** space to hold ICC profile */
+ FIICCPROFILE iccProfile;
- BOOL transparent; // why another table? for easy transparency table retrieval!
- int transparency_count; // transparency could be stored in the palette, which is better
- BYTE transparent_table[256];// overall, but it requires quite some changes and it will render
- // FreeImage_GetTransparencyTable obsolete in its current form;
- FIICCPROFILE iccProfile; // space to hold ICC profile
+ /** contains a list of metadata models attached to the bitmap */
+ METADATAMAP *metadata;
- METADATAMAP *metadata; // contains a list of metadata models attached to the bitmap
+ /** FALSE if the FIBITMAP only contains the header and no pixel data */
+ BOOL has_pixels;
- BOOL has_pixels; // FALSE if the FIBITMAP only contains the header and no pixel data
+ /** optionally contains a thumbnail attached to the bitmap */
+ FIBITMAP *thumbnail;
- FIBITMAP *thumbnail; // optionally contains a thumbnail attached to the bitmap
+ /**@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
};
@@ -89,10 +125,13 @@ FI_STRUCT (FREEIMAGEHEADER) {
// 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
+ 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
};
// ----------------------------------------------------------
@@ -155,40 +194,50 @@ void FreeImage_Aligned_Free(void* mem) {
#endif // _WIN32 || _WIN64
// ----------------------------------------------------------
-// DIB information functions
+// 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
-@param height
-@param bpp
-@param need_masks
-@see FreeImage_AllocateHeaderT
+@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_GetImageSizeHeader(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);
+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);
+ 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;
+ 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.
@@ -196,12 +245,7 @@ FreeImage_GetImageSizeHeader(BOOL header_only, unsigned width, unsigned height,
for the target compiler.
*/
const double FIBITMAP_MAX_MEMORY = (double)((size_t)-1) - 8 * FIBITMAP_ALIGNMENT;
- 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;
- }
+
if(dImageSize > FIBITMAP_MAX_MEMORY) {
// avoid possible overflow inside C allocation functions
return 0;
@@ -224,8 +268,33 @@ FreeImage_GetRGBMasks(FIBITMAP *dib) {
return FreeImage_HasRGBMasks(dib) ? (FREEIMAGERGBMASKS *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL;
}
-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) {
+/**
+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);
@@ -233,6 +302,12 @@ FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int
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;
@@ -302,7 +377,9 @@ FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int
// palette is aligned on a 16 bytes boundary
// pixels are aligned on a 16 bytes boundary
- size_t dib_size = FreeImage_GetImageSizeHeader(header_only, width, height, bpp, need_masks);
+ // 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)
@@ -317,12 +394,13 @@ FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int
// write out the FREEIMAGEHEADER
- FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)bitmap->data;
- fih->type = type;
+ FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)bitmap->data;
+
+ fih->type = type;
memset(&fih->bkgnd_color, 0, sizeof(RGBQUAD));
- fih->transparent = FALSE;
+ fih->transparent = FALSE;
fih->transparency_count = 0;
memset(fih->transparent_table, 0xff, 256);
@@ -331,9 +409,9 @@ FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int
// initialize FIICCPROFILE link
FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap);
- iccProfile->size = 0;
- iccProfile->data = 0;
- iccProfile->flags = 0;
+ iccProfile->size = 0;
+ iccProfile->data = 0;
+ iccProfile->flags = 0;
// initialize metadata models list
@@ -343,6 +421,11 @@ FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int
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);
@@ -385,18 +468,28 @@ FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int
}
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_AllocateHeaderT(header_only, FIT_BITMAP, width, height, bpp, red_mask, green_mask, 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_AllocateHeaderT(FALSE, FIT_BITMAP, width, height, bpp, red_mask, green_mask, 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_AllocateHeaderT(FALSE, type, width, height, bpp, red_mask, green_mask, blue_mask);
+ return FreeImage_AllocateBitmap(FALSE, NULL, 0, type, width, height, bpp, red_mask, green_mask, blue_mask);
}
void DLL_CALLCONV
@@ -404,8 +497,9 @@ FreeImage_Unload(FIBITMAP *dib) {
if (NULL != dib) {
if (NULL != dib->data) {
// delete possible icc profile ...
- if (FreeImage_GetICCProfile(dib)->data)
+ if (FreeImage_GetICCProfile(dib)->data) {
free(FreeImage_GetICCProfile(dib)->data);
+ }
// delete metadata models
METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
@@ -431,6 +525,7 @@ FreeImage_Unload(FIBITMAP *dib) {
// delete bitmap ...
FreeImage_Aligned_Free(dib->data);
}
+
free(dib); // ... and the wrapper
}
}
@@ -439,17 +534,22 @@ FreeImage_Unload(FIBITMAP *dib) {
FIBITMAP * DLL_CALLCONV
FreeImage_Clone(FIBITMAP *dib) {
- if(!dib) return NULL;
+ 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);
+ 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;
+ 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,
@@ -464,12 +564,14 @@ FreeImage_Clone(FIBITMAP *dib) {
METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata;
- // calculate the size of a FreeImage image
+ // 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_GetImageSizeHeader(header_only, width, height, bpp, need_masks);
+ 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);
@@ -515,6 +617,16 @@ FreeImage_Clone(FIBITMAP *dib) {
// 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;
}
@@ -523,6 +635,28 @@ FreeImage_Clone(FIBITMAP *dib) {
// ----------------------------------------------------------
+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;
@@ -589,15 +723,17 @@ FreeImage_GetColorType(FIBITMAP *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)) {
+ 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;
+ if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0)) {
+ return FIC_MINISWHITE;
+ }
}
return FIC_PALETTE;
@@ -611,16 +747,18 @@ FreeImage_GetColorType(FIBITMAP *dib) {
rgb = FreeImage_GetPalette(dib);
for (int i = 0; i < ncolors; i++) {
- if ((rgb->rgbRed != rgb->rgbGreen) || (rgb->rgbRed != rgb->rgbBlue))
+ 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)
+ if ((ncolors-i-1) != rgb->rgbRed) {
return FIC_PALETTE;
- else
+ } else {
minisblack = 0;
+ }
}
rgb++;
@@ -635,17 +773,20 @@ FreeImage_GetColorType(FIBITMAP *dib) {
case 32:
{
- if (FreeImage_GetICCProfile(dib)->flags & FIICC_COLOR_IS_CMYK)
+ 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;
+ for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
+ if (rgb[x].rgbReserved != 0xFF) {
+ return FIC_RGBALPHA;
+ }
+ }
}
return FIC_RGB;
}
@@ -687,7 +828,10 @@ FreeImage_GetRedMask(FIBITMAP *dib) {
case FIT_BITMAP:
// check for 16-bit RGB (565 or 555)
masks = FreeImage_GetRGBMasks(dib);
- return masks ? masks->red_mask : FI_RGBA_RED_MASK;
+ if (masks) {
+ return masks->red_mask;
+ }
+ return FreeImage_GetBPP(dib) >= 24 ? FI_RGBA_RED_MASK : 0;
default:
return 0;
}
@@ -701,7 +845,10 @@ FreeImage_GetGreenMask(FIBITMAP *dib) {
case FIT_BITMAP:
// check for 16-bit RGB (565 or 555)
masks = FreeImage_GetRGBMasks(dib);
- return masks ? masks->green_mask : FI_RGBA_GREEN_MASK;
+ if (masks) {
+ return masks->green_mask;
+ }
+ return FreeImage_GetBPP(dib) >= 24 ? FI_RGBA_GREEN_MASK : 0;
default:
return 0;
}
@@ -715,7 +862,10 @@ FreeImage_GetBlueMask(FIBITMAP *dib) {
case FIT_BITMAP:
// check for 16-bit RGB (565 or 555)
masks = FreeImage_GetRGBMasks(dib);
- return masks ? masks->blue_mask : FI_RGBA_BLUE_MASK;
+ if (masks) {
+ return masks->blue_mask;
+ }
+ return FreeImage_GetBPP(dib) >= 24 ? FI_RGBA_BLUE_MASK : 0;
default:
return 0;
}
@@ -967,7 +1117,11 @@ FreeImage_GetLine(FIBITMAP *dib) {
unsigned DLL_CALLCONV
FreeImage_GetPitch(FIBITMAP *dib) {
- return dib ? FreeImage_GetLine(dib) + 3 & ~3 : 0;
+ if(dib) {
+ FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)dib->data;
+ return fih->external_bits ? fih->external_pitch : (FreeImage_GetLine(dib) + 3 & ~3);
+ }
+ return 0;
}
unsigned DLL_CALLCONV
@@ -1011,7 +1165,9 @@ FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res) {
BITMAPINFOHEADER * DLL_CALLCONV
FreeImage_GetInfoHeader(FIBITMAP *dib) {
- if(!dib) return NULL;
+ 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;
@@ -1029,8 +1185,9 @@ FreeImage_GetInfo(FIBITMAP *dib) {
FIMETADATA * DLL_CALLCONV
FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag) {
- if(!dib)
+ if(!dib) {
return NULL;
+ }
// get the metadata model
METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
@@ -1072,8 +1229,9 @@ FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag
BOOL DLL_CALLCONV
FreeImage_FindNextMetadata(FIMETADATA *mdhandle, FITAG **tag) {
- if(!mdhandle)
+ if(!mdhandle) {
return FALSE;
+ }
METADATAHEADER *mdh = (METADATAHEADER *)mdhandle->data;
TAGMAP *tagmap = mdh->tagmap;
@@ -1115,7 +1273,9 @@ FreeImage_FindCloseMetadata(FIMETADATA *mdhandle) {
BOOL DLL_CALLCONV
FreeImage_CloneMetadata(FIBITMAP *dst, FIBITMAP *src) {
- if(!src || !dst) return FALSE;
+ if(!src || !dst) {
+ return FALSE;
+ }
// get metadata links
METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)src->data)->metadata;
@@ -1165,8 +1325,9 @@ FreeImage_CloneMetadata(FIBITMAP *dst, FIBITMAP *src) {
BOOL DLL_CALLCONV
FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag) {
- if(!dib)
+ if(!dib) {
return FALSE;
+ }
TAGMAP *tagmap = NULL;
@@ -1254,8 +1415,9 @@ FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key,
BOOL DLL_CALLCONV
FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG **tag) {
- if(!dib || !key || !tag)
+ if(!dib || !key || !tag) {
return FALSE;
+ }
TAGMAP *tagmap = NULL;
*tag = NULL;
@@ -1278,12 +1440,50 @@ FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key,
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)
+ if(!dib) {
return FALSE;
+ }
TAGMAP *tagmap = NULL;
@@ -1303,4 +1503,71 @@ FreeImage_GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP *dib) {
// ----------------------------------------------------------
+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/ColorLookup.cpp b/plugins/AdvaImg/src/FreeImage/ColorLookup.cpp
index 5f677eee5c..0f4435a725 100644
--- a/plugins/AdvaImg/src/FreeImage/ColorLookup.cpp
+++ b/plugins/AdvaImg/src/FreeImage/ColorLookup.cpp
@@ -26,10 +26,10 @@
// RGB color names ---------------------------------------------------------
typedef struct tagNamedColor {
- const char *name; // color name
- BYTE r; // red value
- BYTE g; // green value
- BYTE b; // blue value
+ const char *name; //! color name
+ BYTE r; //! red value
+ BYTE g; //! green value
+ BYTE b; //! blue value
} NamedColor;
// --------------------------------------------------------------------------
@@ -43,20 +43,21 @@ Helper function : perform a binary search on a color array
*/
static int
binsearch(const char *name, const NamedColor *color_array, int n) {
- int cond, low, mid, high;
+ 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;
+ 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;
}
/**
@@ -68,22 +69,24 @@ Perform a binary search on a color array
*/
static int
FreeImage_LookupNamedColor(const char *szColor, const NamedColor *color_array, int ncolors) {
- int i;
+ 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]))
+ if (isspace(szColor[i])) {
continue;
- if (isupper(szColor[i]))
- color[i] = (char)tolower(szColor[i]);
- else
+ }
+ if (isupper(szColor[i])) {
+ color[i] = (char)tolower(szColor[i]);
+ } else {
color[i] = szColor[i];
+ }
}
color[i] = 0;
- return (binsearch(color, color_array, ncolors));
+ return binsearch(color, color_array, ncolors);
}
// ==========================================================
@@ -595,153 +598,153 @@ FreeImage_LookupX11Color(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nB
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 },
- { "grey", 128, 128, 128 },
- { "green", 0, 128, 0 },
- { "greenyellow", 173, 255, 47 },
- { "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 }
+ { "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 }
};
diff --git a/plugins/AdvaImg/src/FreeImage/Conversion.cpp b/plugins/AdvaImg/src/FreeImage/Conversion.cpp
index 04cec65ab5..815057ad08 100644
--- a/plugins/AdvaImg/src/FreeImage/Conversion.cpp
+++ b/plugins/AdvaImg/src/FreeImage/Conversion.cpp
@@ -6,6 +6,7 @@
// - 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
//
@@ -372,7 +373,8 @@ FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize, int Palet
if( ReserveSize < 0 ) ReserveSize = 0;
if( ReserveSize > PaletteSize ) ReserveSize = PaletteSize;
if (FreeImage_HasPixels(dib)) {
- if (FreeImage_GetBPP(dib) == 24) {
+ const unsigned bpp = FreeImage_GetBPP(dib);
+ if((FreeImage_GetImageType(dib) == FIT_BITMAP) && (bpp == 24 || bpp == 32)) {
switch(quantize) {
case FIQ_WUQUANT :
{
@@ -387,9 +389,14 @@ FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize, int Palet
} 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;
@@ -402,6 +409,16 @@ FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize, int Palet
}
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;
+ }
}
}
}
@@ -412,26 +429,47 @@ FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize, int Palet
// ==========================================================
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) {
- FIBITMAP *dib = FreeImage_Allocate(width, height, bpp, red_mask, green_mask, blue_mask);
+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 (dib != NULL) {
- if (topdown) {
- for (int i = height - 1; i >= 0; --i) {
- memcpy(FreeImage_GetScanLine(dib, i), bits, FreeImage_GetLine(dib));
- bits += pitch;
- }
- } else {
- for (int i = 0; i < height; ++i) {
- memcpy(FreeImage_GetScanLine(dib, i), bits, FreeImage_GetLine(dib));
- bits += pitch;
- }
+ 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)) {
diff --git a/plugins/AdvaImg/src/FreeImage/ConversionType.cpp b/plugins/AdvaImg/src/FreeImage/ConversionType.cpp
index b537f72814..a2ca90ff9d 100644
--- a/plugins/AdvaImg/src/FreeImage/ConversionType.cpp
+++ b/plugins/AdvaImg/src/FreeImage/ConversionType.cpp
@@ -3,6 +3,7 @@
//
// Design and implementation by
// - Hervé Drolon (drolon@infonie.fr)
+// - Tanner Helland (tannerhelland@users.sf.net)
//
// This file is part of FreeImage 3
//
@@ -346,11 +347,13 @@ FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_line
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;
@@ -378,11 +381,13 @@ FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_line
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;
@@ -503,6 +508,7 @@ FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_line
dst = FreeImage_ConvertToRGBF(src);
break;
case FIT_RGBAF:
+ dst = FreeImage_ConvertToRGBAF(src);
break;
}
break;
@@ -582,11 +588,13 @@ FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_line
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;
@@ -618,6 +626,7 @@ FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_line
dst = FreeImage_ConvertToRGBF(src);
break;
case FIT_RGBAF:
+ dst = FreeImage_ConvertToRGBAF(src);
break;
}
break;
@@ -645,6 +654,7 @@ FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_line
case FIT_RGBA16:
break;
case FIT_RGBAF:
+ dst = FreeImage_ConvertToRGBAF(src);
break;
}
break;
diff --git a/plugins/AdvaImg/src/FreeImage/FreeImageIO.cpp b/plugins/AdvaImg/src/FreeImage/FreeImageIO.cpp
index f8cf7604eb..83394f049c 100644
--- a/plugins/AdvaImg/src/FreeImage/FreeImageIO.cpp
+++ b/plugins/AdvaImg/src/FreeImage/FreeImageIO.cpp
@@ -68,14 +68,18 @@ _MemoryReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
for(x = 0; x < count; x++) {
- //if there isnt size bytes left to read, set pos to eof and return a short count
- if( (mem_header->filelen - mem_header->curpos) < (long)size ) {
- mem_header->curpos = mem_header->filelen;
+ 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->curpos, size );
- mem_header->curpos += size;
+ memcpy( buffer, (char *)mem_header->data + mem_header->current_position, size );
+ mem_header->current_position += size;
buffer = (char *)buffer + size;
}
return x;
@@ -89,32 +93,32 @@ _MemoryWriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle)
FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
//double the data block size if we need to
- while( (mem_header->curpos + (long)(size*count)) >= mem_header->datalen ) {
+ 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->datalen & 0x40000000 ) {
+ if( mem_header->data_length & 0x40000000 ) {
//max 2G
- if( mem_header->datalen == 0x7FFFFFFF ) {
+ if( mem_header->data_length == 0x7FFFFFFF ) {
return 0;
}
newdatalen = 0x7FFFFFFF;
- } else if( mem_header->datalen == 0 ) {
+ } else if( mem_header->data_length == 0 ) {
//default to 4K if nothing yet
newdatalen = 4096;
} else {
//double size
- newdatalen = mem_header->datalen << 1;
+ newdatalen = mem_header->data_length << 1;
}
newdata = realloc( mem_header->data, newdatalen );
if( !newdata ) {
return 0;
}
mem_header->data = newdata;
- mem_header->datalen = newdatalen;
+ mem_header->data_length = newdatalen;
}
- memcpy( (char *)mem_header->data + mem_header->curpos, buffer, size*count );
- mem_header->curpos += size*count;
- if( mem_header->curpos > mem_header->filelen ) {
- mem_header->filelen = mem_header->curpos;
+ 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;
}
@@ -123,25 +127,28 @@ 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->curpos = offset;
+ mem_header->current_position = offset;
return 0;
}
break;
case SEEK_CUR:
- if( mem_header->curpos + offset >= 0 ) {
- mem_header->curpos += offset;
+ if( mem_header->current_position + offset >= 0 ) {
+ mem_header->current_position += offset;
return 0;
}
break;
case SEEK_END:
- if( mem_header->filelen + offset >= 0 ) {
- mem_header->curpos = mem_header->filelen + offset;
+ if( mem_header->file_length + offset >= 0 ) {
+ mem_header->current_position = mem_header->file_length + offset;
return 0;
}
break;
@@ -154,7 +161,7 @@ long DLL_CALLCONV
_MemoryTellProc(fi_handle handle) {
FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
- return mem_header->curpos;
+ return mem_header->current_position;
}
// ----------------------------------------------------------
diff --git a/plugins/AdvaImg/src/FreeImage/LFPQuantizer.cpp b/plugins/AdvaImg/src/FreeImage/LFPQuantizer.cpp
new file mode 100644
index 0000000000..8b592c30f1
--- /dev/null
+++ b/plugins/AdvaImg/src/FreeImage/LFPQuantizer.cpp
@@ -0,0 +1,208 @@
+// ==========================================================
+// 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
index a4c67a2abe..ed3664cf77 100644
--- a/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp
+++ b/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp
@@ -357,7 +357,6 @@ Retrieve the position of a chunk in a PNG stream
*/
static BOOL
mng_FindChunk(FIMEMORY *hPngMemory, BYTE *chunk_name, long offset, DWORD *start_pos, DWORD *next_pos) {
- BOOL mEnd = FALSE;
DWORD mLength = 0;
BYTE *data = NULL;
@@ -513,10 +512,14 @@ mng_RemoveChunk(FIMEMORY *hPngMemory, BYTE *chunk_name) {
DWORD next_pos = 0;
bResult = mng_FindChunk(hPngMemory, chunk_name, 8, &start_pos, &next_pos);
- if(!bResult) return FALSE;
+ if(!bResult) {
+ return FALSE;
+ }
bResult = mng_CopyRemoveChunks(hPngMemory, start_pos, next_pos);
- if(!bResult) return FALSE;
+ if(!bResult) {
+ return FALSE;
+ }
return TRUE;
}
@@ -529,10 +532,14 @@ mng_InsertChunk(FIMEMORY *hPngMemory, BYTE *inNextChunkName, BYTE *inInsertChunk
DWORD next_pos = 0;
bResult = mng_FindChunk(hPngMemory, inNextChunkName, 8, &start_pos, &next_pos);
- if(!bResult) return FALSE;
+ if(!bResult) {
+ return FALSE;
+ }
bResult = mng_CopyInsertChunks(hPngMemory, inNextChunkName, inInsertChunk, chunk_length, start_pos, next_pos);
- if(!bResult) return FALSE;
+ if(!bResult) {
+ return FALSE;
+ }
return TRUE;
}
@@ -962,7 +969,7 @@ mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, in
jng_color_type = mChunk[8];
jng_image_sample_depth = mChunk[9];
jng_image_compression_method = mChunk[10];
- BYTE jng_image_interlace_method = mChunk[11];
+ //BYTE jng_image_interlace_method = mChunk[11]; // for debug only
jng_alpha_sample_depth = mChunk[12];
jng_alpha_compression_method = mChunk[13];
@@ -1000,7 +1007,9 @@ mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, in
break;
}
// load the JPEG
- if(dib) FreeImage_Unload(dib);
+ if(dib) {
+ FreeImage_Unload(dib);
+ }
dib = mng_LoadFromMemoryHandle(hJpegMemory, flags);
// load the PNG alpha layer
@@ -1017,7 +1026,9 @@ mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, in
}
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);
+ if(dib_alpha) {
+ FreeImage_Unload(dib_alpha);
+ }
dib_alpha = mng_LoadFromMemoryHandle(hPngMemory, flags);
}
}
diff --git a/plugins/AdvaImg/src/FreeImage/MemoryIO.cpp b/plugins/AdvaImg/src/FreeImage/MemoryIO.cpp
index 6ae3fb2e11..e0997856a9 100644
--- a/plugins/AdvaImg/src/FreeImage/MemoryIO.cpp
+++ b/plugins/AdvaImg/src/FreeImage/MemoryIO.cpp
@@ -48,7 +48,7 @@ FreeImage_OpenMemory(BYTE *data, DWORD size_in_bytes) {
// wrap a user buffer
mem_header->delete_me = FALSE;
mem_header->data = (BYTE*)data;
- mem_header->datalen = mem_header->filelen = size_in_bytes;
+ mem_header->data_length = mem_header->file_length = size_in_bytes;
} else {
mem_header->delete_me = TRUE;
}
@@ -120,7 +120,7 @@ FreeImage_AcquireMemory(FIMEMORY *stream, BYTE **data, DWORD *size_in_bytes) {
FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data);
*data = (BYTE*)mem_header->data;
- *size_in_bytes = mem_header->filelen;
+ *size_in_bytes = mem_header->file_length;
return TRUE;
}
diff --git a/plugins/AdvaImg/src/FreeImage/MultiPage.cpp b/plugins/AdvaImg/src/FreeImage/MultiPage.cpp
index d48e11be94..4fe76adb16 100644
--- a/plugins/AdvaImg/src/FreeImage/MultiPage.cpp
+++ b/plugins/AdvaImg/src/FreeImage/MultiPage.cpp
@@ -269,8 +269,8 @@ FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL crea
header->node = node;
header->fif = fif;
header->io = io.get ();
- header->handle = handle;
- header->changed = FALSE;
+ header->handle = handle;
+ header->changed = FALSE;
header->read_only = read_only;
header->m_cachefile = NULL;
header->cache_fif = fif;
@@ -344,13 +344,13 @@ FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_h
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);
@@ -359,13 +359,13 @@ FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_h
header->m_filename = NULL;
header->node = node;
header->fif = fif;
- header->handle = handle;
- header->changed = FALSE;
- header->read_only = read_only;
+ 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();
@@ -381,7 +381,7 @@ FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_h
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();
}
@@ -408,7 +408,7 @@ FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap,
// retrieve the plugin list to find the node belonging to this plugin
PluginList *list = FreeImage_GetPluginList();
-
+
if (list) {
PluginNode *node = list->FindNodeFromFIF(fif);
diff --git a/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp b/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp
index c69463c316..b5714b2929 100644
--- a/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp
@@ -28,19 +28,6 @@
// ----------------------------------------------------------
BYTE * DLL_CALLCONV
-FreeImage_GetBits(FIBITMAP *dib) {
- if(!FreeImage_HasPixels(dib)) {
- return NULL;
- }
- // 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;
-}
-
-BYTE * DLL_CALLCONV
FreeImage_GetScanLine(FIBITMAP *dib, int scanline) {
if(!FreeImage_HasPixels(dib)) {
return NULL;
diff --git a/plugins/AdvaImg/src/FreeImage/Plugin.cpp b/plugins/AdvaImg/src/FreeImage/Plugin.cpp
index 6f88e47e68..13da67434e 100644
--- a/plugins/AdvaImg/src/FreeImage/Plugin.cpp
+++ b/plugins/AdvaImg/src/FreeImage/Plugin.cpp
@@ -218,7 +218,7 @@ FreeImage_GetPluginList() {
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
@@ -261,8 +261,8 @@ FreeImage_Initialise(BOOL load_local_plugins_only) {
//s_plugins->AddNode(InitXBM);
//s_plugins->AddNode(InitXPM);
//s_plugins->AddNode(InitDDS);
- s_plugins->AddNode(InitGIF);
- //s_plugins->AddNode(InitHDR);
+ s_plugins->AddNode(InitGIF);
+ //s_plugins->AddNode(InitHDR);
//s_plugins->AddNode(InitG3);
//s_plugins->AddNode(InitSGI);
//s_plugins->AddNode(InitEXR);
@@ -275,26 +275,26 @@ FreeImage_Initialise(BOOL load_local_plugins_only) {
//#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];
- char current_dir[2 * _MAX_PATH], module[2 * _MAX_PATH];
+ 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 (GetCurrentDirectoryA(2 * _MAX_PATH, current_dir) != 0) {
- if (GetModuleFileNameA(NULL, module, 2 * _MAX_PATH) != 0) {
- char *last_point = strrchr(module, '\\');
+ 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 = '\0';
+ *last_point = L'\0';
- bOk = SetCurrentDirectoryA(module);
+ bOk = SetCurrentDirectoryW(module);
}
}
}
@@ -335,7 +335,7 @@ FreeImage_Initialise(BOOL load_local_plugins_only) {
// restore the current directory
if (bOk) {
- SetCurrentDirectoryA(current_dir);
+ SetCurrentDirectoryW(current_dir);
}
}
#endif // _WIN32
diff --git a/plugins/AdvaImg/src/FreeImage/PluginEXR.cpp b/plugins/AdvaImg/src/FreeImage/PluginEXR.cpp
index 4a19b8b56f..b286430380 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginEXR.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginEXR.cpp
@@ -22,6 +22,12 @@
#include "FreeImage.h"
#include "Utilities.h"
+
+#ifdef _MSC_VER
+// OpenEXR has many problems with MSVC warnings (why not just correct them ?), just ignore one of them
+#pragma warning (disable : 4800) // ImfVersion.h - 'const int' : forcing value to bool 'true' or 'false' (performance warning)
+#endif
+
#include "../OpenEXR/IlmImf/ImfIO.h"
#include "../OpenEXR/Iex/Iex.h"
#include "../OpenEXR/IlmImf/ImfOutputFile.h"
@@ -44,72 +50,64 @@ static int s_format_id;
/**
FreeImage input stream wrapper
+@see Imf_2_2::IStream
*/
-class C_IStream: public Imf::IStream {
-public:
- C_IStream (FreeImageIO *io, fi_handle handle):
- IStream(""), _io (io), _handle(handle) {}
-
- virtual bool read (char c[/*n*/], int n);
- virtual Imf::Int64 tellg ();
- virtual void seekg (Imf::Int64 pos);
- virtual void clear () {};
-
+class C_IStream : public Imf::IStream {
private:
FreeImageIO *_io;
fi_handle _handle;
+
+public:
+ C_IStream (FreeImageIO *io, fi_handle handle) :
+ Imf::IStream(""), _io (io), _handle(handle) {
+ }
+
+ virtual bool read (char c[/*n*/], int n) {
+ return ((unsigned)n != _io->read_proc(c, 1, n, _handle));
+ }
+
+ virtual Imath::Int64 tellg() {
+ return _io->tell_proc(_handle);
+ }
+
+ virtual void seekg(Imath::Int64 pos) {
+ _io->seek_proc(_handle, (unsigned)pos, SEEK_SET);
+ }
+
+ virtual void clear() {
+ }
};
+// ----------------------------------------------------------
/**
FreeImage output stream wrapper
+@see Imf_2_2::OStream
*/
-class C_OStream: public Imf::OStream {
-public:
- C_OStream (FreeImageIO *io, fi_handle handle):
- OStream(""), _io (io), _handle(handle) {}
-
- virtual void write (const char c[/*n*/], int n);
- virtual Imf::Int64 tellp ();
- virtual void seekp (Imf::Int64 pos);
-
+class C_OStream : public Imf::OStream {
private:
FreeImageIO *_io;
fi_handle _handle;
-};
-
-
-bool
-C_IStream::read (char c[/*n*/], int n) {
- return ((unsigned)n != _io->read_proc(c, 1, n, _handle));
-}
-
-Imf::Int64
-C_IStream::tellg () {
- return _io->tell_proc(_handle);
-}
-void
-C_IStream::seekg (Imf::Int64 pos) {
- _io->seek_proc(_handle, (unsigned)pos, SEEK_SET);
-}
+public:
+ C_OStream (FreeImageIO *io, fi_handle handle) :
+ Imf::OStream(""), _io (io), _handle(handle) {
+ }
-void
-C_OStream::write (const char c[/*n*/], int n) {
- if((unsigned)n != _io->write_proc((void*)&c[0], 1, n, _handle)) {
- Iex::throwErrnoExc();
+ virtual void write(const char c[/*n*/], int n) {
+ if((unsigned)n != _io->write_proc((void*)&c[0], 1, n, _handle)) {
+ Iex::throwErrnoExc();
+ }
}
-}
-Imf::Int64
-C_OStream::tellp () {
- return _io->tell_proc(_handle);
-}
+ virtual Imath::Int64 tellp() {
+ return _io->tell_proc(_handle);
+ }
-void
-C_OStream::seekp (Imf::Int64 pos) {
- _io->seek_proc(_handle, (unsigned)pos, SEEK_SET);
-}
+ virtual void seekp(Imath::Int64 pos) {
+ _io->seek_proc(_handle, (unsigned)pos, SEEK_SET);
+ }
+};
// ----------------------------------------------------------
@@ -667,7 +665,9 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
if(pixelType == Imf::HALF) {
// convert from float to half
halfData = new(std::nothrow) half[width * height * components];
- if(!halfData) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY);
+ if(!halfData) {
+ THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY);
+ }
for(int y = 0; y < height; y++) {
float *src_bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y);
@@ -716,7 +716,9 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
file.setFrameBuffer (frameBuffer);
file.writePixels (height);
- if(halfData != NULL) delete[] halfData;
+ if(halfData != NULL) {
+ delete[] halfData;
+ }
if(bIsFlipped) {
// invert dib scanlines
FreeImage_FlipVertical(dib);
@@ -725,7 +727,9 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
return TRUE;
} catch(Iex::BaseExc & e) {
- if(halfData != NULL) delete[] halfData;
+ if(halfData != NULL) {
+ delete[] halfData;
+ }
if(bIsFlipped) {
// invert dib scanlines
FreeImage_FlipVertical(dib);
@@ -745,6 +749,11 @@ void DLL_CALLCONV
InitEXR(Plugin *plugin, int format_id) {
s_format_id = format_id;
+ // initialize the OpenEXR library
+ // note that this OpenEXR function produce so called "false memory leaks"
+ // see http://lists.nongnu.org/archive/html/openexr-devel/2013-11/msg00000.html
+ Imf::staticInitialize();
+
plugin->format_proc = Format;
plugin->description_proc = Description;
plugin->extension_proc = Extension;
diff --git a/plugins/AdvaImg/src/FreeImage/PluginG3.cpp b/plugins/AdvaImg/src/FreeImage/PluginG3.cpp
index d5c08b36e6..0a083b459b 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginG3.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginG3.cpp
@@ -92,7 +92,7 @@ G3GetFileSize(FreeImageIO *io, fi_handle handle) {
static BOOL
G3ReadFile(FreeImageIO *io, fi_handle handle, uint8 *tif_rawdata, tmsize_t tif_rawdatasize) {
- return ((tmsize_t)(io->read_proc(tif_rawdata, tif_rawdatasize, 1, handle) * tif_rawdatasize) == tif_rawdatasize);
+ return ((tmsize_t)(io->read_proc(tif_rawdata, (unsigned)tif_rawdatasize, 1, handle) * tif_rawdatasize) == tif_rawdatasize);
}
// ==========================================================
diff --git a/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp b/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp
index 87c0185865..0153959ab8 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp
@@ -4,6 +4,7 @@
// 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
//
@@ -773,7 +774,11 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
}
if( info.disposal_method == GIF_DISPOSAL_BACKGROUND ) {
for( y = 0; y < info.height; y++ ) {
- scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, logicalheight - (y + info.top) - 1) + info.left;
+ 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;
}
@@ -800,7 +805,11 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
}
//copy page data into logical buffer, with full alpha opaqueness
for( y = 0; y < info.height; y++ ) {
- scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, logicalheight - (y + info.top) - 1) + info.left;
+ 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 ) {
diff --git a/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp b/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp
index 0cde6139db..28ce1a5768 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp
@@ -459,8 +459,9 @@ rgbe_WriteBytes_RLE(FreeImageIO *io, fi_handle handle, BYTE *data, int numbytes)
beg_run += run_count;
old_run_count = run_count;
run_count = 1;
- while((data[beg_run] == data[beg_run + run_count]) && (beg_run + run_count < numbytes) && (run_count < 127))
+ while((beg_run + run_count < numbytes) && (run_count < 127) && (data[beg_run] == data[beg_run + run_count])) {
run_count++;
+ }
}
// if data before next big run is a short run then write it as such
if ((old_run_count > 1)&&(old_run_count == beg_run - cur)) {
diff --git a/plugins/AdvaImg/src/FreeImage/PluginICO.cpp b/plugins/AdvaImg/src/FreeImage/PluginICO.cpp
index df5ecee91d..c818379f78 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginICO.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginICO.cpp
@@ -110,6 +110,23 @@ CalculateImageOffset(std::vector<FIBITMAP*>& vPages, int nIndex ) {
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) {
@@ -407,16 +424,17 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
// load the requested icon
if (page < icon_header->idCount) {
// seek to the start of the bitmap data for the icon
- io->seek_proc(handle, 0, SEEK_SET);
- io->seek_proc(handle, icon_list[page].dwImageOffset, SEEK_CUR);
+ io->seek_proc(handle, icon_list[page].dwImageOffset, SEEK_SET);
- if((icon_list[page].bWidth == 0) && (icon_list[page].bHeight == 0)) {
+ 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);
}
diff --git a/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp b/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp
index 5c23a7c6e1..b8bcfc8b58 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp
@@ -175,7 +175,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
if (header_only) {
// create output image
dib = J2KImageToFIBITMAP(s_format_id, image, header_only);
- if(!dib) throw "Failed to import JPEG2000 image";
+ if(!dib) {
+ throw "Failed to import JPEG2000 image";
+ }
// clean-up and return header data
opj_destroy_codec(d_codec);
opj_image_destroy(image);
@@ -193,7 +195,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
// create output image
dib = J2KImageToFIBITMAP(s_format_id, image, header_only);
- if(!dib) throw "Failed to import JPEG2000 image";
+ if(!dib) {
+ throw "Failed to import JPEG2000 image";
+ }
// free image data structure
opj_image_destroy(image);
@@ -201,7 +205,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
return dib;
} catch (const char *text) {
- if(dib) FreeImage_Unload(dib);
+ if(dib) {
+ FreeImage_Unload(dib);
+ }
// free remaining structures
opj_destroy_codec(d_codec);
opj_image_destroy(image);
@@ -231,27 +237,22 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
opj_set_default_encoder_parameters(&parameters);
try {
- parameters.numresolution = 1;
- // check the resolution (i.e. parameters.numresolution)
- int min_size = MIN(FreeImage_GetWidth(dib), FreeImage_GetHeight(dib));
- if(min_size < (1 << parameters.numresolution)) {
- throw "Invalid image size - image is too small";
- }
-
- parameters.tcp_numlayers = 0;
+ parameters.tcp_numlayers = 0;
// if no rate entered, apply a 16:1 rate by default
if(flags == J2K_DEFAULT) {
parameters.tcp_rates[0] = (float)16;
} else {
// for now, the flags parameter is only used to specify the rate
- parameters.tcp_rates[0] = (float)flags;
+ parameters.tcp_rates[0] = (float)(flags & 0x3FF);
}
parameters.tcp_numlayers++;
parameters.cp_disto_alloc = 1;
// convert the dib to a OpenJPEG image
image = FIBITMAPToJ2KImage(s_format_id, dib, &parameters);
- if(!image) return FALSE;
+ if(!image) {
+ return FALSE;
+ }
// decide if MCT should be used
parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0;
diff --git a/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp b/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp
index edf5b396c3..742fe2c038 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp
@@ -175,7 +175,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
if (header_only) {
// create output image
dib = J2KImageToFIBITMAP(s_format_id, image, header_only);
- if(!dib) throw "Failed to import JPEG2000 image";
+ if(!dib) {
+ throw "Failed to import JPEG2000 image";
+ }
// clean-up and return header data
opj_destroy_codec(d_codec);
opj_image_destroy(image);
@@ -193,7 +195,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
// create output image
dib = J2KImageToFIBITMAP(s_format_id, image, header_only);
- if(!dib) throw "Failed to import JPEG2000 image";
+ if(!dib) {
+ throw "Failed to import JPEG2000 image";
+ }
// free image data structure
opj_image_destroy(image);
@@ -201,7 +205,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
return dib;
} catch (const char *text) {
- if(dib) FreeImage_Unload(dib);
+ if(dib) {
+ FreeImage_Unload(dib);
+ }
// free remaining structures
opj_destroy_codec(d_codec);
opj_image_destroy(image);
@@ -231,27 +237,22 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
opj_set_default_encoder_parameters(&parameters);
try {
- parameters.numresolution = 1;
- // check the resolution (i.e. parameters.numresolution)
- int min_size = MIN(FreeImage_GetWidth(dib), FreeImage_GetHeight(dib));
- if(min_size < (1 << parameters.numresolution)) {
- throw "Invalid image size - image is too small";
- }
-
- parameters.tcp_numlayers = 0;
+ parameters.tcp_numlayers = 0;
// if no rate entered, apply a 16:1 rate by default
- if(flags == J2K_DEFAULT) {
+ if(flags == JP2_DEFAULT) {
parameters.tcp_rates[0] = (float)16;
} else {
// for now, the flags parameter is only used to specify the rate
- parameters.tcp_rates[0] = (float)flags;
+ parameters.tcp_rates[0] = (float)(flags & 0x3FF);
}
parameters.tcp_numlayers++;
parameters.cp_disto_alloc = 1;
// convert the dib to a OpenJPEG image
image = FIBITMAPToJ2KImage(s_format_id, dib, &parameters);
- if(!image) return FALSE;
+ if(!image) {
+ return FALSE;
+ }
// decide if MCT should be used
parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0;
diff --git a/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp b/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp
index c1b45e6347..573989c5df 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp
@@ -919,9 +919,6 @@ jpeg_write_exif_profile_raw(j_compress_ptr cinfo, FIBITMAP *dib) {
if(tag_exif) {
const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_exif);
-
- if (NULL == tag_value)
- return FALSE;
// verify the identifying string
if(memcmp(exif_signature, tag_value, sizeof(exif_signature)) != 0) {
@@ -929,21 +926,23 @@ jpeg_write_exif_profile_raw(j_compress_ptr cinfo, FIBITMAP *dib) {
return FALSE;
}
- DWORD tag_length = FreeImage_GetTagLength(tag_exif);
-
- BYTE *profile = (BYTE*)malloc(tag_length * sizeof(BYTE));
- if(profile == NULL) return FALSE;
+ if(NULL != tag_value) {
+ DWORD tag_length = FreeImage_GetTagLength(tag_exif);
- for(DWORD i = 0; i < tag_length; i += 65504L) {
- unsigned length = MIN((long)(tag_length - i), 65504L);
+ BYTE *profile = (BYTE*)malloc(tag_length * sizeof(BYTE));
+ if(profile == NULL) return FALSE;
- memcpy(profile, tag_value + i, length);
- jpeg_write_marker(cinfo, EXIF_MARKER, profile, length);
- }
+ 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);
+ free(profile);
- return TRUE;
+ return TRUE;
+ }
}
return FALSE;
diff --git a/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp b/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp
index f5e4878c1d..0e14e09ac9 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp
@@ -163,8 +163,6 @@ JXR_ErrorMessage(const int error) {
default:
return "Invalid instruction - please contact the FreeImage team";
}
-
- return NULL;
}
// ==========================================================
@@ -410,11 +408,12 @@ GetOutputPixelFormat(FIBITMAP *dib, PKPixelFormatGUID *guid_format, BOOL *bHasAl
}
// ==========================================================
-// Metadata loading & saving
+// Metadata loading
// ==========================================================
/**
Read a JPEG-XR IFD as a buffer
+@see ReadMetadata
*/
static ERR
ReadProfile(WMPStream* pStream, unsigned cbByteCount, unsigned uOffset, BYTE **ppbProfile) {
@@ -436,6 +435,7 @@ ReadProfile(WMPStream* pStream, unsigned cbByteCount, unsigned uOffset, BYTE **p
/**
Convert a DPKPROPVARIANT to a FITAG, then store the tag as FIMD_EXIF_MAIN
+@see ReadDescriptiveMetadata
*/
static BOOL
ReadPropVariant(WORD tag_id, const DPKPROPVARIANT & varSrc, FIBITMAP *dib) {
@@ -470,7 +470,7 @@ ReadPropVariant(WORD tag_id, const DPKPROPVARIANT & varSrc, FIBITMAP *dib) {
case DPKVT_LPWSTR:
FreeImage_SetTagType(tag, FIDT_UNDEFINED);
dwSize = (DWORD)(sizeof(U16) * (wcslen((wchar_t *) varSrc.VT.pwszVal) + 1)); // +1 for NULL term
- FreeImage_SetTagCount(tag, dwSize / 2);
+ FreeImage_SetTagCount(tag, dwSize);
FreeImage_SetTagLength(tag, dwSize);
FreeImage_SetTagValue(tag, varSrc.VT.pwszVal);
break;
@@ -533,6 +533,7 @@ ReadDescriptiveMetadata(PKImageDecode *pID, FIBITMAP *dib) {
/**
Read ICC, XMP, Exif, Exif-GPS, IPTC, descriptive (i.e. Exif-TIFF) metadata
+@see ReadProfile, ReadDescriptiveMetadata
*/
static ERR
ReadMetadata(PKImageDecode *pID, FIBITMAP *dib) {
@@ -593,7 +594,7 @@ ReadMetadata(PKImageDecode *pID, FIBITMAP *dib) {
error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile);
JXR_CHECK(error_code);
// decode the Exif profile
- jpegxr_read_exif_profile(dib, pbProfile, cbByteCount);
+ jpegxr_read_exif_profile(dib, pbProfile, cbByteCount, uOffset);
}
// Exif-GPS metadata
@@ -603,7 +604,7 @@ ReadMetadata(PKImageDecode *pID, FIBITMAP *dib) {
error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile);
JXR_CHECK(error_code);
// decode the Exif-GPS profile
- jpegxr_read_exif_gps_profile(dib, pbProfile, cbByteCount);
+ jpegxr_read_exif_gps_profile(dib, pbProfile, cbByteCount, uOffset);
}
// free profile buffer
@@ -630,6 +631,168 @@ ReadMetadata(PKImageDecode *pID, FIBITMAP *dib) {
}
// ==========================================================
+// Metadata saving
+// ==========================================================
+
+/**
+Convert a FITAG (coming from FIMD_EXIF_MAIN) to a DPKPROPVARIANT.
+No allocation is needed here, the function just copy pointers when needed.
+@see WriteDescriptiveMetadata
+*/
+static BOOL
+WritePropVariant(FIBITMAP *dib, WORD tag_id, DPKPROPVARIANT & varDst) {
+ FITAG *tag = NULL;
+
+ TagLib& s = TagLib::instance();
+
+ // clear output DPKPROPVARIANT
+ varDst.vt = DPKVT_EMPTY;
+
+ // given the tag id, get the tag key
+ const char *key = s.getTagFieldName(TagLib::EXIF_MAIN, tag_id, NULL);
+ // then, get the tag info
+ if(!FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, key, &tag)) {
+ return FALSE;
+ }
+
+ // set the tag value
+ switch(FreeImage_GetTagType(tag)) {
+ case FIDT_ASCII:
+ varDst.vt = DPKVT_LPSTR;
+ varDst.VT.pszVal = (char*)FreeImage_GetTagValue(tag);
+ break;
+ case FIDT_BYTE:
+ case FIDT_UNDEFINED:
+ varDst.vt = DPKVT_LPWSTR;
+ varDst.VT.pwszVal = (U16*)FreeImage_GetTagValue(tag);
+ break;
+ case FIDT_SHORT:
+ varDst.vt = DPKVT_UI2;
+ varDst.VT.uiVal = *((U16*)FreeImage_GetTagValue(tag));
+ break;
+ case FIDT_LONG:
+ varDst.vt = DPKVT_UI4;
+ varDst.VT.ulVal = *((U32*)FreeImage_GetTagValue(tag));
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+/**
+Write EXIF_MAIN metadata to JPEG-XR descriptive metadata
+@see WritePropVariant
+*/
+static ERR
+WriteDescriptiveMetadata(PKImageEncode *pIE, FIBITMAP *dib) {
+ ERR error_code = 0; // error code as returned by the interface
+ DESCRIPTIVEMETADATA DescMetadata;
+
+ // fill the DESCRIPTIVEMETADATA structure (use pointers to arrays when needed)
+ WritePropVariant(dib, WMP_tagImageDescription, DescMetadata.pvarImageDescription);
+ WritePropVariant(dib, WMP_tagCameraMake, DescMetadata.pvarCameraMake);
+ WritePropVariant(dib, WMP_tagCameraModel, DescMetadata.pvarCameraModel);
+ WritePropVariant(dib, WMP_tagSoftware, DescMetadata.pvarSoftware);
+ WritePropVariant(dib, WMP_tagDateTime, DescMetadata.pvarDateTime);
+ WritePropVariant(dib, WMP_tagArtist, DescMetadata.pvarArtist);
+ WritePropVariant(dib, WMP_tagCopyright, DescMetadata.pvarCopyright);
+ WritePropVariant(dib, WMP_tagRatingStars, DescMetadata.pvarRatingStars);
+ WritePropVariant(dib, WMP_tagRatingValue, DescMetadata.pvarRatingValue);
+ WritePropVariant(dib, WMP_tagCaption, DescMetadata.pvarCaption);
+ WritePropVariant(dib, WMP_tagDocumentName, DescMetadata.pvarDocumentName);
+ WritePropVariant(dib, WMP_tagPageName, DescMetadata.pvarPageName);
+ WritePropVariant(dib, WMP_tagPageNumber, DescMetadata.pvarPageNumber);
+ WritePropVariant(dib, WMP_tagHostComputer, DescMetadata.pvarHostComputer);
+
+ // copy the structure to the encoder
+ error_code = pIE->SetDescriptiveMetadata(pIE, &DescMetadata);
+
+ // no need to free anything here
+ return error_code;
+}
+
+/**
+Write ICC, XMP, Exif, Exif-GPS, IPTC, descriptive (i.e. Exif-TIFF) metadata
+*/
+static ERR
+WriteMetadata(PKImageEncode *pIE, FIBITMAP *dib) {
+ ERR error_code = 0; // error code as returned by the interface
+ BYTE *profile = NULL;
+ unsigned profile_size = 0;
+
+ try {
+ // write ICC profile
+ {
+ FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
+ if(iccProfile->data) {
+ error_code = pIE->SetColorContext(pIE, (U8*)iccProfile->data, iccProfile->size);
+ JXR_CHECK(error_code);
+ }
+ }
+
+ // write descriptive metadata
+ if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib)) {
+ error_code = WriteDescriptiveMetadata(pIE, dib);
+ JXR_CHECK(error_code);
+ }
+
+ // write IPTC metadata
+ if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) {
+ // create a binary profile
+ if(write_iptc_profile(dib, &profile, &profile_size)) {
+ // write the profile
+ error_code = PKImageEncode_SetIPTCNAAMetadata_WMP(pIE, profile, profile_size);
+ JXR_CHECK(error_code);
+ // release profile
+ free(profile);
+ profile = NULL;
+ }
+ }
+
+ // write XMP metadata
+ {
+ FITAG *tag_xmp = NULL;
+ if(FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp)) {
+ error_code = PKImageEncode_SetXMPMetadata_WMP(pIE, (BYTE*)FreeImage_GetTagValue(tag_xmp), FreeImage_GetTagLength(tag_xmp));
+ JXR_CHECK(error_code);
+ }
+ }
+
+ // write Exif metadata
+ {
+ if(tiff_get_ifd_profile(dib, FIMD_EXIF_EXIF, &profile, &profile_size)) {
+ error_code = PKImageEncode_SetEXIFMetadata_WMP(pIE, profile, profile_size);
+ JXR_CHECK(error_code);
+ // release profile
+ free(profile);
+ profile = NULL;
+ }
+ }
+
+ // write Exif GPS metadata
+ {
+ if(tiff_get_ifd_profile(dib, FIMD_EXIF_GPS, &profile, &profile_size)) {
+ error_code = PKImageEncode_SetGPSInfoMetadata_WMP(pIE, profile, profile_size);
+ JXR_CHECK(error_code);
+ // release profile
+ free(profile);
+ profile = NULL;
+ }
+ }
+
+ return WMP_errSuccess;
+
+ } catch(...) {
+ free(profile);
+ return error_code;
+ }
+}
+
+
+
+// ==========================================================
// Quantization tables (Y, U, V, YHP, UHP, VHP),
// optimized for PSNR
// ==========================================================
@@ -1238,8 +1401,11 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
float resY = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterY(dib));
pEncoder->SetResolution(pEncoder, resX, resY);
- // write pixels
- // --------------
+ // set metadata
+ WriteMetadata(pEncoder, dib);
+
+ // write metadata & pixels
+ // -----------------------
// dib coordinates are upside-down relative to usual conventions
bIsFlipped = FreeImage_FlipVertical(dib);
@@ -1250,7 +1416,7 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
// get dst pitch (count of BYTE for stride)
const unsigned cbStride = FreeImage_GetPitch(dib);
- // write pixels on output
+ // write metadata + pixels on output
error_code = pEncoder->WritePixels(pEncoder, height, dib_bits, cbStride);
JXR_CHECK(error_code);
diff --git a/plugins/AdvaImg/src/FreeImage/PluginPFM.cpp b/plugins/AdvaImg/src/FreeImage/PluginPFM.cpp
index 231e8baa22..ea3c46b14e 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginPFM.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginPFM.cpp
@@ -63,11 +63,13 @@ Get an integer value from the actual position pointed by handle
static int
pfm_get_int(FreeImageIO *io, fi_handle handle) {
char c = 0;
- BOOL firstchar;
+ BOOL bFirstChar;
// skip forward to start of next number
- if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ if(!io->read_proc(&c, 1, 1, handle)) {
+ throw FI_MSG_ERROR_PARSING;
+ }
while (1) {
// eat comments
@@ -75,15 +77,16 @@ pfm_get_int(FreeImageIO *io, fi_handle handle) {
if (c == '#') {
// if we're at a comment, read to end of line
- firstchar = TRUE;
+ bFirstChar = TRUE;
while (1) {
- if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ if(!io->read_proc(&c, 1, 1, handle)) {
+ throw FI_MSG_ERROR_PARSING;
+ }
- if (firstchar && c == ' ') {
+ if (bFirstChar && c == ' ') {
// loop off 1 sp after #
-
- firstchar = FALSE;
+ bFirstChar = FALSE;
} else if (c == '\n') {
break;
}
@@ -92,11 +95,12 @@ pfm_get_int(FreeImageIO *io, fi_handle handle) {
if (c >= '0' && c <='9') {
// we've found what we were looking for
-
break;
}
- if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ if(!io->read_proc(&c, 1, 1, handle)) {
+ throw FI_MSG_ERROR_PARSING;
+ }
}
// we're at the start of a number, continue until we hit a non-number
@@ -106,10 +110,13 @@ pfm_get_int(FreeImageIO *io, fi_handle handle) {
while (1) {
i = (i * 10) + (c - '0');
- if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ if(!io->read_proc(&c, 1, 1, handle)) {
+ throw FI_MSG_ERROR_PARSING;
+ }
- if (c < '0' || c > '9')
- break;
+ if (c < '0' || c > '9') {
+ break;
+ }
}
return i;
diff --git a/plugins/AdvaImg/src/FreeImage/PluginPICT.cpp b/plugins/AdvaImg/src/FreeImage/PluginPICT.cpp
index 99958a489c..371056d20b 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginPICT.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginPICT.cpp
@@ -82,21 +82,21 @@ static const int outputMessageSize = 256;
// Internal functions
// ==========================================================
-static unsigned
+static BYTE
Read8(FreeImageIO *io, fi_handle handle) {
- unsigned char i = 0;
+ BYTE i = 0;
io->read_proc(&i, 1, 1, handle);
return i;
}
-static unsigned
+static WORD
Read16(FreeImageIO *io, fi_handle handle) {
// reads a two-byte big-endian integer from the given file and returns its value.
// assumes unsigned.
unsigned hi = Read8(io, handle);
unsigned lo = Read8(io, handle);
- return lo + (hi << 8);
+ return (WORD)(lo + (hi << 8));
}
static unsigned
@@ -388,7 +388,7 @@ ReadColorTable( FreeImageIO *io, fi_handle handle, WORD* pNumColors, RGBQUAD* pP
// The indicies in a device colour table are bogus and
// usually == 0, so I assume we allocate up the list of
// colours in order.
- val = i;
+ val = (WORD)i;
}
if (val >= numColors) {
throw "pixel value greater than color table size.";
@@ -416,7 +416,7 @@ SkipBits( FreeImageIO *io, fi_handle handle, MacRect* bounds, WORD rowBytes, int
if (pixelSize <= 8) {
rowBytes &= 0x7fff;
}
- pixwidth = width;
+ pixwidth = (WORD)width;
if (pixelSize == 16) {
pixwidth *= 2;
@@ -541,6 +541,7 @@ expandBuf8( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst )
static BYTE*
UnpackPictRow( FreeImageIO *io, fi_handle handle, BYTE* pLineBuf, int width, int rowBytes, int srcBytes ) {
+
if (rowBytes < 8) { // Ah-ha! The bits aren't actually packed. This will be easy.
io->read_proc( pLineBuf, rowBytes, 1, handle );
}
@@ -589,7 +590,7 @@ Unpack32Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds,
int width = bounds->right - bounds->left;
if (rowBytes == 0) {
- rowBytes = width*4;
+ rowBytes = (WORD)( width * 4 );
}
BYTE* pLineBuf = (BYTE*)malloc( rowBytes ); // Let's allocate enough for 4 bit planes
@@ -656,7 +657,7 @@ Unpack8Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds,
rowBytes &= 0x7fff;
if (rowBytes == 0) {
- rowBytes = width;
+ rowBytes = (WORD)width;
}
for ( int i = 0; i < height; i++ ) {
@@ -694,7 +695,7 @@ UnpackBits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, W
rowBytes &= 0x7fff;
}
- pixwidth = width;
+ pixwidth = (WORD)width;
pkpixsize = 1; // RLE unit: one byte for everything...
if (pixelSize == 16) { // ...except 16 bpp.
pkpixsize = 2;
diff --git a/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp b/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp
index f6b59e299b..fe80a2b533 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp
@@ -6,6 +6,7 @@
// - 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
//
@@ -49,9 +50,9 @@ typedef struct {
fi_handle s_handle;
} fi_ioStructure, *pfi_ioStructure;
-/////////////////////////////////////////////////////////////////////////////
-// libpng interface
-//
+// ==========================================================
+// libpng interface
+// ==========================================================
static void
_ReadProc(png_structp png_ptr, unsigned char *data, png_size_t size) {
@@ -99,6 +100,7 @@ ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
FITAG *tag = NULL;
png_textp text_ptr = NULL;
+ png_timep mod_time = NULL;
int num_text = 0;
// iTXt/tEXt/zTXt chuncks
@@ -130,6 +132,31 @@ ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
}
}
+ // 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;
}
@@ -143,6 +170,7 @@ WriteMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
BOOL bResult = TRUE;
png_text text_metadata;
+ png_time mod_time;
// set the 'Comments' metadata as iTXt chuncks
@@ -174,7 +202,7 @@ WriteMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
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.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
@@ -186,6 +214,23 @@ WriteMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
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;
}
@@ -265,21 +310,207 @@ 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;
+ png_infop info_ptr = NULL;
png_uint_32 width, height;
- png_colorp png_palette = NULL;
- int color_type, palette_entries = 0;
- int bit_depth, pixel_depth; // pixel_depth = bit_depth * channels
+ int color_type;
+ int bit_depth;
+ int pixel_depth = 0; // pixel_depth = bit_depth * channels
FIBITMAP *dib = NULL;
- RGBQUAD *palette = NULL; // pointer to dib palette
- png_bytepp row_pointers = NULL;
- int i;
+ png_bytepp row_pointers = NULL;
fi_ioStructure fio;
fio.s_handle = handle;
@@ -334,154 +565,58 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
- pixel_depth = png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr);
-
- // get image data type (assume standard image type)
+ // configure the decoder
FREE_IMAGE_TYPE image_type = FIT_BITMAP;
- if (bit_depth == 16) {
- if ((pixel_depth == 16) && (color_type == PNG_COLOR_TYPE_GRAY)) {
- image_type = FIT_UINT16;
- }
- else if ((pixel_depth == 48) && (color_type == PNG_COLOR_TYPE_RGB)) {
- image_type = FIT_RGB16;
- }
- else if ((pixel_depth == 64) && (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) {
- image_type = FIT_RGBA16;
- } else {
- // tell libpng to strip 16 bit/color files down to 8 bits/color
- png_set_strip_16(png_ptr);
- bit_depth = 8;
- }
- }
-
-#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
-
- // set some additional flags
-
- switch(color_type) {
- case PNG_COLOR_TYPE_RGB:
- case PNG_COLOR_TYPE_RGB_ALPHA:
-#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
- // flip the RGB pixels to BGR (or RGBA to BGRA)
-
- if(image_type == FIT_BITMAP) {
- png_set_bgr(png_ptr);
- }
-#endif
- break;
-
- case PNG_COLOR_TYPE_PALETTE:
- // expand palette images to the full 8 bits from 2 bits/pixel
-
- if (pixel_depth == 2) {
- png_set_packing(png_ptr);
- pixel_depth = 8;
- }
-
- break;
-
- case PNG_COLOR_TYPE_GRAY:
- // expand grayscale images to the full 8 bits from 2 bits/pixel
- // but *do not* expand fully transparent palette entries to a full alpha channel
-
- if (pixel_depth == 2) {
- png_set_expand_gray_1_2_4_to_8(png_ptr);
- pixel_depth = 8;
- }
-
- break;
-
- case PNG_COLOR_TYPE_GRAY_ALPHA:
- // expand 8-bit greyscale + 8-bit alpha to 32-bit
- png_set_gray_to_rgb(png_ptr);
-#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
- // flip the RGBA pixels to BGRA
-
- png_set_bgr(png_ptr);
-#endif
- pixel_depth = 32;
-
- break;
-
- default:
- throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ if(!ConfigureDecoder(png_ptr, info_ptr, flags, &image_type)) {
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
}
- // 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);
+ // update image info
- // color type may have changed, due to our transformations
+ 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);
- color_type = png_get_color_type(png_ptr,info_ptr);
-
- // create a DIB and write the bitmap header
- // set up the DIB palette, if needed
+ // create a dib and write the bitmap header
+ // set up the dib palette, if needed
switch (color_type) {
case PNG_COLOR_TYPE_RGB:
- png_set_invert_alpha(png_ptr);
-
- if(image_type == FIT_BITMAP) {
- dib = FreeImage_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
- } else {
- dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth);
- }
- break;
-
case PNG_COLOR_TYPE_RGB_ALPHA:
- if(image_type == FIT_BITMAP) {
- dib = FreeImage_AllocateHeader(header_only, width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
- } else {
- dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth);
- }
+ 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_AllocateHeader(header_only, width, height, pixel_depth);
+ 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);
+ png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries);
- palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib));
- palette = FreeImage_GetPalette(dib);
+ palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib));
- // store the palette
+ // store the palette
- for (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;
+ 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);
+ dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
- if(pixel_depth <= 8) {
- palette = FreeImage_GetPalette(dib);
- palette_entries = 1 << pixel_depth;
+ if(dib && (pixel_depth <= 8)) {
+ RGBQUAD *palette = FreeImage_GetPalette(dib);
+ const int palette_entries = 1 << pixel_depth;
- for (i = 0; i < palette_entries; i++) {
+ for(int i = 0; i < palette_entries; i++) {
palette[i].rgbRed =
palette[i].rgbGreen =
palette[i].rgbBlue = (BYTE)((i * 255) / (palette_entries - 1));
@@ -493,6 +628,10 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
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)) {
@@ -507,21 +646,26 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
if((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) {
// single transparent color
- if (trans_color->gray < palette_entries) {
+ if (trans_color->gray < 256) {
BYTE table[256];
- memset(table, 0xFF, palette_entries);
+ memset(table, 0xFF, 256);
table[trans_color->gray] = 0;
- FreeImage_SetTransparencyTable(dib, table, palette_entries);
+ 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
+ // store the background color (only supported for FIT_BITMAP types)
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) {
+ 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.
@@ -598,7 +742,7 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
// 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);
+ row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k);
}
png_set_benign_errors(png_ptr, 1);
@@ -644,7 +788,7 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
free(row_pointers);
}
if (dib) {
- FreeImage_Unload(dib);
+ FreeImage_Unload(dib);
}
FreeImage_OutputMessageProc(s_format_id, text);
@@ -655,6 +799,8 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
return NULL;
}
+// --------------------------------------------------------------------------
+
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
png_structp png_ptr;
@@ -903,7 +1049,7 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
// 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);
+ FreeImage_ConvertLine32To24(buffer, FreeImage_GetScanLine(dib, height - k - 1), width);
png_write_row(png_ptr, buffer);
}
}
@@ -911,8 +1057,8 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
} 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));
+ for (png_uint_32 k = 0; k < height; k++) {
+ png_write_row(png_ptr, FreeImage_GetScanLine(dib, height - k - 1));
}
}
}
@@ -930,7 +1076,11 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
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);
}
}
diff --git a/plugins/AdvaImg/src/FreeImage/PluginPNM.cpp b/plugins/AdvaImg/src/FreeImage/PluginPNM.cpp
index 3155315559..3b4d0de554 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginPNM.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginPNM.cpp
@@ -33,11 +33,13 @@ Get an integer value from the actual position pointed by handle
static int
GetInt(FreeImageIO *io, fi_handle handle) {
char c = 0;
- BOOL firstchar;
+ BOOL bFirstChar;
// skip forward to start of next number
- if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ if(!io->read_proc(&c, 1, 1, handle)) {
+ throw FI_MSG_ERROR_PARSING;
+ }
while (1) {
// eat comments
@@ -45,15 +47,16 @@ GetInt(FreeImageIO *io, fi_handle handle) {
if (c == '#') {
// if we're at a comment, read to end of line
- firstchar = TRUE;
+ bFirstChar = TRUE;
while (1) {
- if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ if(!io->read_proc(&c, 1, 1, handle)) {
+ throw FI_MSG_ERROR_PARSING;
+ }
- if (firstchar && c == ' ') {
+ if (bFirstChar && c == ' ') {
// loop off 1 sp after #
-
- firstchar = FALSE;
+ bFirstChar = FALSE;
} else if (c == '\n') {
break;
}
@@ -62,11 +65,12 @@ GetInt(FreeImageIO *io, fi_handle handle) {
if (c >= '0' && c <='9') {
// we've found what we were looking for
-
break;
}
- if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ if(!io->read_proc(&c, 1, 1, handle)) {
+ throw FI_MSG_ERROR_PARSING;
+ }
}
// we're at the start of a number, continue until we hit a non-number
@@ -76,10 +80,13 @@ GetInt(FreeImageIO *io, fi_handle handle) {
while (1) {
i = (i * 10) + (c - '0');
- if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ if(!io->read_proc(&c, 1, 1, handle)) {
+ throw FI_MSG_ERROR_PARSING;
+ }
- if (c < '0' || c > '9')
- break;
+ if (c < '0' || c > '9') {
+ break;
+ }
}
return i;
diff --git a/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp b/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp
index bf5d82169c..e9bd5bfa77 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp
@@ -140,12 +140,72 @@ public:
/**
Convert a processed raw data array to a FIBITMAP
+@param RawProcessor LibRaw handle containing the processed raw image
+@return Returns the converted dib if successfull, returns NULL otherwise
+*/
+static FIBITMAP *
+libraw_ConvertProcessedRawToDib(LibRaw *RawProcessor) {
+ FIBITMAP *dib = NULL;
+ int width, height, colors, bpp;
+
+ try {
+ int bgr = 0; // pixel copy order: RGB if (bgr == 0) and BGR otherwise
+
+ // get image info
+ RawProcessor->get_mem_image_format(&width, &height, &colors, &bpp);
+
+ // only 3-color images supported...
+ if(colors != 3) {
+ throw "LibRaw : only 3-color images supported";
+ }
+
+ if(bpp == 16) {
+ // allocate output dib
+ dib = FreeImage_AllocateT(FIT_RGB16, width, height);
+ if(!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ } else if(bpp == 8) {
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ bgr = 1; // only useful for FIT_BITMAP types
+#endif
+
+ // allocate output dib
+ dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
+ if(!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+ }
+
+ // copy post-processed bitmap data into FIBITMAP buffer
+ if(RawProcessor->copy_mem_image(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), bgr) != LIBRAW_SUCCESS) {
+ throw "LibRaw : failed to copy data into dib";
+ }
+
+ // flip vertically
+ FreeImage_FlipVertical(dib);
+
+ return dib;
+
+ } catch(const char *text) {
+ FreeImage_Unload(dib);
+ FreeImage_OutputMessageProc(s_format_id, text);
+ return NULL;
+ }
+}
+
+
+/**
+Convert a processed raw image to a FIBITMAP
@param image Processed raw image
@return Returns the converted dib if successfull, returns NULL otherwise
+@see libraw_LoadEmbeddedPreview
*/
static FIBITMAP *
-libraw_ConvertToDib(libraw_processed_image_t *image) {
+libraw_ConvertProcessedImageToDib(libraw_processed_image_t *image) {
FIBITMAP *dib = NULL;
+
try {
unsigned width = image->width;
unsigned height = image->height;
@@ -185,12 +245,14 @@ libraw_ConvertToDib(libraw_processed_image_t *image) {
}
}
}
+
+ return dib;
} catch(const char *text) {
+ FreeImage_Unload(dib);
FreeImage_OutputMessageProc(s_format_id, text);
+ return NULL;
}
-
- return dib;
}
/**
@@ -228,9 +290,9 @@ libraw_LoadEmbeddedPreview(LibRaw *RawProcessor, int flags) {
dib = FreeImage_LoadFromMemory(fif, hmem, flags);
// close the stream
FreeImage_CloseMemory(hmem);
- } else {
+ } else if((flags & FIF_LOAD_NOPIXELS) != FIF_LOAD_NOPIXELS) {
// convert processed data to output dib
- dib = libraw_ConvertToDib(thumb_image);
+ dib = libraw_ConvertProcessedImageToDib(thumb_image);
}
} else {
throw "LibRaw : failed to run dcraw_make_mem_thumb";
@@ -262,7 +324,6 @@ Load raw data and convert to FIBITMAP
static FIBITMAP *
libraw_LoadRawData(LibRaw *RawProcessor, int bitspersample) {
FIBITMAP *dib = NULL;
- libraw_processed_image_t *processed_image = NULL;
try {
// set decoding parameters
@@ -300,38 +361,119 @@ libraw_LoadRawData(LibRaw *RawProcessor, int bitspersample) {
}
// retrieve processed image
- int error_code = 0;
- processed_image = RawProcessor->dcraw_make_mem_image(&error_code);
- if(processed_image) {
- // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
- if(processed_image->type != LIBRAW_IMAGE_BITMAP) {
- throw "invalid image type";
+ dib = libraw_ConvertProcessedRawToDib(RawProcessor);
+
+ return dib;
+
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+ return NULL;
+ }
+}
+
+/**
+Load the Bayer matrix (unprocessed raw data) as a FIT_UINT16 image.
+Note that some formats don't have a Bayer matrix (e.g. Foveon, Canon sRAW, demosaiced DNG files).
+@param RawProcessor Libraw handle
+@return Returns the loaded dib if successfull, returns NULL otherwise
+*/
+static FIBITMAP *
+libraw_LoadUnprocessedData(LibRaw *RawProcessor) {
+ FIBITMAP *dib = NULL;
+
+ try {
+ // unpack data
+ if(RawProcessor->unpack() != LIBRAW_SUCCESS) {
+ throw "LibRaw : failed to unpack data";
+ }
+
+ // check for a supported Bayer format
+ if(!(RawProcessor->imgdata.idata.filters || RawProcessor->imgdata.idata.colors == 1)) {
+ throw "LibRaw : only Bayer-pattern RAW files are supported";
+ }
+
+ // allocate output dib
+ const unsigned width = RawProcessor->imgdata.sizes.raw_width;
+ const unsigned height = RawProcessor->imgdata.sizes.raw_height;
+ const size_t line_size = width * sizeof(WORD);
+ const WORD *src_bits = (WORD*)RawProcessor->imgdata.rawdata.raw_image;
+
+ if(src_bits) {
+ dib = FreeImage_AllocateT(FIT_UINT16, width, height);
+ }
+ if(!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // retrieve the raw image
+ for(unsigned y = 0; y < height; y++) {
+ WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y);
+ memcpy(dst_bits, src_bits, line_size);
+ src_bits += width;
+ }
+
+ // store metadata needed for post-processing
+ {
+ char value[512];
+
+ const libraw_image_sizes_t *sizes = &RawProcessor->imgdata.sizes;
+
+ // image output width & height
+ {
+ sprintf(value, "%d", sizes->iwidth);
+ FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Width", value);
+
+ sprintf(value, "%d", sizes->iheight);
+ FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Height", value);
}
- // only 3-color images supported...
- if(processed_image->colors != 3) {
- throw "only 3-color images supported";
+
+ // image output frame
+ {
+ const unsigned f_left = sizes->left_margin;
+ const unsigned f_top = sizes->top_margin;
+ const unsigned f_width = sizes->width;
+ const unsigned f_height = sizes->height;
+
+ sprintf(value, "%d", f_left);
+ FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Left", value);
+
+ sprintf(value, "%d", f_top);
+ FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Top", value);
+
+ sprintf(value, "%d", f_width);
+ FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Width", value);
+
+ sprintf(value, "%d", f_height);
+ FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Height", value);
}
- } else {
- throw "LibRaw : failed to run dcraw_make_mem_image";
- }
- // convert processed data to output dib
- dib = libraw_ConvertToDib(processed_image);
-
- // clean-up and return
- RawProcessor->dcraw_clear_mem(processed_image);
+ // Bayer pattern
+ // Mask describing the order of color pixels in the matrix.
+ // This field describe 16 pixels (8 rows with two pixels in each, from left to right and from top to bottom).
+
+ if(RawProcessor->imgdata.idata.filters) {
+ // description of colors numbered from 0 to 3 (RGBG,RGBE,GMCY, or GBTG)
+ char *cdesc = RawProcessor->imgdata.idata.cdesc;
+ if(!cdesc[3]) {
+ cdesc[3] = 'G';
+ }
+ char *pattern = &value[0];
+ for(int i = 0; i < 16; i++) {
+ pattern[i] = cdesc[ RawProcessor->fcol(i >> 1, i & 1) ];
+ }
+ pattern[16] = 0;
+ FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.BayerPattern", value);
+ }
+ }
+
return dib;
} catch(const char *text) {
- // clean-up and return
- if(processed_image) {
- RawProcessor->dcraw_clear_mem(processed_image);
- }
+ FreeImage_Unload(dib);
FreeImage_OutputMessageProc(s_format_id, text);
+ return NULL;
}
-
- return NULL;
}
// ==========================================================
@@ -397,8 +539,8 @@ Extension() {
"sr2," // Sony Digital Camera Raw Image Format.
"srf," // Sony Digital Camera Raw Image Format for DSC-F828 8 megapixel digital camera or Sony DSC-R1.
"srw," // Samsung Raw Image Format.
- "sti"; // Sinar Capture Shop Raw Image File.
-// "x3f" // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor.
+ "sti," // Sinar Capture Shop Raw Image File.
+ "x3f"; // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor.
return raw_extensions;
}
@@ -416,33 +558,37 @@ static BOOL
HasMagicHeader(FreeImageIO *io, fi_handle handle) {
const unsigned signature_size = 32;
BYTE signature[signature_size] = { 0 };
-
- // Canon (CR2), Intel byte order
+ /*
+ note: classic TIFF signature is
+ { 0x49, 0x49, 0x2A, 0x00 } Classic TIFF, little-endian
+ { 0x4D, 0x4D, 0x00, 0x2A } Classic TIFF, big-endian
+ */
+ // Canon (CR2), little-endian byte order
const BYTE CR2_II[] = { 0x49, 0x49, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x43, 0x52, 0x02, 0x00 };
- // Canon (CR2), Motorola byte order
- const BYTE CR2_MM[] = { 0x4D, 0x4D, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x43, 0x52, 0x02, 0x00 };
- // Canon (CRW), Intel byte order
- const BYTE CRW_II[] = { 0x49, 0x49, 0x1A, 0x00, 0x00, 0x00, 0x48, 0x45, 0x41, 0x50, 0x43, 0x43, 0x44, 0x52, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ // Canon (CRW), little-endian byte order
+ const BYTE CRW_II[] = { 0x49, 0x49, 0x1A, 0x00, 0x00, 0x00, 0x48, 0x45, 0x41, 0x50, 0x43, 0x43, 0x44, 0x52, 0x02, 0x00 };
// Minolta (MRW)
const BYTE MRW[] = { 0x00, 0x4D, 0x52, 0x4D, 0x00 };
- // Olympus (ORF), Intel byte order
+ // Olympus (ORF), little-endian byte order
const BYTE ORF_IIRS[] = { 0x49, 0x49, 0x52, 0x53, 0x08, 0x00, 0x00, 0x00 };
const BYTE ORF_IIRO[] = { 0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00 };
- // Olympus (ORF), Motorola byte order
+ // Olympus (ORF), big-endian byte order
const BYTE ORF_MMOR[] = { 0x4D, 0x4D, 0x4F, 0x52, 0x00, 0x00, 0x00, 0x08 };
// Fujifilm (RAF)
- const BYTE RAF[] = { 0x46, 0x55, 0x4A, 0x49, 0x46, 0x49, 0x4C, 0x4D, 0x43, 0x43, 0x44, 0x2D, 0x52, 0x41, 0x57, 0x20, 0x30, 0x32, 0x30, 0x31 };
- // Panasonic (RW2) or Leica (RWL)
- const BYTE RW2_II[] = { 0x49, 0x49, 0x55, 0x00, 0x18, 0x00, 0x00, 0x00, 0x88, 0xE7, 0x74, 0xD8, 0xF8, 0x25, 0x1D, 0x4D, 0x94, 0x7A, 0x6E, 0x77, 0x82, 0x2B, 0x5D, 0x6A };
+ const BYTE RAF[] = { 0x46, 0x55, 0x4A, 0x49, 0x46, 0x49, 0x4C, 0x4D, 0x43, 0x43, 0x44, 0x2D, 0x52, 0x41, 0x57, 0x20 };
+ // Panasonic (RW2) or Leica (RWL), little-endian byte order
+ const BYTE RWx_II[] = { 0x49, 0x49, 0x55, 0x00, 0x18, 0x00, 0x00, 0x00, 0x88, 0xE7, 0x74, 0xD8, 0xF8, 0x25, 0x1D, 0x4D, 0x94, 0x7A, 0x6E, 0x77, 0x82, 0x2B, 0x5D, 0x6A };
+ // Panasonic (RAW) or Leica (RAW), little-endian byte order
+ const BYTE RAW_II[] = { 0x49, 0x49, 0x55, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00 };
+ // Foveon (X3F)
+ const BYTE X3F[] = { 0x46, 0x4F, 0x56, 0x62 };
if(io->read_proc(signature, 1, signature_size, handle) != signature_size) {
return FALSE;
}
if(memcmp(CR2_II, signature, 12) == 0)
return TRUE;
- if(memcmp(CR2_MM, signature, 12) == 0)
- return TRUE;
- if(memcmp(CRW_II, signature, 26) == 0)
+ if(memcmp(CRW_II, signature, 16) == 0)
return TRUE;
if(memcmp(MRW, signature, 5) == 0)
return TRUE;
@@ -452,9 +598,13 @@ HasMagicHeader(FreeImageIO *io, fi_handle handle) {
return TRUE;
if(memcmp(ORF_MMOR, signature, 8) == 0)
return TRUE;
- if(memcmp(RAF, signature, 20) == 0)
+ if(memcmp(RAF, signature, 16) == 0)
return TRUE;
- if(memcmp(RW2_II, signature, 24) == 0)
+ if(memcmp(RWx_II, signature, 24) == 0)
+ return TRUE;
+ if(memcmp(RAW_II, signature, 18) == 0)
+ return TRUE;
+ if(memcmp(X3F, signature, 4) == 0)
return TRUE;
return FALSE;
@@ -547,6 +697,8 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
RawProcessor->imgdata.params.shot_select = 0;
// (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb)
RawProcessor->imgdata.params.use_camera_wb = 1;
+ // (-M) Use any color matrix from the camera metadata. This option only affects Olympus, Leaf, and Phase One cameras.
+ RawProcessor->imgdata.params.use_camera_matrix = 1;
// (-h) outputs the image in 50% size
RawProcessor->imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0;
@@ -559,6 +711,10 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
// header only mode
dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor->imgdata.sizes.width, RawProcessor->imgdata.sizes.height);
}
+ else if((flags & RAW_UNPROCESSED) == RAW_UNPROCESSED) {
+ // load raw data without post-processing (i.e. as a Bayer matrix)
+ dib = libraw_LoadUnprocessedData(RawProcessor);
+ }
else if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
// try to get the embedded JPEG
dib = libraw_LoadEmbeddedPreview(RawProcessor, 0);
diff --git a/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp b/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp
index f12d7286ce..84864308e0 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp
@@ -39,20 +39,20 @@
#endif
typedef struct tagTGAHEADER {
- BYTE id_length; // ID length
- BYTE color_map_type; // color map type
- BYTE image_type; // image type
-
- WORD cm_first_entry; // first entry index
- WORD cm_length; // color map length
- BYTE cm_size; // color map entry size, in bits
-
- WORD is_xorigin; // X-origin of image
- WORD is_yorigin; // Y-origin of image
- WORD is_width; // image width
- WORD is_height; // image height
- BYTE is_pixel_depth; // pixel depth
- BYTE is_image_descriptor; // image descriptor
+ BYTE id_length; //! length of the image ID field
+ BYTE color_map_type; //! whether a color map is included
+ BYTE image_type; //! compression and color types
+
+ WORD cm_first_entry; //! first entry index (offset into the color map table)
+ WORD cm_length; //! color map length (number of entries)
+ BYTE cm_size; //! color map entry size, in bits (number of bits per pixel)
+
+ WORD is_xorigin; //! X-origin of image (absolute coordinate of lower-left corner for displays where origin is at the lower left)
+ WORD is_yorigin; //! Y-origin of image (as for X-origin)
+ WORD is_width; //! image width
+ WORD is_height; //! image height
+ BYTE is_pixel_depth; //! bits per pixel
+ BYTE is_image_descriptor; //! image descriptor, bits 3-0 give the alpha channel depth, bits 5-4 give direction
} TGAHEADER;
typedef struct tagTGAEXTENSIONAREA {
@@ -400,14 +400,14 @@ Validate(FreeImageIO *io, fi_handle handle) {
}
// if the color map type is 1 then we validate the map entry information...
if(header.color_map_type > 0) {
- // It doesn't make any sense if the first entry is larger than the color map table
+ // it doesn't make any sense if the first entry is larger than the color map table
if(header.cm_first_entry >= header.cm_length) {
return FALSE;
}
- }
- // check header.cm_size, don't allow 0 or anything bigger than 32
- if(header.cm_size == 0 || header.cm_size > 32) {
- return FALSE;
+ // check header.cm_size, don't allow 0 or anything bigger than 32
+ if(header.cm_size == 0 || header.cm_size > 32) {
+ return FALSE;
+ }
}
// the width/height shouldn't be 0, right ?
if(header.is_width == 0 || header.is_height == 0) {
@@ -415,9 +415,9 @@ Validate(FreeImageIO *io, fi_handle handle) {
}
// let's now verify all the types that are supported by FreeImage (this is our final verification)
switch(header.image_type) {
- case TGA_CMAP :
+ case TGA_CMAP:
case TGA_RGB:
- case TGA_MONO :
+ case TGA_MONO:
case TGA_RLECMAP:
case TGA_RLERGB:
case TGA_RLEMONO:
@@ -435,8 +435,6 @@ Validate(FreeImageIO *io, fi_handle handle) {
return FALSE;
}
}
-
- return FALSE;
}
static BOOL DLL_CALLCONV
@@ -1339,7 +1337,7 @@ Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void
header.is_width = (WORD)FreeImage_GetWidth(dib);
header.is_height = (WORD)FreeImage_GetHeight(dib);
header.is_pixel_depth = (BYTE)bpp;
- header.is_image_descriptor = 0;
+ header.is_image_descriptor = (bpp == 32 ? 8 : 0);
if (palette) {
header.color_map_type = 1;
diff --git a/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp b/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp
index 4e502c56e8..1b454531c1 100644
--- a/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp
+++ b/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp
@@ -44,29 +44,22 @@
#include "FreeImageIO.h"
#include "PSDParser.h"
-// ----------------------------------------------------------
-// geotiff interface (see XTIFF.cpp)
-// ----------------------------------------------------------
-
-// Extended TIFF Directory GEO Tag Support
+// --------------------------------------------------------------------------
+// GeoTIFF profile (see XTIFF.cpp)
+// --------------------------------------------------------------------------
void XTIFFInitialize();
+BOOL tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib);
+BOOL tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib);
-// GeoTIFF profile
-void tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib);
-void tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib);
-
-// ----------------------------------------------------------
-// exif interface (see XTIFF.cpp)
+// --------------------------------------------------------------------------
+// TIFF Exif profile (see XTIFF.cpp)
// ----------------------------------------------------------
-
-// TIFF Exif profile
BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib);
BOOL tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib);
-// ----------------------------------------------------------
+// --------------------------------------------------------------------------
// LogLuv conversion functions interface (see TIFFLogLuv.cpp)
-// ----------------------------------------------------------
-
+// --------------------------------------------------------------------------
void tiff_ConvertLineXYZToRGB(BYTE *target, BYTE *source, double stonits, int width_in_pixels);
void tiff_ConvertLineRGBToXYZ(BYTE *target, BYTE *source, int width_in_pixels);
@@ -141,13 +134,13 @@ typedef struct {
static tmsize_t
_tiffReadProc(thandle_t handle, void *buf, tmsize_t size) {
fi_TIFFIO *fio = (fi_TIFFIO*)handle;
- return fio->io->read_proc(buf, size, 1, fio->handle) * size;
+ return fio->io->read_proc(buf, (unsigned)size, 1, fio->handle) * size;
}
static tmsize_t
_tiffWriteProc(thandle_t handle, void *buf, tmsize_t size) {
fi_TIFFIO *fio = (fi_TIFFIO*)handle;
- return fio->io->write_proc(buf, size, 1, fio->handle) * size;
+ return fio->io->write_proc(buf, (unsigned)size, 1, fio->handle) * size;
}
static toff_t
@@ -192,21 +185,12 @@ Open a TIFF file descriptor for reading or writing
TIFF *
TIFFFdOpen(thandle_t handle, const char *name, const char *mode) {
TIFF *tif;
-
// Open the file; the callback will set everything up
tif = TIFFClientOpen(name, mode, handle,
_tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
_tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
- // Warning: tif_fd is declared as 'int' currently (see libTIFF),
- // may result in incorrect file pointers inside libTIFF on
- // 64bit machines (sizeof(int) != sizeof(long)).
- // Needs to be fixed within libTIFF.
- if (tif) {
- tif->tif_fd = (long)handle;
- }
-
return tif;
}
@@ -933,7 +917,6 @@ tiff_write_xmp_profile(TIFF *tiff, FIBITMAP *dib) {
static BOOL
tiff_write_exif_profile(TIFF *tiff, FIBITMAP *dib) {
BOOL bResult = FALSE;
- uint32 exif_offset = 0;
// write EXIF_MAIN tags, EXIF_EXIF not supported yet
bResult = tiff_write_exif_tags(tiff, TagLib::EXIF_MAIN, dib);
@@ -1062,6 +1045,8 @@ Open(FreeImageIO *io, fi_handle handle, BOOL read) {
if (read) {
fio->tif = TIFFFdOpen((thandle_t)fio, "", "r");
} else {
+ // mode = "w" : write Classic TIFF
+ // mode = "w8" : write Big TIFF
fio->tif = TIFFFdOpen((thandle_t)fio, "", "w");
}
if(fio->tif == NULL) {
@@ -1106,11 +1091,10 @@ PageCount(FreeImageIO *io, fi_handle handle, void *data) {
check for uncommon bitspersample values (e.g. 10, 12, ...)
@param photometric TIFFTAG_PHOTOMETRIC tiff tag
@param bitspersample TIFFTAG_BITSPERSAMPLE tiff tag
-@param samplesperpixel TIFFTAG_SAMPLESPERPIXEL tiff tag
@return Returns FALSE if a uncommon bit-depth is encountered, returns TRUE otherwise
*/
static BOOL
-IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) {
+IsValidBitsPerSample(uint16 photometric, uint16 bitspersample) {
switch(bitspersample) {
case 1:
@@ -1131,7 +1115,12 @@ IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesper
}
break;
case 32:
- return TRUE;
+ if((photometric == PHOTOMETRIC_MINISWHITE) || (photometric == PHOTOMETRIC_MINISBLACK) || (photometric == PHOTOMETRIC_LOGLUV)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ break;
case 64:
case 128:
if(photometric == PHOTOMETRIC_MINISBLACK) {
@@ -1376,7 +1365,7 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
// check for unsupported formats
// ---------------------------------------------------------------------------------
- if(IsValidBitsPerSample(photometric, bitspersample, samplesperpixel) == FALSE) {
+ if(IsValidBitsPerSample(photometric, bitspersample) == FALSE) {
FreeImage_OutputMessageProc(s_format_id,
"Unable to handle this format: bitspersample = %d, samplesperpixel = %d, photometric = %d",
(int)bitspersample, (int)samplesperpixel, (int)photometric);
@@ -2029,8 +2018,8 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
// calculate src line and dst pitch
int dst_pitch = FreeImage_GetPitch(dib);
- int tileRowSize = TIFFTileRowSize(tif);
- int imageRowSize = TIFFScanlineSize(tif);
+ uint32 tileRowSize = (uint32)TIFFTileRowSize(tif);
+ uint32 imageRowSize = (uint32)TIFFScanlineSize(tif);
// In the tiff file the lines are saved from up to down
@@ -2038,11 +2027,10 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
- uint32 x, y, rowSize;
- for (y = 0; y < height; y += tileHeight) {
+ for (uint32 y = 0; y < height; y += tileHeight) {
int32 nrows = (y + tileHeight > height ? height - y : tileHeight);
- for (x = 0, rowSize = 0; x < width; x += tileWidth, rowSize += tileRowSize) {
+ for (uint32 x = 0, rowSize = 0; x < width; x += tileWidth, rowSize += tileRowSize) {
memset(tileBuffer, 0, tileSize);
// read one tile
diff --git a/plugins/AdvaImg/src/FreeImage/WuQuantizer.cpp b/plugins/AdvaImg/src/FreeImage/WuQuantizer.cpp
index 041eae368b..66d37066bf 100644
--- a/plugins/AdvaImg/src/FreeImage/WuQuantizer.cpp
+++ b/plugins/AdvaImg/src/FreeImage/WuQuantizer.cpp
@@ -108,22 +108,43 @@ WuQuantizer::Hist3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2, int R
for(i = 0; i < 256; i++)
table[i] = i * i;
- 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;
+ 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;
+ }
}
}