summaryrefslogtreecommitdiff
path: root/src/process/im_resize.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/process/im_resize.cpp')
-rw-r--r--src/process/im_resize.cpp332
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);
+ }
+ }
+}
+