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; }
BOOL fipImage::getMetadata(FREE_IMAGE_MDMODEL model, const char *key, fipTag& tag) const { FITAG *searchedTag = NULL; FreeImage_GetMetadata(model, _dib, key, &searchedTag); if(searchedTag != NULL) { tag = FreeImage_CloneTag(searchedTag); return TRUE; } else { // clear the tag tag = (FITAG*)NULL; } return FALSE; }
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; }
FIBITMAP * DLL_CALLCONV FreeImage_Clone(FIBITMAP *dib) { if(!dib) return NULL; unsigned width = FreeImage_GetWidth(dib); unsigned height = FreeImage_GetHeight(dib); unsigned bpp = FreeImage_GetBPP(dib); // allocate a new dib FIBITMAP *new_dib = FreeImage_AllocateT(FreeImage_GetImageType(dib), 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 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 unsigned dib_size = FreeImage_GetImageSize(width, height, bpp); // 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; // 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 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; } } return new_dib; } 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; }
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; }