diff options
Diffstat (limited to 'src/process/im_resize.cpp')
-rw-r--r-- | src/process/im_resize.cpp | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/src/process/im_resize.cpp b/src/process/im_resize.cpp new file mode 100644 index 0000000..ddf6e47 --- /dev/null +++ b/src/process/im_resize.cpp @@ -0,0 +1,332 @@ +/** \file + * \brief Image Resize + * + * See Copyright Notice in im_lib.h + * $Id: im_resize.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include <im.h> +#include <im_util.h> +#include <im_math.h> +#include <im_complex.h> +#include <im_counter.h> + +#include "im_process_loc.h" + +#include <stdlib.h> +#include <memory.h> + + +static inline void iResizeInverse(int x, int y, float *xl, float *yl, float x_invfactor, float y_invfactor) +{ + *xl = (x + 0.5f) * x_invfactor; + *yl = (y + 0.5f) * y_invfactor; +} + +template <class DT, class DTU> +static int iResize(int src_width, int src_height, const DT *src_map, + int dst_width, int dst_height, DT *dst_map, + DTU Dummy, int order, int counter) +{ + float xl, yl; + float x_invfactor = float(src_width)/float(dst_width); + float y_invfactor = float(src_height)/float(dst_height); + + for (int y = 0; y < dst_height; y++) + { + for (int x = 0; x < dst_width; x++) + { + iResizeInverse(x, y, &xl, &yl, x_invfactor, y_invfactor); + + // if inside the original image + if (xl > 0.0 && yl > 0.0 && xl < src_width && yl < src_height) + { + if (order == 1) + *dst_map = imBilinearInterpolation(src_width, src_height, src_map, xl, yl); + else if (order == 3) + *dst_map = imBicubicInterpolation(src_width, src_height, src_map, xl, yl, Dummy); + else + *dst_map = imZeroOrderInterpolation(src_width, src_height, src_map, xl, yl); + } + + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +template <class DT, class DTU> +static int iReduce(int src_width, int src_height, const DT *src_map, + int dst_width, int dst_height, DT *dst_map, + DTU Dummy, int order, int counter) +{ + float xl, yl; + float x_invfactor = float(src_width)/float(dst_width); + float y_invfactor = float(src_height)/float(dst_height); + + iResizeInverse(1, 1, &xl, &yl, x_invfactor, y_invfactor); + float xl0 = xl, yl0 = yl; + iResizeInverse(2, 2, &xl, &yl, x_invfactor, y_invfactor); + float xl1 = xl, yl1 = yl; + + float box_width = xl1 - xl0; + float box_height = yl1 - yl0; + + for (int y = 0; y < dst_height; y++) + { + for (int x = 0; x < dst_width; x++) + { + iResizeInverse(x, y, &xl, &yl, x_invfactor, y_invfactor); + + // if inside the original image + if (xl > 0.0 && yl > 0.0 && xl < src_width && yl < src_height) + { + if (order == 0) + *dst_map = imZeroOrderDecimation(src_width, src_height, src_map, xl, yl, box_width, box_height, Dummy); + else + *dst_map = imBilinearDecimation(src_width, src_height, src_map, xl, yl, box_width, box_height, Dummy); + } + + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + return 1; +} + +int imProcessReduce(const imImage* src_image, imImage* dst_image, int order) +{ + int ret = 0; + int counter = imCounterBegin("Reduce Size"); + const char* int_msg = (order == 1)? "Bilinear Decimation": "Zero Order Decimation"; + imCounterTotal(counter, src_image->depth*dst_image->height, int_msg); + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = iReduce(src_image->width, src_image->height, (const imbyte*)src_image->data[i], + dst_image->width, dst_image->height, (imbyte*)dst_image->data[i], + float(0), order, counter); + break; + case IM_USHORT: + ret = iReduce(src_image->width, src_image->height, (const imushort*)src_image->data[i], + dst_image->width, dst_image->height, (imushort*)dst_image->data[i], + float(0), order, counter); + break; + case IM_INT: + ret = iReduce(src_image->width, src_image->height, (const int*)src_image->data[i], + dst_image->width, dst_image->height, (int*)dst_image->data[i], + float(0), order, counter); + break; + case IM_FLOAT: + ret = iReduce(src_image->width, src_image->height, (const float*)src_image->data[i], + dst_image->width, dst_image->height, (float*)dst_image->data[i], + float(0), order, counter); + break; + case IM_CFLOAT: + ret = iReduce(src_image->width, src_image->height, (const imcfloat*)src_image->data[i], + dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i], + imcfloat(0,0), order, counter); + break; + } + } + + imCounterEnd(counter); + return ret; +} + +int imProcessResize(const imImage* src_image, imImage* dst_image, int order) +{ + int ret = 0; + int counter = imCounterBegin("Resize"); + const char* int_msg = (order == 3)? "Bicubic Interpolation": (order == 1)? "Bilinear Interpolation": "Zero Order Interpolation"; + imCounterTotal(counter, src_image->depth*dst_image->height, int_msg); + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = iResize(src_image->width, src_image->height, (const imbyte*)src_image->data[i], + dst_image->width, dst_image->height, (imbyte*)dst_image->data[i], + float(0), order, counter); + break; + case IM_USHORT: + ret = iResize(src_image->width, src_image->height, (const imushort*)src_image->data[i], + dst_image->width, dst_image->height, (imushort*)dst_image->data[i], + float(0), order, counter); + break; + case IM_INT: + ret = iResize(src_image->width, src_image->height, (const int*)src_image->data[i], + dst_image->width, dst_image->height, (int*)dst_image->data[i], + float(0), order, counter); + break; + case IM_FLOAT: + ret = iResize(src_image->width, src_image->height, (const float*)src_image->data[i], + dst_image->width, dst_image->height, (float*)dst_image->data[i], + float(0), order, counter); + break; + case IM_CFLOAT: + ret = iResize(src_image->width, src_image->height, (const imcfloat*)src_image->data[i], + dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i], + imcfloat(0,0), order, counter); + break; + } + } + + imCounterEnd(counter); + return ret; +} + +template <class DT> +static void ReduceBy4(int src_width, + int src_height, + DT *src_map, + int dst_width, + int dst_height, + DT *dst_map) +{ + int x,y,yd,xd; + (void)dst_height; + + // make an even size + int height = (src_height/2)*2; + int width = (src_width/2)*2; + + for(y = 0 ; y < height ; y += 2) + { + yd = y/2; + for(x = 0 ; x < width ; x += 2) + { + xd = x/2; + dst_map[yd * dst_width + xd] = ((src_map[y * src_width + x] + + src_map[y * src_width + (x+1)] + + src_map[(y+1) * src_width + x] + + src_map[(y+1) * src_width + (x+1)])/4); + } + } +} + +void imProcessReduceBy4(const imImage* src_image, imImage* dst_image) +{ + int i; + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ReduceBy4(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image->width, dst_image->height, (imbyte*)dst_image->data[i]); + break; + case IM_USHORT: + ReduceBy4(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image->width, dst_image->height, (imushort*)dst_image->data[i]); + break; + case IM_INT: + ReduceBy4(src_image->width, src_image->height, (int*)src_image->data[i], dst_image->width, dst_image->height, (int*)dst_image->data[i]); + break; + case IM_FLOAT: + ReduceBy4(src_image->width, src_image->height, (float*)src_image->data[i], dst_image->width, dst_image->height, (float*)dst_image->data[i]); + break; + case IM_CFLOAT: + ReduceBy4(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i]); + break; + } + } +} + +void imProcessCrop(const imImage* src_image, imImage* dst_image, int xmin, int ymin) +{ + int type_size = imDataTypeSize(src_image->data_type); + for (int i = 0; i < src_image->depth; i++) + { + imbyte *src_map = (imbyte*)src_image->data[i]; + imbyte *dst_map = (imbyte*)dst_image->data[i]; + + for (int y = 0; y < dst_image->height; y++) + { + int src_offset = (y + ymin)*src_image->line_size + xmin*type_size; + int dst_offset = y*dst_image->line_size; + + memcpy(&dst_map[dst_offset], &src_map[src_offset], dst_image->line_size); + } + } +} + +void imProcessInsert(const imImage* src_image, const imImage* rgn_image, imImage* dst_image, int xmin, int ymin) +{ + int type_size = imDataTypeSize(src_image->data_type); + int dst_size1 = xmin*type_size; + int dst_size2 = src_image->line_size - (rgn_image->line_size + dst_size1); + int dst_offset2 = dst_size1+rgn_image->line_size; + int ymax = ymin+rgn_image->height-1; + int rgn_size = rgn_image->line_size; + + if (dst_size2 < 0) + { + dst_size2 = 0; + rgn_size = src_image->line_size - dst_size1; + dst_offset2 = dst_size1+rgn_size; + } + + if (ymax > src_image->height-1) + ymax = src_image->height-1; + + for (int i = 0; i < src_image->depth; i++) + { + imbyte *src_map = (imbyte*)src_image->data[i]; + imbyte *rgn_map = (imbyte*)rgn_image->data[i]; + imbyte *dst_map = (imbyte*)dst_image->data[i]; + + for (int y = 0; y < src_image->height; y++) + { + if (y < ymin || y > ymax) + { + memcpy(dst_map, src_map, src_image->line_size); + } + else + { + if (dst_size1) + memcpy(dst_map, src_map, dst_size1); + + memcpy(dst_map + dst_size1, rgn_map, rgn_size); + + if (dst_size2) + memcpy(dst_map + dst_offset2, + src_map + dst_offset2, dst_size2); + + rgn_map += rgn_image->line_size; + } + + src_map += src_image->line_size; + dst_map += dst_image->line_size; + } + } +} + +void imProcessAddMargins(const imImage* src_image, imImage* dst_image, int xmin, int ymin) +{ + int type_size = imDataTypeSize(src_image->data_type); + for (int i = 0; i < src_image->depth; i++) + { + imbyte *dst_map = (imbyte*)dst_image->data[i]; + imbyte *src_map = (imbyte*)src_image->data[i]; + + for (int y = 0; y < src_image->height; y++) + { + int src_offset = y*src_image->line_size; + int dst_offset = (y + ymin)*dst_image->line_size + xmin*type_size; + + memcpy(&dst_map[dst_offset], &src_map[src_offset], src_image->line_size); + } + } +} + |