aboutsummaryrefslogtreecommitdiff
path: root/system/pdp_resample.c
diff options
context:
space:
mode:
Diffstat (limited to 'system/pdp_resample.c')
-rw-r--r--system/pdp_resample.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/system/pdp_resample.c b/system/pdp_resample.c
new file mode 100644
index 0000000..2b5a9de
--- /dev/null
+++ b/system/pdp_resample.c
@@ -0,0 +1,135 @@
+/*
+ * Pure Data Packet system file. - image resampling routines
+ * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include "pdp_resample.h"
+#include "pdp.h"
+
+/*
+
+efficient bilinear resampling ??
+performance: how to eliminate divides? -> virtual coordinates 2^k x 2^k (conf. opengl)
+
+i.e. 16 bit virtual coordinates: easy modular addressing
+
+*/
+
+s32 pdp_resample_bilin(s16 *image, s32 width, s32 height, s32 virt_x, s32 virt_y)
+{
+
+ s32 fp_x, fp_y, frac_x, frac_y, f, offset, r_1, r_2;
+
+ virt_x &= 0xffff;
+ virt_y &= 0xffff;
+
+ fp_x = virt_x * (width - 1);
+ fp_y = virt_y * (height - 1);
+
+ frac_x = fp_x & (0xffff);
+ frac_y = fp_y & (0xffff);
+
+ offset = (fp_x >> 16) + (fp_y >> 16) * width;
+ image += offset;
+
+ f = 0x10000 - frac_x;
+
+ r_1 = ((f * (s32)(image[0]) + frac_x * (s32)(image[1])))>>16;
+
+ image += width;
+
+ r_2 = ((f * (s32)(image[0]) + frac_x * (s32)(image[1])))>>16;
+
+ f = 0x10000 - frac_y;
+
+ return ((f * r_1 + frac_y * r_2)>>16);
+
+}
+
+
+void pdp_resample_scale_bilin(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h, s32 dst_w, s32 dst_h)
+{
+ s32 i,j;
+ s32 virt_x=0;
+ s32 virt_y=0; /* virtual coordinates in 30 bit */
+ s32 scale_x = 0x40000000 / dst_w;
+ s32 scale_y = 0x40000000 / dst_h;
+
+ for (j=0; j<dst_h; j++){
+ for (i=0; i<dst_w; i++){
+ *dst_image++ = pdp_resample_bilin(src_image, src_w, src_h, virt_x>>14, virt_y>>14);
+ virt_x += scale_x;
+ }
+ virt_x = 0;
+ virt_y += scale_y;
+ }
+
+}
+
+void pdp_resample_scale_nn(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h, s32 dst_w, s32 dst_h)
+{
+ s32 i,j;
+ s32 x=0;
+ s32 y=0;
+ s32 frac_x=0;
+ s32 frac_y=0;
+ s32 scale_x = (src_w << 20 ) / dst_w;
+ s32 scale_y = (src_h << 20 ) / dst_h;
+
+ for (j=0; j<dst_h; j++){
+ for (i=0; i<dst_w; i++){
+ *dst_image++ = src_image[x+y];
+ frac_x += scale_x;
+ x = frac_x >> 20;
+ }
+ x = 0;
+ frac_x = 0;
+ frac_y += scale_y;
+ y = (frac_y >> 20) * src_w;
+ }
+
+}
+
+void pdp_resample_zoom_tiled_bilin(s16 *src_image, s16 *dst_image, s32 w, s32 h,
+ float zoom_x, float zoom_y, float center_x_relative, float center_y_relative)
+{
+ float izx = 1.0f / zoom_x;
+ float izy = 1.0f / zoom_y;
+ s32 scale_x = (s32)((float)0x100000 * izx / (float)w);
+ s32 scale_y = (s32)((float)0x100000 * izy / (float)h);
+
+ s32 top_virt_x = (s32)((1.0f - izx) * (float)0x100000 * center_x_relative);
+ s32 top_virt_y = (s32)((1.0f - izy) * (float)0x100000 * center_y_relative);
+
+ s32 virt_x = top_virt_x;
+ s32 virt_y = top_virt_y;
+
+ s32 i,j;
+
+ for (j=0; j<h; j++){
+ for (i=0; i<w; i++){
+ *dst_image++ = pdp_resample_bilin(src_image, w, h, virt_x>>4, virt_y>>4);
+ virt_x += scale_x;
+ }
+ virt_x = top_virt_x;
+ virt_y += scale_y;
+ }
+
+}
+