// ========================================================== // Upsampling / downsampling routine // // Design and implementation by // - Hervé Drolon (drolon@infonie.fr) // - Carsten Klein (cklein05@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! // ========================================================== #include "../stdafx.h" #include "Resize.h" FIBITMAP * DLL_CALLCONV FreeImage_RescaleRect(FIBITMAP *src, int dst_width, int dst_height, int src_left, int src_top, int src_right, int src_bottom, FREE_IMAGE_FILTER filter, unsigned flags) { FIBITMAP *dst = NULL; const int src_width = FreeImage_GetWidth(src); const int src_height = FreeImage_GetHeight(src); if (!FreeImage_HasPixels(src) || (dst_width <= 0) || (dst_height <= 0) || (src_width <= 0) || (src_height <= 0)) { return NULL; } // normalize the rectangle if (src_right < src_left) { INPLACESWAP(src_left, src_right); } if (src_bottom < src_top) { INPLACESWAP(src_top, src_bottom); } // check the size of the sub image if((src_left < 0) || (src_right > src_width) || (src_top < 0) || (src_bottom > src_height)) { return NULL; } // select the filter CGenericFilter *pFilter = NULL; switch (filter) { case FILTER_BOX: pFilter = new(std::nothrow) CBoxFilter(); break; case FILTER_BICUBIC: pFilter = new(std::nothrow) CBicubicFilter(); break; case FILTER_BILINEAR: pFilter = new(std::nothrow) CBilinearFilter(); break; case FILTER_BSPLINE: pFilter = new(std::nothrow) CBSplineFilter(); break; case FILTER_CATMULLROM: pFilter = new(std::nothrow) CCatmullRomFilter(); break; case FILTER_LANCZOS3: pFilter = new(std::nothrow) CLanczos3Filter(); break; } if (!pFilter) { return NULL; } CResizeEngine Engine(pFilter); dst = Engine.scale(src, dst_width, dst_height, src_left, src_top, src_right - src_left, src_bottom - src_top, flags); delete pFilter; if ((flags & FI_RESCALE_OMIT_METADATA) != FI_RESCALE_OMIT_METADATA) { // copy metadata from src to dst FreeImage_CloneMetadata(dst, src); } return dst; } FIBITMAP * DLL_CALLCONV FreeImage_Rescale(FIBITMAP *src, int dst_width, int dst_height, FREE_IMAGE_FILTER filter) { return FreeImage_RescaleRect(src, dst_width, dst_height, 0, 0, FreeImage_GetWidth(src), FreeImage_GetHeight(src), filter, FI_RESCALE_DEFAULT); } 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(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; }