BOOL fipImage::convertToRGBF() { if(_dib) { FIBITMAP *dib = FreeImage_ConvertToRGBF(_dib); return replace(dib); } return FALSE; }
/** Apply the global/local tone mapping operator to a RGBF image and convert to 24-bit RGB<br> User parameters control intensity, contrast, and level of adaptation @param src Input RGBF image @param intensity Overall intensity in range [-8:8] : default to 0 @param contrast Contrast in range [0.3:1) : default to 0 @param adaptation Adaptation in range [0:1] : default to 1 @param color_correction Color correction in range [0:1] : default to 0 @return Returns a 24-bit RGB image if successful, returns NULL otherwise */ FIBITMAP* DLL_CALLCONV FreeImage_TmoReinhard05Ex(FIBITMAP *src, double intensity, double contrast, double adaptation, double color_correction) { if(!FreeImage_HasPixels(src)) return NULL; // working RGBF variable FIBITMAP *dib = NULL, *Y = NULL; dib = FreeImage_ConvertToRGBF(src); if(!dib) return NULL; // get the Luminance channel Y = ConvertRGBFToY(dib); if(!Y) { FreeImage_Unload(dib); return NULL; } // perform the tone mapping ToneMappingReinhard05(dib, Y, (float)intensity, (float)contrast, (float)adaptation, (float)color_correction); // not needed anymore FreeImage_Unload(Y); // clamp image highest values to display white, then convert to 24-bit RGB FIBITMAP *dst = ClampConvertRGBFTo24(dib); // clean-up and return FreeImage_Unload(dib); // copy metadata from src to dst FreeImage_CloneMetadata(dst, src); return dst; }
/** Apply the Adaptive Logarithmic Mapping operator to a HDR image and convert to 24-bit RGB @param src Input RGB16 or RGB[A]F image @param gamma Gamma correction (gamma > 0). 1 means no correction, 2.2 in the original paper. @param exposure Exposure parameter (0 means no correction, 0 in the original paper) @return Returns a 24-bit RGB image if successful, returns NULL otherwise */ FIBITMAP* DLL_CALLCONV FreeImage_TmoDrago03(FIBITMAP *src, double gamma, double exposure) { float maxLum, minLum, avgLum; if(!FreeImage_HasPixels(src)) return NULL; // working RGBF variable FIBITMAP *dib = NULL; dib = FreeImage_ConvertToRGBF(src); if(!dib) return NULL; // default algorithm parameters const float biasParam = 0.85F; const float expoParam = (float)pow(2.0, exposure); //default exposure is 1, 2^0 // convert to Yxy ConvertInPlaceRGBFToYxy(dib); // get the luminance LuminanceFromYxy(dib, &maxLum, &minLum, &avgLum); // perform the tone mapping ToneMappingDrago03(dib, maxLum, avgLum, biasParam, expoParam); // convert back to RGBF ConvertInPlaceYxyToRGBF(dib); if(gamma != 1) { // perform gamma correction REC709GammaCorrection(dib, (float)gamma); } // clamp image highest values to display white, then convert to 24-bit RGB FIBITMAP *dst = ClampConvertRGBFTo24(dib); // clean-up and return FreeImage_Unload(dib); // copy metadata from src to dst FreeImage_CloneMetadata(dst, src); return dst; }
FIBITMAP* DLL_CALLCONV FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_linear) { FIBITMAP *dst = NULL; if(!FreeImage_HasPixels(src)) return NULL; // convert from src_type to dst_type const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src); if(src_type == dst_type) { return FreeImage_Clone(src); } const unsigned src_bpp = FreeImage_GetBPP(src); switch(src_type) { case FIT_BITMAP: switch(dst_type) { case FIT_UINT16: dst = FreeImage_ConvertToUINT16(src); break; case FIT_INT16: dst = (src_bpp == 8) ? convertByteToShort.convert(src, dst_type) : NULL; break; case FIT_UINT32: dst = (src_bpp == 8) ? convertByteToULong.convert(src, dst_type) : NULL; break; case FIT_INT32: dst = (src_bpp == 8) ? convertByteToLong.convert(src, dst_type) : NULL; break; case FIT_FLOAT: dst = FreeImage_ConvertToFloat(src); break; case FIT_DOUBLE: dst = (src_bpp == 8) ? convertByteToDouble.convert(src, dst_type) : NULL; break; case FIT_COMPLEX: dst = (src_bpp == 8) ? convertByteToComplex.convert(src) : NULL; break; case FIT_RGB16: 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; case FIT_UINT16: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: dst = FreeImage_ConvertToFloat(src); break; case FIT_DOUBLE: dst = convertUShortToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertUShortToComplex.convert(src); break; case FIT_RGB16: 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; case FIT_INT16: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: dst = convertShortToFloat.convert(src, dst_type); break; case FIT_DOUBLE: dst = convertShortToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertShortToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_UINT32: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_INT32: break; case FIT_FLOAT: dst = convertULongToFloat.convert(src, dst_type); break; case FIT_DOUBLE: dst = convertULongToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertULongToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_INT32: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_FLOAT: dst = convertLongToFloat.convert(src, dst_type); break; case FIT_DOUBLE: dst = convertLongToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertLongToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_FLOAT: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_DOUBLE: dst = convertFloatToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertFloatToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: dst = FreeImage_ConvertToRGBF(src); break; case FIT_RGBAF: dst = FreeImage_ConvertToRGBAF(src); break; } break; case FIT_DOUBLE: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: break; case FIT_COMPLEX: dst = convertDoubleToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_COMPLEX: switch(dst_type) { case FIT_BITMAP: break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: break; case FIT_DOUBLE: break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_RGB16: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertTo24Bits(src); break; case FIT_UINT16: dst = FreeImage_ConvertToUINT16(src); break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: dst = FreeImage_ConvertToFloat(src); break; case FIT_DOUBLE: break; 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; case FIT_RGBA16: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertTo32Bits(src); break; case FIT_UINT16: dst = FreeImage_ConvertToUINT16(src); break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: dst = FreeImage_ConvertToFloat(src); break; case FIT_DOUBLE: break; case FIT_COMPLEX: break; case FIT_RGB16: dst = FreeImage_ConvertToRGB16(src); break; case FIT_RGBF: dst = FreeImage_ConvertToRGBF(src); break; case FIT_RGBAF: dst = FreeImage_ConvertToRGBAF(src); break; } break; case FIT_RGBF: switch(dst_type) { case FIT_BITMAP: break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: dst = FreeImage_ConvertToFloat(src); break; case FIT_DOUBLE: break; case FIT_COMPLEX: break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBAF: dst = FreeImage_ConvertToRGBAF(src); break; } break; case FIT_RGBAF: switch(dst_type) { case FIT_BITMAP: break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: dst = FreeImage_ConvertToFloat(src); break; case FIT_DOUBLE: break; case FIT_COMPLEX: break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: dst = FreeImage_ConvertToRGBF(src); break; } break; } if(NULL == dst) { FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, dst_type); } return dst; }
FIBITMAP * DLL_CALLCONV FreeImage_MakeThumbnail(FIBITMAP *dib, int max_pixel_size, BOOL convert) { FIBITMAP *thumbnail = NULL; int new_width, new_height; if(!FreeImage_HasPixels(dib) || (max_pixel_size <= 0)) return NULL; int width = FreeImage_GetWidth(dib); int height = FreeImage_GetHeight(dib); if(max_pixel_size == 0) max_pixel_size = 1; if((width < max_pixel_size) && (height < max_pixel_size)) { // image is smaller than the requested thumbnail return FreeImage_Clone(dib); } if(width > height) { new_width = max_pixel_size; // change image height with the same ratio double ratio = ((double)new_width / (double)width); new_height = (int)(height * ratio + 0.5); if(new_height == 0) new_height = 1; } else { new_height = max_pixel_size; // change image width with the same ratio double ratio = ((double)new_height / (double)height); new_width = (int)(width * ratio + 0.5); if(new_width == 0) new_width = 1; } const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); // perform downsampling using a bilinear interpolation switch(image_type) { case FIT_BITMAP: case FIT_UINT16: case FIT_RGB16: case FIT_RGBA16: case FIT_FLOAT: case FIT_RGBF: case FIT_RGBAF: { FREE_IMAGE_FILTER filter = FILTER_BILINEAR; thumbnail = FreeImage_Rescale(dib, new_width, new_height, filter); } break; case FIT_INT16: case FIT_UINT32: case FIT_INT32: case FIT_DOUBLE: case FIT_COMPLEX: default: // cannot rescale this kind of image thumbnail = NULL; break; } if((thumbnail != NULL) && (image_type != FIT_BITMAP) && convert) { // convert to a standard bitmap FIBITMAP *bitmap = NULL; switch((int)image_type) { case FIT_UINT16: bitmap = FreeImage_ConvertTo8Bits(thumbnail); break; case FIT_RGB16: bitmap = FreeImage_ConvertTo24Bits(thumbnail); break; case FIT_RGBA16: bitmap = FreeImage_ConvertTo32Bits(thumbnail); break; case FIT_FLOAT: bitmap = FreeImage_ConvertToStandardType(thumbnail, TRUE); break; case FIT_RGBF: bitmap = FreeImage_ToneMapping(thumbnail, FITMO_DRAGO03); break; case FIT_RGBAF: // no way to keep the transparency yet ... FIBITMAP *rgbf = FreeImage_ConvertToRGBF(thumbnail); bitmap = FreeImage_ToneMapping(rgbf, FITMO_DRAGO03); FreeImage_Unload(rgbf); break; } if(bitmap != NULL) { FreeImage_Unload(thumbnail); thumbnail = bitmap; } } // copy metadata from src to dst FreeImage_CloneMetadata(thumbnail, dib); return thumbnail; }
/** Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB @param dib Input RGBF / RGB16 image @param color_saturation Color saturation (s parameter in the paper) in [0.4..0.6] @param attenuation Atenuation factor (beta parameter in the paper) in [0.8..0.9] @return Returns a 24-bit RGB image if successful, returns NULL otherwise */ FIBITMAP* DLL_CALLCONV FreeImage_TmoFattal02(FIBITMAP *dib, double color_saturation, double attenuation) { const float alpha = 0.1F; // parameter alpha = 0.1 const float beta = (float)MAX(0.8, MIN(0.9, attenuation)); // parameter beta = [0.8..0.9] const float s = (float)MAX(0.4, MIN(0.6, color_saturation));// exponent s controls color saturation = [0.4..0.6] FIBITMAP *src = NULL; FIBITMAP *Yin = NULL; FIBITMAP *Yout = NULL; FIBITMAP *dst = NULL; if(!FreeImage_HasPixels(dib)) return NULL; try { // convert to RGBF src = FreeImage_ConvertToRGBF(dib); if(!src) throw(1); // get the luminance channel Yin = ConvertRGBFToY(src); if(!Yin) throw(1); // perform the tone mapping Yout = tmoFattal02(Yin, alpha, beta); if(!Yout) throw(1); // clip low and high values and normalize to [0..1] //NormalizeY(Yout, 0.001F, 0.995F); NormalizeY(Yout, 0, 1); // compress the dynamic range const unsigned width = FreeImage_GetWidth(src); const unsigned height = FreeImage_GetHeight(src); const unsigned rgb_pitch = FreeImage_GetPitch(src); const unsigned y_pitch = FreeImage_GetPitch(Yin); BYTE *bits = (BYTE*)FreeImage_GetBits(src); BYTE *bits_yin = (BYTE*)FreeImage_GetBits(Yin); BYTE *bits_yout = (BYTE*)FreeImage_GetBits(Yout); for(unsigned y = 0; y < height; y++) { float *Lin = (float*)bits_yin; float *Lout = (float*)bits_yout; float *color = (float*)bits; for(unsigned x = 0; x < width; x++) { for(unsigned c = 0; c < 3; c++) { *color = (Lin[x] > 0) ? pow(*color/Lin[x], s) * Lout[x] : 0; color++; } } bits += rgb_pitch; bits_yin += y_pitch; bits_yout += y_pitch; } // not needed anymore FreeImage_Unload(Yin); Yin = NULL; FreeImage_Unload(Yout); Yout = NULL; // clamp image highest values to display white, then convert to 24-bit RGB dst = ClampConvertRGBFTo24(src); // clean-up and return FreeImage_Unload(src); src = NULL; // copy metadata from src to dst FreeImage_CloneMetadata(dst, dib); return dst; } catch(int) { if(src) FreeImage_Unload(src); if(Yin) FreeImage_Unload(Yin); if(Yout) FreeImage_Unload(Yout); return NULL; } }
FIBITMAP* DLL_CALLCONV FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_linear) { FIBITMAP *dst = NULL; if(!src) return NULL; // convert from src_type to dst_type const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src); if(src_type == dst_type) { return FreeImage_Clone(src); } if(src_type == FIT_BITMAP) { const unsigned src_bpp = FreeImage_GetBPP(src); if(((src_bpp == 24) || (src_bpp == 32)) && (dst_type != FIT_RGBF)) { FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Only 24-/32-bit dib can be converted to type %d.", dst_type); return NULL; } else if(src_bpp != 8) { FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Only 8-bit dib can be converted to type %d.", dst_type); return NULL; } } switch(src_type) { case FIT_BITMAP: switch(dst_type) { case FIT_UINT16: dst = convertByteToUShort.convert(src, dst_type); break; case FIT_INT16: dst = convertByteToShort.convert(src, dst_type); break; case FIT_UINT32: dst = convertByteToULong.convert(src, dst_type); break; case FIT_INT32: dst = convertByteToLong.convert(src, dst_type); break; case FIT_FLOAT: dst = convertByteToFloat.convert(src, dst_type); break; case FIT_DOUBLE: dst = convertByteToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertByteToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: dst = FreeImage_ConvertToRGBF(src); break; case FIT_RGBAF: break; } break; case FIT_UINT16: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: dst = convertUShortToFloat.convert(src, dst_type); break; case FIT_DOUBLE: dst = convertUShortToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertUShortToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_INT16: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: dst = convertShortToFloat.convert(src, dst_type); break; case FIT_DOUBLE: dst = convertShortToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertShortToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_UINT32: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_INT32: break; case FIT_FLOAT: dst = convertULongToFloat.convert(src, dst_type); break; case FIT_DOUBLE: dst = convertULongToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertULongToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_INT32: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_FLOAT: dst = convertLongToFloat.convert(src, dst_type); break; case FIT_DOUBLE: dst = convertLongToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertLongToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_FLOAT: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_DOUBLE: dst = convertFloatToDouble.convert(src, dst_type); break; case FIT_COMPLEX: dst = convertFloatToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_DOUBLE: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertToStandardType(src, scale_linear); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: break; case FIT_COMPLEX: dst = convertDoubleToComplex.convert(src); break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_COMPLEX: switch(dst_type) { case FIT_BITMAP: break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: break; case FIT_DOUBLE: break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: break; case FIT_RGBAF: break; } break; case FIT_RGB16: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertTo24Bits(src); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: break; case FIT_DOUBLE: break; case FIT_COMPLEX: break; case FIT_RGBA16: break; case FIT_RGBF: dst = FreeImage_ConvertToRGBF(src); break; case FIT_RGBAF: break; } break; case FIT_RGBA16: switch(dst_type) { case FIT_BITMAP: dst = FreeImage_ConvertTo32Bits(src); break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: break; case FIT_DOUBLE: break; case FIT_COMPLEX: break; case FIT_RGB16: break; case FIT_RGBF: dst = FreeImage_ConvertToRGBF(src); break; case FIT_RGBAF: break; } break; case FIT_RGBF: switch(dst_type) { case FIT_BITMAP: break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: break; case FIT_DOUBLE: break; case FIT_COMPLEX: break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBAF: break; } break; case FIT_RGBAF: switch(dst_type) { case FIT_BITMAP: break; case FIT_UINT16: break; case FIT_INT16: break; case FIT_UINT32: break; case FIT_INT32: break; case FIT_FLOAT: break; case FIT_DOUBLE: break; case FIT_COMPLEX: break; case FIT_RGB16: break; case FIT_RGBA16: break; case FIT_RGBF: dst = FreeImage_ConvertToRGBF(src); break; } break; } if(NULL == dst) { FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, dst_type); } else { // copy metadata from src to dst FreeImage_CloneMetadata(dst, src); } return dst; }