// ========================================================== // fipImage class implementation // // Design and implementation by // - Hervé Drolon (drolon@infonie.fr) // // This file is part of FreeImage 3 // // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER // THIS DISCLAIMER. // // Use at your own risk! // ========================================================== #include "FreeImagePlus.h" /////////////////////////////////////////////////////////////////// // Protected functions BOOL fipImage::replace(FIBITMAP *new_dib) { if(new_dib == NULL) return FALSE; if(_dib) FreeImage_Unload(_dib); _dib = new_dib; _bHasChanged = TRUE; return TRUE; } /////////////////////////////////////////////////////////////////// // Creation & Destruction fipImage::fipImage(FREE_IMAGE_TYPE image_type, unsigned width, unsigned height, unsigned bpp) { _dib = NULL; _bHasChanged = FALSE; if(width && height && bpp) setSize(image_type, width, height, bpp); } fipImage::~fipImage() { if(_dib) { FreeImage_Unload(_dib); _dib = NULL; } } BOOL fipImage::setSize(FREE_IMAGE_TYPE image_type, unsigned width, unsigned height, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { if(_dib) { FreeImage_Unload(_dib); } if((_dib = FreeImage_AllocateT(image_type, width, height, bpp, red_mask, green_mask, blue_mask)) == NULL) return FALSE; if(image_type == FIT_BITMAP) { // Create palette if needed switch(bpp) { case 1: case 4: case 8: RGBQUAD *pal = FreeImage_GetPalette(_dib); for(unsigned i = 0; i < FreeImage_GetColorsUsed(_dib); i++) { pal[i].rgbRed = i; pal[i].rgbGreen = i; pal[i].rgbBlue = i; } break; } } _bHasChanged = TRUE; return TRUE; } void fipImage::clear() { if(_dib) { FreeImage_Unload(_dib); _dib = NULL; } _bHasChanged = TRUE; } /////////////////////////////////////////////////////////////////// // Copying fipImage::fipImage(const fipImage& Image) { _dib = NULL; _fif = FIF_UNKNOWN; FIBITMAP *clone = FreeImage_Clone((FIBITMAP*)Image._dib); replace(clone); } fipImage& fipImage::operator=(const fipImage& Image) { if(this != &Image) { FIBITMAP *clone = FreeImage_Clone((FIBITMAP*)Image._dib); replace(clone); } return *this; } fipImage& fipImage::operator=(FIBITMAP *dib) { if(_dib != dib) { replace(dib); } return *this; } BOOL fipImage::copySubImage(fipImage& dst, int left, int top, int right, int bottom) const { if(_dib) { dst = FreeImage_Copy(_dib, left, top, right, bottom); return dst.isValid(); } return FALSE; } BOOL fipImage::pasteSubImage(fipImage& src, int left, int top, int alpha) { if(_dib) { BOOL bResult = FreeImage_Paste(_dib, src._dib, left, top, alpha); _bHasChanged = TRUE; return bResult; } return FALSE; } BOOL fipImage::crop(int left, int top, int right, int bottom) { if(_dib) { FIBITMAP *dst = FreeImage_Copy(_dib, left, top, right, bottom); return replace(dst); } return FALSE; } /////////////////////////////////////////////////////////////////// // Information functions FREE_IMAGE_TYPE fipImage::getImageType() const { return FreeImage_GetImageType(_dib); } unsigned fipImage::getWidth() const { return FreeImage_GetWidth(_dib); } unsigned fipImage::getHeight() const { return FreeImage_GetHeight(_dib); } unsigned fipImage::getScanWidth() const { return FreeImage_GetPitch(_dib); } BOOL fipImage::isValid() const { return (_dib != NULL) ? TRUE:FALSE; } BITMAPINFO* fipImage::getInfo() const { return FreeImage_GetInfo(_dib); } BITMAPINFOHEADER* fipImage::getInfoHeader() const { return FreeImage_GetInfoHeader(_dib); } LONG fipImage::getImageSize() const { return FreeImage_GetDIBSize(_dib); } unsigned fipImage::getBitsPerPixel() const { return FreeImage_GetBPP(_dib); } unsigned fipImage::getLine() const { return FreeImage_GetLine(_dib); } double fipImage::getHorizontalResolution() const { return (FreeImage_GetDotsPerMeterX(_dib) / (double)100); } double fipImage::getVerticalResolution() const { return (FreeImage_GetDotsPerMeterY(_dib) / (double)100); } void fipImage::setHorizontalResolution(double value) { FreeImage_SetDotsPerMeterX(_dib, (unsigned)(value * 100 + 0.5)); } void fipImage::setVerticalResolution(double value) { FreeImage_SetDotsPerMeterY(_dib, (unsigned)(value * 100 + 0.5)); } /////////////////////////////////////////////////////////////////// // Palette operations RGBQUAD* fipImage::getPalette() const { return FreeImage_GetPalette(_dib); } unsigned fipImage::getPaletteSize() const { return FreeImage_GetColorsUsed(_dib) * sizeof(RGBQUAD); } unsigned fipImage::getColorsUsed() const { return FreeImage_GetColorsUsed(_dib); } FREE_IMAGE_COLOR_TYPE fipImage::getColorType() const { return FreeImage_GetColorType(_dib); } BOOL fipImage::isGrayscale() const { return ((FreeImage_GetBPP(_dib) == 8) && (FreeImage_GetColorType(_dib) != FIC_PALETTE)); } /////////////////////////////////////////////////////////////////// // Pixel access BYTE* fipImage::accessPixels() const { return FreeImage_GetBits(_dib); } BYTE* fipImage::getScanLine(unsigned scanline) const { if(scanline < FreeImage_GetHeight(_dib)) { return FreeImage_GetScanLine(_dib, scanline); } return NULL; } BOOL fipImage::getPixelIndex(unsigned x, unsigned y, BYTE *value) const { return FreeImage_GetPixelIndex(_dib, x, y, value); } BOOL fipImage::getPixelColor(unsigned x, unsigned y, RGBQUAD *value) const { return FreeImage_GetPixelColor(_dib, x, y, value); } BOOL fipImage::setPixelIndex(unsigned x, unsigned y, BYTE *value) { _bHasChanged = TRUE; return FreeImage_SetPixelIndex(_dib, x, y, value); } BOOL fipImage::setPixelColor(unsigned x, unsigned y, RGBQUAD *value) { _bHasChanged = TRUE; return FreeImage_SetPixelColor(_dib, x, y, value); } /////////////////////////////////////////////////////////////////// // File type identification FREE_IMAGE_FORMAT fipImage::identifyFIF(const char* lpszPathName) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; // check the file signature and get its format // (the second argument is currently not used by FreeImage) fif = FreeImage_GetFileType(lpszPathName, 0); if(fif == FIF_UNKNOWN) { // no signature ? // try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilename(lpszPathName); } return fif; } FREE_IMAGE_FORMAT fipImage::identifyFIFU(const wchar_t* lpszPathName) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; // check the file signature and get its format // (the second argument is currently not used by FreeImage) fif = FreeImage_GetFileTypeU(lpszPathName, 0); if(fif == FIF_UNKNOWN) { // no signature ? // try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilenameU(lpszPathName); } return fif; } FREE_IMAGE_FORMAT fipImage::identifyFIFFromHandle(FreeImageIO *io, fi_handle handle) { if(io && handle) { // check the file signature and get its format return FreeImage_GetFileTypeFromHandle(io, handle, 16); } return FIF_UNKNOWN; } FREE_IMAGE_FORMAT fipImage::identifyFIFFromMemory(FIMEMORY *hmem) { if(hmem != NULL) { return FreeImage_GetFileTypeFromMemory(hmem, 0); } return FIF_UNKNOWN; } /////////////////////////////////////////////////////////////////// // Loading & Saving BOOL fipImage::load(const char* lpszPathName, int flag) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; // check the file signature and get its format // (the second argument is currently not used by FreeImage) fif = FreeImage_GetFileType(lpszPathName, 0); if(fif == FIF_UNKNOWN) { // no signature ? // try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilename(lpszPathName); } // check that the plugin has reading capabilities ... if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { // Free the previous dib if(_dib) { FreeImage_Unload(_dib); } // Load the file _dib = FreeImage_Load(fif, lpszPathName, flag); _bHasChanged = TRUE; if(_dib == NULL) return FALSE; return TRUE; } return FALSE; } BOOL fipImage::loadU(const wchar_t* lpszPathName, int flag) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; // check the file signature and get its format // (the second argument is currently not used by FreeImage) fif = FreeImage_GetFileTypeU(lpszPathName, 0); if(fif == FIF_UNKNOWN) { // no signature ? // try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilenameU(lpszPathName); } // check that the plugin has reading capabilities ... if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { // Free the previous dib if(_dib) { FreeImage_Unload(_dib); } // Load the file _dib = FreeImage_LoadU(fif, lpszPathName, flag); _bHasChanged = TRUE; if(_dib == NULL) return FALSE; return TRUE; } return FALSE; } BOOL fipImage::loadFromHandle(FreeImageIO *io, fi_handle handle, int flag) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; // check the file signature and get its format fif = FreeImage_GetFileTypeFromHandle(io, handle, 16); if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { // Free the previous dib if(_dib) { FreeImage_Unload(_dib); } // Load the file _dib = FreeImage_LoadFromHandle(fif, io, handle, flag); _bHasChanged = TRUE; if(_dib == NULL) return FALSE; return TRUE; } return FALSE; } BOOL fipImage::loadFromMemory(fipMemoryIO& memIO, int flag) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; // check the file signature and get its format fif = memIO.getFileType(); if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { // Free the previous dib if(_dib) { FreeImage_Unload(_dib); } // Load the file _dib = memIO.load(fif, flag); _bHasChanged = TRUE; if(_dib == NULL) return FALSE; return TRUE; } return FALSE; } BOOL fipImage::save(const char* lpszPathName, int flag) const { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; BOOL bSuccess = FALSE; // Try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilename(lpszPathName); if(fif != FIF_UNKNOWN ) { // Check that the dib can be saved in this format BOOL bCanSave; FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(_dib); if(image_type == FIT_BITMAP) { // standard bitmap type WORD bpp = FreeImage_GetBPP(_dib); bCanSave = (FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)); } else { // special bitmap type bCanSave = FreeImage_FIFSupportsExportType(fif, image_type); } if(bCanSave) { bSuccess = FreeImage_Save(fif, _dib, lpszPathName, flag); return bSuccess; } } return bSuccess; } BOOL fipImage::saveU(const wchar_t* lpszPathName, int flag) const { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; BOOL bSuccess = FALSE; // Try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilenameU(lpszPathName); if(fif != FIF_UNKNOWN ) { // Check that the dib can be saved in this format BOOL bCanSave; FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(_dib); if(image_type == FIT_BITMAP) { // standard bitmap type WORD bpp = FreeImage_GetBPP(_dib); bCanSave = (FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)); } else { // special bitmap type bCanSave = FreeImage_FIFSupportsExportType(fif, image_type); } if(bCanSave) { bSuccess = FreeImage_SaveU(fif, _dib, lpszPathName, flag); return bSuccess; } } return bSuccess; } BOOL fipImage::saveToHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flag) const { BOOL bSuccess = FALSE; if(fif != FIF_UNKNOWN ) { // Check that the dib can be saved in this format BOOL bCanSave; FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(_dib); if(image_type == FIT_BITMAP) { // standard bitmap type WORD bpp = FreeImage_GetBPP(_dib); bCanSave = (FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)); } else { // special bitmap type bCanSave = FreeImage_FIFSupportsExportType(fif, image_type); } if(bCanSave) { bSuccess = FreeImage_SaveToHandle(fif, _dib, io, handle, flag); return bSuccess; } } return bSuccess; } BOOL fipImage::saveToMemory(FREE_IMAGE_FORMAT fif, fipMemoryIO& memIO, int flag) const { BOOL bSuccess = FALSE; if(fif != FIF_UNKNOWN ) { // Check that the dib can be saved in this format BOOL bCanSave; FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(_dib); if(image_type == FIT_BITMAP) { // standard bitmap type WORD bpp = FreeImage_GetBPP(_dib); bCanSave = (FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)); } else { // special bitmap type bCanSave = FreeImage_FIFSupportsExportType(fif, image_type); } if(bCanSave) { bSuccess = memIO.save(fif, _dib, flag); return bSuccess; } } return bSuccess; } /////////////////////////////////////////////////////////////////// // Conversion routines BOOL fipImage::convertToType(FREE_IMAGE_TYPE image_type, BOOL scale_linear) { if(_dib) { FIBITMAP *dib = FreeImage_ConvertToType(_dib, image_type, scale_linear); return replace(dib); } return FALSE; } BOOL fipImage::threshold(BYTE T) { if(_dib) { FIBITMAP *dib1 = FreeImage_Threshold(_dib, T); return replace(dib1); } return FALSE; } BOOL fipImage::convertTo4Bits() { if(_dib) { FIBITMAP *dib4 = FreeImage_ConvertTo4Bits(_dib); return replace(dib4); } return FALSE; } BOOL fipImage::convertTo8Bits() { if(_dib) { FIBITMAP *dib8 = FreeImage_ConvertTo8Bits(_dib); return replace(dib8); } return FALSE; } BOOL fipImage::convertTo16Bits555() { if(_dib) { FIBITMAP *dib16_555 = FreeImage_ConvertTo16Bits555(_dib); return replace(dib16_555); } return FALSE; } BOOL fipImage::convertTo16Bits565() { if(_dib) { FIBITMAP *dib16_565 = FreeImage_ConvertTo16Bits565(_dib); return replace(dib16_565); } return FALSE; } BOOL fipImage::convertTo24Bits() { if(_dib) { FIBITMAP *dibRGB = FreeImage_ConvertTo24Bits(_dib); return replace(dibRGB); } return FALSE; } BOOL fipImage::convertTo32Bits() { if(_dib) { FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(_dib); return replace(dib32); } return FALSE; } BOOL fipImage::convertToGrayscale() { if(_dib) { FIBITMAP *dib8 = FreeImage_ConvertToGreyscale(_dib); return replace(dib8); } return FALSE; } BOOL fipImage::colorQuantize(FREE_IMAGE_QUANTIZE algorithm) { if(_dib) { FIBITMAP *dib8 = FreeImage_ColorQuantize(_dib, algorithm); return replace(dib8); } return FALSE; } BOOL fipImage::dither(FREE_IMAGE_DITHER algorithm) { if(_dib) { FIBITMAP *dib = FreeImage_Dither(_dib, algorithm); return replace(dib); } return FALSE; } BOOL fipImage::convertToRGBF() { if(_dib) { FIBITMAP *dib = FreeImage_ConvertToRGBF(_dib); return replace(dib); } return FALSE; } BOOL fipImage::toneMapping(FREE_IMAGE_TMO tmo, double first_param, double second_param, double third_param, double fourth_param) { if(_dib) { FIBITMAP *dst = NULL; // Apply a tone mapping algorithm and convert to 24-bit switch(tmo) { case FITMO_REINHARD05: dst = FreeImage_TmoReinhard05Ex(_dib, first_param, second_param, third_param, fourth_param); break; default: dst = FreeImage_ToneMapping(_dib, tmo, first_param, second_param); break; } return replace(dst); } return FALSE; } /////////////////////////////////////////////////////////////////// // Transparency support: background colour and alpha channel BOOL fipImage::isTransparent() const { return FreeImage_IsTransparent(_dib); } unsigned fipImage::getTransparencyCount() const { return FreeImage_GetTransparencyCount(_dib); } BYTE* fipImage::getTransparencyTable() const { return FreeImage_GetTransparencyTable(_dib); } void fipImage::setTransparencyTable(BYTE *table, int count) { FreeImage_SetTransparencyTable(_dib, table, count); _bHasChanged = TRUE; } BOOL fipImage::hasFileBkColor() const { return FreeImage_HasBackgroundColor(_dib); } BOOL fipImage::getFileBkColor(RGBQUAD *bkcolor) const { return FreeImage_GetBackgroundColor(_dib, bkcolor); } BOOL fipImage::setFileBkColor(RGBQUAD *bkcolor) { _bHasChanged = TRUE; return FreeImage_SetBackgroundColor(_dib, bkcolor); } /////////////////////////////////////////////////////////////////// // Channel processing support BOOL fipImage::getChannel(fipImage& image, FREE_IMAGE_COLOR_CHANNEL channel) const { if(_dib) { image = FreeImage_GetChannel(_dib, channel); return image.isValid(); } return FALSE; } BOOL fipImage::setChannel(fipImage& image, FREE_IMAGE_COLOR_CHANNEL channel) { if(_dib) { _bHasChanged = TRUE; return FreeImage_SetChannel(_dib, image._dib, channel); } return FALSE; } BOOL fipImage::splitChannels(fipImage& RedChannel, fipImage& GreenChannel, fipImage& BlueChannel) { if(_dib) { RedChannel = FreeImage_GetChannel(_dib, FICC_RED); GreenChannel = FreeImage_GetChannel(_dib, FICC_GREEN); BlueChannel = FreeImage_GetChannel(_dib, FICC_BLUE); return (RedChannel.isValid() && GreenChannel.isValid() && BlueChannel.isValid()); } return FALSE; } BOOL fipImage::combineChannels(fipImage& red, fipImage& green, fipImage& blue) { if(!_dib) { int width = red.getWidth(); int height = red.getHeight(); _dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); } if(_dib) { BOOL bResult = TRUE; bResult &= FreeImage_SetChannel(_dib, red._dib, FICC_RED); bResult &= FreeImage_SetChannel(_dib, green._dib, FICC_GREEN); bResult &= FreeImage_SetChannel(_dib, blue._dib, FICC_BLUE); _bHasChanged = TRUE; return bResult; } return FALSE; } /////////////////////////////////////////////////////////////////// // Rotation and flipping BOOL fipImage::rotateEx(double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask) { if(_dib) { if(FreeImage_GetBPP(_dib) >= 8) { FIBITMAP *rotated = FreeImage_RotateEx(_dib, angle, x_shift, y_shift, x_origin, y_origin, use_mask); return replace(rotated); } } return FALSE; } BOOL fipImage::rotate(double angle, const void *bkcolor) { if(_dib) { switch(FreeImage_GetImageType(_dib)) { case FIT_BITMAP: switch(FreeImage_GetBPP(_dib)) { case 1: case 8: case 24: case 32: break; default: return FALSE; } break; case FIT_UINT16: case FIT_RGB16: case FIT_RGBA16: case FIT_FLOAT: case FIT_RGBF: case FIT_RGBAF: break; default: return FALSE; break; } FIBITMAP *rotated = FreeImage_Rotate(_dib, angle, bkcolor); return replace(rotated); } return FALSE; } BOOL fipImage::flipVertical() { if(_dib) { _bHasChanged = TRUE; return FreeImage_FlipVertical(_dib); } return FALSE; } BOOL fipImage::flipHorizontal() { if(_dib) { _bHasChanged = TRUE; return FreeImage_FlipHorizontal(_dib); } return FALSE; } /////////////////////////////////////////////////////////////////// // Color manipulation routines BOOL fipImage::invert() { if(_dib) { _bHasChanged = TRUE; return FreeImage_Invert(_dib); } return FALSE; } BOOL fipImage::adjustCurve(BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel) { if(_dib) { _bHasChanged = TRUE; return FreeImage_AdjustCurve(_dib, LUT, channel); } return FALSE; } BOOL fipImage::adjustGamma(double gamma) { if(_dib) { _bHasChanged = TRUE; return FreeImage_AdjustGamma(_dib, gamma); } return FALSE; } BOOL fipImage::adjustBrightness(double percentage) { if(_dib) { _bHasChanged = TRUE; return FreeImage_AdjustBrightness(_dib, percentage); } return FALSE; } BOOL fipImage::adjustContrast(double percentage) { if(_dib) { _bHasChanged = TRUE; return FreeImage_AdjustContrast(_dib, percentage); } return FALSE; } BOOL fipImage::adjustBrightnessContrastGamma(double brightness, double contrast, double gamma) { if(_dib) { _bHasChanged = TRUE; return FreeImage_AdjustColors(_dib, brightness, contrast, gamma, FALSE); } return FALSE; } BOOL fipImage::getHistogram(DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel) const { if(_dib) { return FreeImage_GetHistogram(_dib, histo, channel); } return FALSE; } /////////////////////////////////////////////////////////////////// // Upsampling / downsampling routine BOOL fipImage::rescale(unsigned new_width, unsigned new_height, FREE_IMAGE_FILTER filter) { if(_dib) { switch(FreeImage_GetImageType(_dib)) { case FIT_BITMAP: case FIT_UINT16: case FIT_RGB16: case FIT_RGBA16: case FIT_FLOAT: case FIT_RGBF: case FIT_RGBAF: break; default: return FALSE; break; } // Perform upsampling / downsampling FIBITMAP *dst = FreeImage_Rescale(_dib, new_width, new_height, filter); return replace(dst); } return FALSE; } BOOL fipImage::makeThumbnail(unsigned max_size, BOOL convert) { if(_dib) { switch(FreeImage_GetImageType(_dib)) { case FIT_BITMAP: case FIT_UINT16: case FIT_RGB16: case FIT_RGBA16: case FIT_FLOAT: case FIT_RGBF: case FIT_RGBAF: break; default: return FALSE; break; } // Perform downsampling FIBITMAP *dst = FreeImage_MakeThumbnail(_dib, max_size, convert); return replace(dst); } return FALSE; } /////////////////////////////////////////////////////////////////// // Metadata unsigned fipImage::getMetadataCount(FREE_IMAGE_MDMODEL model) const { return FreeImage_GetMetadataCount(model, _dib); } 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 fipImage::setMetadata(FREE_IMAGE_MDMODEL model, const char *key, fipTag& tag) { return FreeImage_SetMetadata(model, _dib, key, tag); }