Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/BitmapAccess.cpp view on Meta::CPAN
// Design and implementation by
// - Floris van den Berg (flvdberg@wxs.nl)
// - Hervé Drolon (drolon@infonie.fr)
// - Detlev Vendt (detlev.vendt@brillit.de)
// - Petr Supina (psup@centrum.cz)
// - Carsten Klein (c.klein@datagis.com)
// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
//
// This file is part of FreeImage 3
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.
//
// Use at your own risk!
// ==========================================================
#ifdef _MSC_VER
#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
#endif
#include <stdlib.h>
#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__)
#include <malloc.h>
#endif // _WIN32 || _WIN64 || __MINGW32__
#include "FreeImage.h"
#include "FreeImageIO.h"
#include "Utilities.h"
#include "MapIntrospector.h"
#include "../Metadata/FreeImageTag.h"
/**
Constants for the BITMAPINFOHEADER::biCompression field
BI_RGB:
The bitmap is in uncompressed red green blue (RGB) format that is not compressed and does not use color masks.
BI_BITFIELDS:
The bitmap is not compressed and the color table consists of three DWORD color masks that specify the red, green, and blue components,
respectively, of each pixel. This is valid when used with 16 and 32-bits per pixel bitmaps.
*/
#ifndef _WINGDI_
#define BI_RGB 0L
#define BI_BITFIELDS 3L
#endif // _WINGDI_
// ----------------------------------------------------------
// Metadata definitions
// ----------------------------------------------------------
/** helper for map<key, value> where value is a pointer to a FreeImage tag */
typedef std::map<std::string, FITAG*> TAGMAP;
/** helper for map<FREE_IMAGE_MDMODEL, TAGMAP*> */
typedef std::map<int, TAGMAP*> METADATAMAP;
/** helper for metadata iterator */
FI_STRUCT (METADATAHEADER) {
long pos; //! current position when iterating the map
TAGMAP *tagmap; //! pointer to the tag map
};
// ----------------------------------------------------------
// FIBITMAP definition
// ----------------------------------------------------------
/**
FreeImage header structure
*/
FI_STRUCT (FREEIMAGEHEADER) {
/** data type - bitmap, array of long, double, complex, etc */
FREE_IMAGE_TYPE type;
/** background color used for RGB transparency */
RGBQUAD bkgnd_color;
/**@name transparency management */
//@{
/**
why another table ? for easy transparency table retrieval !
transparency could be stored in the palette, which is better
overall, but it requires quite some changes and it will render
FreeImage_GetTransparencyTable obsolete in its current form;
*/
BYTE transparent_table[256];
/** number of transparent colors */
int transparency_count;
/** TRUE if the image is transparent */
BOOL transparent;
//@}
/** space to hold ICC profile */
FIICCPROFILE iccProfile;
/** contains a list of metadata models attached to the bitmap */
METADATAMAP *metadata;
/** FALSE if the FIBITMAP only contains the header and no pixel data */
BOOL has_pixels;
/** optionally contains a thumbnail attached to the bitmap */
FIBITMAP *thumbnail;
/**@name external pixel buffer management */
//@{
/** pointer to user provided pixels, NULL otherwise */
BYTE *external_bits;
/** user provided pitch, 0 otherwise */
unsigned external_pitch;
//@}
//BYTE filler[1]; // fill to 32-bit alignment
};
// ----------------------------------------------------------
// FREEIMAGERGBMASKS definition
// ----------------------------------------------------------
/**
RGB mask structure - mainly used for 16-bit RGB555 / RGB 565 FIBITMAP
*/
FI_STRUCT (FREEIMAGERGBMASKS) {
unsigned red_mask; //! bit layout of the red components
unsigned green_mask; //! bit layout of the green components
unsigned blue_mask; //! bit layout of the blue components
};
// ----------------------------------------------------------
// Memory allocation on a specified alignment boundary
// ----------------------------------------------------------
#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
assert(alignment == FIBITMAP_ALIGNMENT);
return _aligned_malloc(amount, alignment);
}
void FreeImage_Aligned_Free(void* mem) {
_aligned_free(mem);
}
#elif defined (__MINGW32__)
void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
assert(alignment == FIBITMAP_ALIGNMENT);
return __mingw_aligned_malloc (amount, alignment);
}
void FreeImage_Aligned_Free(void* mem) {
__mingw_aligned_free (mem);
}
#else
void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
src/Source/FreeImage/BitmapAccess.cpp view on Meta::CPAN
case FIT_RGBA16:
bpp = 8 * sizeof(FIRGBA16);
break;
case FIT_RGBF:
bpp = 8 * sizeof(FIRGBF);
break;
case FIT_RGBAF:
bpp = 8 * sizeof(FIRGBAF);
break;
default:
return NULL;
}
FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP));
if (bitmap != NULL) {
// calculate the size of a FreeImage image
// align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
// palette is aligned on a 16 bytes boundary
// pixels are aligned on a 16 bytes boundary
// when using a user provided pixel buffer, force a 'header only' allocation
size_t dib_size = FreeImage_GetInternalImageSize(header_only || ext_bits, width, height, bpp, need_masks);
if(dib_size == 0) {
// memory allocation will fail (probably a malloc overflow)
free(bitmap);
return NULL;
}
bitmap->data = (BYTE *)FreeImage_Aligned_Malloc(dib_size * sizeof(BYTE), FIBITMAP_ALIGNMENT);
if (bitmap->data != NULL) {
memset(bitmap->data, 0, dib_size);
// write out the FREEIMAGEHEADER
FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)bitmap->data;
fih->type = type;
memset(&fih->bkgnd_color, 0, sizeof(RGBQUAD));
fih->transparent = FALSE;
fih->transparency_count = 0;
memset(fih->transparent_table, 0xff, 256);
fih->has_pixels = header_only ? FALSE : TRUE;
// initialize FIICCPROFILE link
FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap);
iccProfile->size = 0;
iccProfile->data = 0;
iccProfile->flags = 0;
// initialize metadata models list
fih->metadata = new(std::nothrow) METADATAMAP;
// initialize attached thumbnail
fih->thumbnail = NULL;
// store a pointer to user provided pixel buffer (if any)
fih->external_bits = ext_bits;
fih->external_pitch = ext_pitch;
// write out the BITMAPINFOHEADER
BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(bitmap);
bih->biSize = sizeof(BITMAPINFOHEADER);
bih->biWidth = width;
bih->biHeight = height;
bih->biPlanes = 1;
bih->biCompression = need_masks ? BI_BITFIELDS : BI_RGB;
bih->biBitCount = (WORD)bpp;
bih->biClrUsed = CalculateUsedPaletteEntries(bpp);
bih->biClrImportant = bih->biClrUsed;
bih->biXPelsPerMeter = 2835; // 72 dpi
bih->biYPelsPerMeter = 2835; // 72 dpi
if(bpp == 8) {
// build a default greyscale palette (very useful for image processing)
RGBQUAD *pal = FreeImage_GetPalette(bitmap);
for(int i = 0; i < 256; i++) {
pal[i].rgbRed = (BYTE)i;
pal[i].rgbGreen = (BYTE)i;
pal[i].rgbBlue = (BYTE)i;
}
}
// just setting the masks (only if needed) just like the palette.
if (need_masks) {
FREEIMAGERGBMASKS *masks = FreeImage_GetRGBMasks(bitmap);
masks->red_mask = red_mask;
masks->green_mask = green_mask;
masks->blue_mask = blue_mask;
}
return bitmap;
}
free(bitmap);
}
return NULL;
}
FIBITMAP * DLL_CALLCONV
FreeImage_AllocateHeaderForBits(BYTE *ext_bits, unsigned ext_pitch, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
return FreeImage_AllocateBitmap(FALSE, ext_bits, ext_pitch, type, width, height, bpp, red_mask, green_mask, blue_mask);
}
FIBITMAP * DLL_CALLCONV
FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
return FreeImage_AllocateBitmap(header_only, NULL, 0, type, width, height, bpp, red_mask, green_mask, blue_mask);
}
FIBITMAP * DLL_CALLCONV
FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
return FreeImage_AllocateBitmap(header_only, NULL, 0, FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask);
}
FIBITMAP * DLL_CALLCONV
FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
return FreeImage_AllocateBitmap(FALSE, NULL, 0, FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask);
}
FIBITMAP * DLL_CALLCONV
FreeImage_AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
return FreeImage_AllocateBitmap(FALSE, NULL, 0, type, width, height, bpp, red_mask, green_mask, blue_mask);
}
void DLL_CALLCONV
FreeImage_Unload(FIBITMAP *dib) {
if (NULL != dib) {
if (NULL != dib->data) {
// delete possible icc profile ...
if (FreeImage_GetICCProfile(dib)->data) {
free(FreeImage_GetICCProfile(dib)->data);
}
// delete metadata models
METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
for(METADATAMAP::iterator i = (*metadata).begin(); i != (*metadata).end(); i++) {
TAGMAP *tagmap = (*i).second;
if(tagmap) {
for(TAGMAP::iterator j = tagmap->begin(); j != tagmap->end(); j++) {
FITAG *tag = (*j).second;
FreeImage_DeleteTag(tag);
}
delete tagmap;
}
}
delete metadata;
// delete embedded thumbnail
FreeImage_Unload(FreeImage_GetThumbnail(dib));
// delete bitmap ...
FreeImage_Aligned_Free(dib->data);
}
free(dib); // ... and the wrapper
}
}
// ----------------------------------------------------------
FIBITMAP * DLL_CALLCONV
FreeImage_Clone(FIBITMAP *dib) {
if(!dib) {
return NULL;
}
FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib);
unsigned width = FreeImage_GetWidth(dib);
unsigned height = FreeImage_GetHeight(dib);
unsigned bpp = FreeImage_GetBPP(dib);
const BYTE *ext_bits = ((FREEIMAGEHEADER *)dib->data)->external_bits;
// check for pixel availability ...
BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE;
// check whether this image has masks defined ...
BOOL need_masks = (bpp == 16 && type == FIT_BITMAP) ? TRUE : FALSE;
// allocate a new dib
FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, type, width, height, bpp,
FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib));
if (new_dib) {
// save ICC profile links
FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib);
FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib);
// save metadata links
METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata;
// calculate the size of the src image
// align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
// palette is aligned on a 16 bytes boundary
// pixels are aligned on a 16 bytes boundary
// when using a user provided pixel buffer, force a 'header only' calculation
size_t dib_size = FreeImage_GetInternalImageSize(header_only || ext_bits, width, height, bpp, need_masks);
// copy the bitmap + internal pointers (remember to restore new_dib internal pointers later)
memcpy(new_dib->data, dib->data, dib_size);
// reset ICC profile link for new_dib
memset(dst_iccProfile, 0, sizeof(FIICCPROFILE));
// restore metadata link for new_dib
((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata;
// reset thumbnail link for new_dib
((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL;
// copy possible ICC profile
FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size);
dst_iccProfile->flags = src_iccProfile->flags;
// copy metadata models
for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
int model = (*i).first;
TAGMAP *src_tagmap = (*i).second;
if(src_tagmap) {
// create a metadata model
TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP();
if(dst_tagmap) {
// fill the model
for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
std::string dst_key = (*j).first;
FITAG *dst_tag = FreeImage_CloneTag( (*j).second );
// assign key and tag value
(*dst_tagmap)[dst_key] = dst_tag;
}
// assign model and tagmap
(*dst_metadata)[model] = dst_tagmap;
}
}
}
// copy the thumbnail
FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib));
// copy user provided pixel buffer (if any)
if(ext_bits) {
const unsigned pitch = FreeImage_GetPitch(dib);
const unsigned linesize = FreeImage_GetLine(dib);
for(unsigned y = 0; y < height; y++) {
memcpy(FreeImage_GetScanLine(new_dib, y), ext_bits, linesize);
ext_bits += pitch;
}
}
return new_dib;
}
return NULL;
}
// ----------------------------------------------------------
BYTE * DLL_CALLCONV
FreeImage_GetBits(FIBITMAP *dib) {
if(!FreeImage_HasPixels(dib)) {
return NULL;
}
if(((FREEIMAGEHEADER *)dib->data)->external_bits) {
return ((FREEIMAGEHEADER *)dib->data)->external_bits;
}
// returns the pixels aligned on a FIBITMAP_ALIGNMENT bytes alignment boundary
size_t lp = (size_t)FreeImage_GetInfoHeader(dib);
lp += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * FreeImage_GetColorsUsed(dib);
lp += FreeImage_HasRGBMasks(dib) ? sizeof(DWORD) * 3 : 0;
lp += (lp % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - lp % FIBITMAP_ALIGNMENT : 0);
return (BYTE *)lp;
src/Source/FreeImage/BitmapAccess.cpp view on Meta::CPAN
unsigned DLL_CALLCONV
FreeImage_GetColorsUsed(FIBITMAP *dib) {
return dib ? FreeImage_GetInfoHeader(dib)->biClrUsed : 0;
}
unsigned DLL_CALLCONV
FreeImage_GetDIBSize(FIBITMAP *dib) {
return (dib) ? sizeof(BITMAPINFOHEADER) + (FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD)) + (FreeImage_GetPitch(dib) * FreeImage_GetHeight(dib)) : 0;
}
RGBQUAD * DLL_CALLCONV
FreeImage_GetPalette(FIBITMAP *dib) {
return (dib && FreeImage_GetBPP(dib) < 16) ? (RGBQUAD *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL;
}
unsigned DLL_CALLCONV
FreeImage_GetDotsPerMeterX(FIBITMAP *dib) {
return (dib) ? FreeImage_GetInfoHeader(dib)->biXPelsPerMeter : 0;
}
unsigned DLL_CALLCONV
FreeImage_GetDotsPerMeterY(FIBITMAP *dib) {
return (dib) ? FreeImage_GetInfoHeader(dib)->biYPelsPerMeter : 0;
}
void DLL_CALLCONV
FreeImage_SetDotsPerMeterX(FIBITMAP *dib, unsigned res) {
if(dib) {
FreeImage_GetInfoHeader(dib)->biXPelsPerMeter = res;
}
}
void DLL_CALLCONV
FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res) {
if(dib) {
FreeImage_GetInfoHeader(dib)->biYPelsPerMeter = res;
}
}
BITMAPINFOHEADER * DLL_CALLCONV
FreeImage_GetInfoHeader(FIBITMAP *dib) {
if(!dib) {
return NULL;
}
size_t lp = (size_t)dib->data + sizeof(FREEIMAGEHEADER);
lp += (lp % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - lp % FIBITMAP_ALIGNMENT : 0);
lp += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT;
return (BITMAPINFOHEADER *)lp;
}
BITMAPINFO * DLL_CALLCONV
FreeImage_GetInfo(FIBITMAP *dib) {
return (BITMAPINFO *)FreeImage_GetInfoHeader(dib);
}
// ----------------------------------------------------------
// Metadata routines
// ----------------------------------------------------------
FIMETADATA * DLL_CALLCONV
FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag) {
if(!dib) {
return NULL;
}
// get the metadata model
METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
TAGMAP *tagmap = NULL;
if( (*metadata).find(model) != (*metadata).end() ) {
tagmap = (*metadata)[model];
}
if(tagmap) {
// allocate a handle
FIMETADATA *handle = (FIMETADATA *)malloc(sizeof(FIMETADATA));
if(handle) {
// calculate the size of a METADATAHEADER
int header_size = sizeof(METADATAHEADER);
handle->data = (BYTE *)malloc(header_size * sizeof(BYTE));
if(handle->data) {
memset(handle->data, 0, header_size * sizeof(BYTE));
// write out the METADATAHEADER
METADATAHEADER *mdh = (METADATAHEADER *)handle->data;
mdh->pos = 1;
mdh->tagmap = tagmap;
// get the first element
TAGMAP::iterator i = tagmap->begin();
*tag = (*i).second;
return handle;
}
free(handle);
}
}
return NULL;
}
BOOL DLL_CALLCONV
FreeImage_FindNextMetadata(FIMETADATA *mdhandle, FITAG **tag) {
if(!mdhandle) {
return FALSE;
}
METADATAHEADER *mdh = (METADATAHEADER *)mdhandle->data;
TAGMAP *tagmap = mdh->tagmap;
int current_pos = mdh->pos;
int mapsize = (int)tagmap->size();
if(current_pos < mapsize) {
// get the tag element at position pos
int count = 0;
for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) {
if(count == current_pos) {
*tag = (*i).second;
mdh->pos++;
break;
}
count++;
}
return TRUE;
}
return FALSE;
}
void DLL_CALLCONV
FreeImage_FindCloseMetadata(FIMETADATA *mdhandle) {
if (NULL != mdhandle) { // delete the handle
if (NULL != mdhandle->data) {
free(mdhandle->data);
}
free(mdhandle); // ... and the wrapper
}
}
// ----------------------------------------------------------
BOOL DLL_CALLCONV
FreeImage_CloneMetadata(FIBITMAP *dst, FIBITMAP *src) {
if(!src || !dst) {
return FALSE;
}
// get metadata links
METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)src->data)->metadata;
METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)dst->data)->metadata;
// copy metadata models, *except* the FIMD_ANIMATION model
for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
int model = (*i).first;
if(model == (int)FIMD_ANIMATION) {
continue;
}
TAGMAP *src_tagmap = (*i).second;
if(src_tagmap) {
if( dst_metadata->find(model) != dst_metadata->end() ) {
// destroy dst model
FreeImage_SetMetadata((FREE_IMAGE_MDMODEL)model, dst, NULL, NULL);
}
// create a metadata model
TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP();
if(dst_tagmap) {
// fill the model
for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
std::string dst_key = (*j).first;
FITAG *dst_tag = FreeImage_CloneTag( (*j).second );
// assign key and tag value
(*dst_tagmap)[dst_key] = dst_tag;
}
// assign model and tagmap
(*dst_metadata)[model] = dst_tagmap;
}
}
}
// clone resolution
FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src));
FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src));
return TRUE;
}
// ----------------------------------------------------------
BOOL DLL_CALLCONV
FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag) {
if(!dib) {
return FALSE;
}
TAGMAP *tagmap = NULL;
// get the metadata model
METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
METADATAMAP::iterator model_iterator = metadata->find(model);
if (model_iterator != metadata->end()) {
tagmap = model_iterator->second;
}
if(key != NULL) {
if(!tagmap) {
// this model, doesn't exist: create it
tagmap = new(std::nothrow) TAGMAP();
(*metadata)[model] = tagmap;
}
if(tag) {
// first check the tag
if(FreeImage_GetTagKey(tag) == NULL) {
FreeImage_SetTagKey(tag, key);
} else if(strcmp(key, FreeImage_GetTagKey(tag)) != 0) {
// set the tag key
FreeImage_SetTagKey(tag, key);
}
if(FreeImage_GetTagCount(tag) * FreeImage_TagDataWidth(FreeImage_GetTagType(tag)) != FreeImage_GetTagLength(tag)) {
FreeImage_OutputMessageProc(FIF_UNKNOWN, "Invalid data count for tag '%s'", key);
return FALSE;
}
// fill the tag ID if possible and if it's needed
TagLib& tag_lib = TagLib::instance();
switch(model) {
case FIMD_IPTC:
{
int id = tag_lib.getTagID(TagLib::IPTC, key);
/*
if(id == -1) {
FreeImage_OutputMessageProc(FIF_UNKNOWN, "IPTC: Invalid key '%s'", key);
}
*/
FreeImage_SetTagID(tag, (WORD)id);
}
break;
default:
break;
}
// delete existing tag
FITAG *old_tag = (*tagmap)[key];
if(old_tag) {
FreeImage_DeleteTag(old_tag);
}
// create a new tag
(*tagmap)[key] = FreeImage_CloneTag(tag);
}
else {
// delete existing tag
TAGMAP::iterator i = tagmap->find(key);
if(i != tagmap->end()) {
FITAG *old_tag = (*i).second;
FreeImage_DeleteTag(old_tag);
tagmap->erase(key);
}
}
}
else {
// destroy the metadata model
if(tagmap) {
for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) {
FITAG *tag = (*i).second;
FreeImage_DeleteTag(tag);
}
delete tagmap;
metadata->erase(model_iterator);
}
}
return TRUE;
}
BOOL DLL_CALLCONV
FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG **tag) {
if(!dib || !key || !tag) {
return FALSE;
}
TAGMAP *tagmap = NULL;
*tag = NULL;
// get the metadata model
METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
if(!(*metadata).empty()) {
METADATAMAP::iterator model_iterator = metadata->find(model);
if (model_iterator != metadata->end() ) {
// this model exists : try to get the requested tag
tagmap = model_iterator->second;
TAGMAP::iterator tag_iterator = tagmap->find(key);
if (tag_iterator != tagmap->end() ) {
// get the requested tag
*tag = tag_iterator->second;
}
}
}
return (*tag != NULL) ? TRUE : FALSE;
}
/**
Build and set a FITAG whose type is FIDT_ASCII.
@param model Metadata model to be filled
@param dib Image to be filled
@param key Tag key
@param value Tag value as a ASCII string
@return Returns TRUE if successful, returns FALSE otherwise
*/
BOOL DLL_CALLCONV
FreeImage_SetMetadataKeyValue(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, const char *value) {
if(!dib || !key || !value) {
return FALSE;
}
// create a tag
FITAG *tag = FreeImage_CreateTag();
if(tag) {
BOOL bSuccess = TRUE;
// fill the tag
DWORD tag_length = (DWORD)(strlen(value) + 1);
bSuccess &= FreeImage_SetTagKey(tag, key);
bSuccess &= FreeImage_SetTagLength(tag, tag_length);
bSuccess &= FreeImage_SetTagCount(tag, tag_length);
bSuccess &= FreeImage_SetTagType(tag, FIDT_ASCII);
bSuccess &= FreeImage_SetTagValue(tag, value);
if(bSuccess) {
// set the tag
bSuccess &= FreeImage_SetMetadata(model, dib, FreeImage_GetTagKey(tag), tag);
}
// delete the tag
FreeImage_DeleteTag(tag);
return bSuccess;
}
return FALSE;
}
// ----------------------------------------------------------
unsigned DLL_CALLCONV
FreeImage_GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP *dib) {
if(!dib) {
return FALSE;
}
TAGMAP *tagmap = NULL;
// get the metadata model
METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
if( (*metadata).find(model) != (*metadata).end() ) {
tagmap = (*metadata)[model];
}
if(!tagmap) {
// this model, doesn't exist: return
return 0;
}
// get the tag count
return (unsigned)tagmap->size();
}
// ----------------------------------------------------------
unsigned DLL_CALLCONV
FreeImage_GetMemorySize(FIBITMAP *dib) {
if (!dib) {
return 0;
}
FREEIMAGEHEADER *header = (FREEIMAGEHEADER *)dib->data;
BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(dib);
BOOL header_only = !header->has_pixels || header->external_bits != NULL;
BOOL need_masks = bih->biCompression == BI_BITFIELDS;
unsigned width = bih->biWidth;
unsigned height = bih->biHeight;
unsigned bpp = bih->biBitCount;
// start off with the size of the FIBITMAP structure
size_t size = sizeof(FIBITMAP);
// add sizes of FREEIMAGEHEADER, BITMAPINFOHEADER, palette and DIB data
size += FreeImage_GetInternalImageSize(header_only, width, height, bpp, need_masks);
// add ICC profile size
size += header->iccProfile.size;
// add thumbnail image size
if (header->thumbnail) {
// we assume a thumbnail not having a thumbnail as well,
// so this recursive call should not create an infinite loop
size += FreeImage_GetMemorySize(header->thumbnail);
}
// add metadata size
METADATAMAP *md = header->metadata;
if (!md) {
return (unsigned)size;
}
// add size of METADATAMAP
size += sizeof(METADATAMAP);
const size_t models = md->size();
if (models == 0) {
return (unsigned)size;
}
unsigned tags = 0;
for (METADATAMAP::iterator i = md->begin(); i != md->end(); i++) {
TAGMAP *tm = i->second;
if (tm) {
for (TAGMAP::iterator j = tm->begin(); j != tm->end(); j++) {
++tags;
const std::string & key = j->first;
size += key.capacity();
size += FreeImage_GetTagMemorySize(j->second);
}
}
}
// add size of all TAGMAP instances
size += models * sizeof(TAGMAP);
// add size of tree nodes in METADATAMAP
size += MapIntrospector<METADATAMAP>::GetNodesMemorySize(models);
// add size of tree nodes in TAGMAP
size += MapIntrospector<TAGMAP>::GetNodesMemorySize(tags);
return (unsigned)size;
}
( run in 0.497 second using v1.01-cache-2.11-cpan-13bb782fe5a )