1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
// ==========================================================
// Upsampling / downsampling routine
//
// 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 "Resize.h"
FIBITMAP * DLL_CALLCONV
FreeImage_Rescale(FIBITMAP *src, int dst_width, int dst_height, FREE_IMAGE_FILTER filter) {
FIBITMAP *dst = NULL;
if (!src || (dst_width <= 0) || (dst_height <= 0)) {
return NULL;
}
// select the filter
CGenericFilter *pFilter = NULL;
switch(filter) {
case FILTER_BOX:
pFilter = new CBoxFilter();
break;
case FILTER_BICUBIC:
pFilter = new CBicubicFilter();
break;
case FILTER_BILINEAR:
pFilter = new CBilinearFilter();
break;
case FILTER_BSPLINE:
pFilter = new CBSplineFilter();
break;
case FILTER_CATMULLROM:
pFilter = new CCatmullRomFilter();
break;
case FILTER_LANCZOS3:
pFilter = new CLanczos3Filter();
break;
}
CResizeEngine Engine(pFilter);
// perform upsampling or downsampling
if((FreeImage_GetBPP(src) == 4) || (FreeImage_GetColorType(src) == FIC_PALETTE)) {
// special case for 4-bit images or color map indexed images ...
if(FreeImage_IsTransparent(src) == FALSE) {
FIBITMAP *src24 = NULL;
FIBITMAP *dst24 = NULL;
try {
// transparent conversion to 24-bit (any transparency table will be destroyed)
src24 = FreeImage_ConvertTo24Bits(src);
if(!src24) throw(1);
// perform upsampling or downsampling
dst24 = Engine.scale(src24, dst_width, dst_height);
if(!dst24) throw(1);
// color quantize to 8-bit
dst = FreeImage_ColorQuantize(dst24, FIQ_WUQUANT);
// free and return
FreeImage_Unload(src24);
FreeImage_Unload(dst24);
} catch(int) {
if(src24) FreeImage_Unload(src24);
if(dst24) FreeImage_Unload(dst24);
}
} else {
FIBITMAP *src32 = NULL;
try {
// transparent conversion to 32-bit (keep transparency)
src32 = FreeImage_ConvertTo32Bits(src);
if(!src32) throw(1);
// perform upsampling or downsampling
dst = Engine.scale(src32, dst_width, dst_height);
if(!dst) throw(1);
// free and return
FreeImage_Unload(src32);
} catch(int) {
if(src32) FreeImage_Unload(src32);
if(dst) FreeImage_Unload(dst);
}
}
}
else if((FreeImage_GetBPP(src) == 16) && (FreeImage_GetImageType(src) == FIT_BITMAP)) {
// convert 16-bit RGB to 24-bit
FIBITMAP *src24 = NULL;
try {
// transparent conversion to 24-bit (any transparency table will be destroyed)
src24 = FreeImage_ConvertTo24Bits(src);
if(!src24) throw(1);
// perform upsampling or downsampling
dst = Engine.scale(src24, dst_width, dst_height);
if(!dst) throw(1);
// free and return
FreeImage_Unload(src24);
} catch(int) {
if(src24) FreeImage_Unload(src24);
if(dst) FreeImage_Unload(dst);
}
}
else {
// normal case :
// 1- or 8-bit greyscale, 24- or 32-bit RGB(A) images
// 16-bit greyscale, 48- or 64-bit RGB(A) images
// 32-bit float, 96- or 128-bit RGB(A) float images
dst = Engine.scale(src, dst_width, dst_height);
}
delete pFilter;
return dst;
}
FIBITMAP * DLL_CALLCONV
FreeImage_MakeThumbnail(FIBITMAP *dib, int max_pixel_size, BOOL convert) {
FIBITMAP *thumbnail = NULL;
int new_width, new_height;
if(!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;
}
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;
}
}
return thumbnail;
}
|