Author: post
Date: 2009-06-27 17:38:20 +0200 (Sat, 27 Jun 2009)
New Revision: 2516

Modified:
   trunk/plugins/resample/resample.c
Log:
Resampler: Added Nearest Neighbor Resampling, and enabled it for very small 
input images. Can also be used for fast resampling.

Modified: trunk/plugins/resample/resample.c
===================================================================
--- trunk/plugins/resample/resample.c   2009-06-27 15:24:39 UTC (rev 2515)
+++ trunk/plugins/resample/resample.c   2009-06-27 15:38:20 UTC (rev 2516)
@@ -51,7 +51,8 @@
        guint (*resample_support)();
        gdouble (*resample_func)(gdouble);
        GThread *threadid;
-       gboolean use_compatible;
+       gboolean use_compatible;        /* Use compatible resampler if 
pixelsize != 4 */
+       gboolean use_fast;              /* Use nearest neighbour resampler, 
also compatible*/
 } ResampleInfo;
 
 RS_DEFINE_FILTER(rs_resample, RSResample)
@@ -71,6 +72,8 @@
 static void ResizeV(ResampleInfo *info);
 static void ResizeH_compatible(ResampleInfo *info);
 static void ResizeV_compatible(ResampleInfo *info);
+static void ResizeH_fast(ResampleInfo *info);
+static void ResizeV_fast(ResampleInfo *info);
 
 static RSFilterClass *rs_resample_parent_class = NULL;
 inline guint clampbits(gint x, guint n) { guint32 _y_temp; if( (_y_temp=x>>n) 
) x = ~_y_temp >> (32-n); return x;}
@@ -167,12 +170,16 @@
 
        if (t->input->w == t->output->w) 
        {
-               if (t->use_compatible)
+               if (t->use_fast)
+                       ResizeV_fast(t);                
+               else if (t->use_compatible)
                        ResizeV_compatible(t);
                else 
                        ResizeV(t);             
        } else  {
-               if (t->use_compatible)
+               if (t->use_fast)
+                       ResizeH_fast(t);
+               else if (t->use_compatible)
                        ResizeH_compatible(t);
                else 
                        ResizeH(t);     
@@ -215,6 +222,8 @@
 
        /* Use compatible (and slow) version if input isn't 3 channels and 
pixelsize 4 */ 
        gboolean use_compatible = ( ! ( input->pixelsize == 4 && 
input->channels == 3));
+       gboolean use_fast = FALSE;
+
        guint threads = rs_get_number_of_processor_cores();
 
        ResampleInfo* h_resample = g_new(ResampleInfo,  threads);
@@ -238,6 +247,7 @@
                h->dest_offset_other = input_y_offset;
                h->dest_end_other  = MIN(input_y_offset+input_y_per_thread, 
input_height);
                h->use_compatible = use_compatible;
+               h->use_fast = use_fast;
 
                /* Start it up */
                h->threadid = g_thread_create(start_thread_resampler, h, TRUE, 
NULL);
@@ -358,11 +368,13 @@
        gdouble filter_step = MIN(1.0 / pos_step, 1.0);
        gdouble filter_support = (gdouble) lanczos_taps() / filter_step;
        gint fir_filter_size = (gint) (ceil(filter_support*2));
+
+       if (old_size <= fir_filter_size)
+               return ResizeH_fast(info);
+
        gint *weights = g_new(gint, new_size * fir_filter_size);
        gint *offsets = g_new(gint, new_size);
 
-       g_assert(new_size > fir_filter_size);
-
        gdouble pos = 0.0;
        gint i,j,k;
 
@@ -455,11 +467,13 @@
        gdouble filter_step = MIN(1.0 / pos_step, 1.0);
        gdouble filter_support = (gdouble) lanczos_taps() / filter_step;
        gint fir_filter_size = (gint) (ceil(filter_support*2));
+
+       if (old_size <= fir_filter_size)
+               return ResizeV_fast(info);
+
        gint *weights = g_new(gint, new_size * fir_filter_size);
        gint *offsets = g_new(gint, new_size);
 
-       g_assert(new_size > fir_filter_size);
-
        gdouble pos = 0.0;
 
        gint i,j,k;
@@ -551,11 +565,13 @@
        gdouble filter_step = MIN(1.0 / pos_step, 1.0);
        gdouble filter_support = (gdouble) lanczos_taps() / filter_step;
        gint fir_filter_size = (gint) (ceil(filter_support*2));
+
+       if (old_size <= fir_filter_size)
+               return ResizeH_fast(info);
+
        gint *weights = g_new(gint, new_size * fir_filter_size);
        gint *offsets = g_new(gint, new_size);
 
-       g_assert(new_size > fir_filter_size);
-
        gdouble pos = 0.0;
        gint i,j,k;
 
@@ -646,11 +662,13 @@
        gdouble filter_step = MIN(1.0 / pos_step, 1.0);
        gdouble filter_support = (gdouble) lanczos_taps() / filter_step;
        gint fir_filter_size = (gint) (ceil(filter_support*2));
+
+       if (old_size <= fir_filter_size)
+               return ResizeV_fast(info);
+
        gint *weights = g_new(gint, new_size * fir_filter_size);
        gint *offsets = g_new(gint, new_size);
 
-       g_assert(new_size > fir_filter_size);
-
        gdouble pos = 0.0;
 
        gint i,j,k;
@@ -719,3 +737,76 @@
        g_free(weights);
        g_free(offsets);
 }
+
+static void
+ResizeV_fast(ResampleInfo *info)
+{
+       const RS_IMAGE16 *input = info->input;
+       const RS_IMAGE16 *output = info->output;
+       const guint old_size = info->old_size;
+       const guint new_size = info->new_size;
+       const guint start_x = info->dest_offset_other;
+       const guint end_x = info->dest_end_other;
+
+       gint pixelsize = input->pixelsize;
+       gint ch = input->channels;
+
+       gdouble pos_step = ((gdouble) old_size) / ((gdouble)new_size);
+
+       gint pos = 0;
+       gint delta = (gint)(pos_step * 65536.0);
+
+       guint y,x,c;
+       
+       for (y = 0; y < new_size ; y++)
+       {
+               gushort *out = GET_PIXEL(output, 0, y);
+               for (x = start_x; x < end_x; x++)
+               {
+                       gushort *in = GET_PIXEL(input, x, pos>>16);
+                       for (c = 0; c < ch; c++)
+                       {
+                               out[x*pixelsize+c] = in[c];
+                       }
+               }
+               pos += delta;
+       }
+}
+
+
+
+static void
+ResizeH_fast(ResampleInfo *info)
+{
+       const RS_IMAGE16 *input = info->input;
+       const RS_IMAGE16 *output = info->output;
+       const guint old_size = info->old_size;
+       const guint new_size = info->new_size;
+
+       gint pixelsize = input->pixelsize;
+       gint ch = input->channels;
+
+       gdouble pos_step = ((gdouble) old_size) / ((gdouble)new_size);
+
+       gint pos;
+       gint delta = (gint)(pos_step * 65536.0);
+
+       guint y,x,c;
+       for (y = info->dest_offset_other; y < info->dest_end_other ; y++)
+       {
+               gushort *in_line = GET_PIXEL(input, 0, y);
+               gushort *out = GET_PIXEL(output, 0, y);
+               pos = 0;
+
+               for (x = 0; x < new_size; x++)
+               {
+                       for (c = 0 ; c < ch; c++)  
+                       {
+                               out[x*pixelsize+c] = 
in_line[(pos>>16)*pixelsize+c];
+                       }
+                       pos += delta;
+               }
+       }
+}
+
+


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to