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 = 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_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 bitmap ... FreeImage_Aligned_Free(dib->data); } free(dib); // ... and the wrapper } }
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; }
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; tagmap = (*metadata)[model]; if(key != NULL) { if(!tagmap) { // this model, doesn't exist: create it tagmap = new TAGMAP(); (*metadata)[model] = tagmap; } // first check the tag if(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)) { // invalid data count ? return FALSE; } } // 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 { // 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)[model] = NULL; } } return TRUE; }
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; tagmap = (*metadata)[model]; if(!tagmap) { // this model, doesn't exist: return return 0; } // get the tag count return tagmap->size(); }
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_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; }
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; }