[Pixman] [PATCH v9 13/15] pixman-filter: Negative subsample values produces scaled result

spitzak at gmail.com spitzak at gmail.com
Fri Jan 22 01:42:11 PST 2016


From: Bill Spitzak <spitzak at gmail.com>

If a negative value is used for the subsampling, then -n subsamples are
used at scale==1, and fewer are used at larger scale, more are used at
smaller scale, so that the total number of samples is approximately
the same. The computed value is rounded up to the next power of 2.

The scale demo is modified to allow these negative numbers, and initially
uses -12.

v9: First version with this

Signed-off-by: Bill Spitzak <spitzak at gmail.com>
---
 demos/scale.ui         |  5 +++--
 pixman/pixman-filter.c | 59 ++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/demos/scale.ui b/demos/scale.ui
index b62cbfb..1e77f56 100644
--- a/demos/scale.ui
+++ b/demos/scale.ui
@@ -24,12 +24,12 @@
     <property name="page_size">10</property>
   </object>
   <object class="GtkAdjustment" id="subsample_adjustment">
-    <property name="lower">0</property>
+    <property name="lower">-256</property>
     <property name="upper">12</property>
     <property name="step_increment">1</property>
     <property name="page_increment">1</property>
     <property name="page_size">0</property>
-    <property name="value">4</property>
+    <property name="value">-12</property>
   </object>
   <object class="GtkWindow" id="main">
     <child>
@@ -321,6 +321,7 @@
                       <object class="GtkSpinButton" id="subsample_spin_button">
                         <property name="visible">True</property>
 			<property name="adjustment">subsample_adjustment</property>
+			<property name="value">-12</property>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 7a751ba..639d5e6 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -336,6 +336,47 @@ gnuplot_filter(int width, int samples, const pixman_fixed_t* p)
 }
 #endif
 
+/* Besides calculating the width, this modifies the scale and subsample_bits */
+static int
+filter_width(pixman_kernel_t reconstruct, pixman_kernel_t sample,
+	     double* scale, int* subsample_bits)
+{
+    int width;
+    /* IMPULSE.x does not work for scale < 1.0 */
+    if (reconstruct == PIXMAN_KERNEL_IMPULSE && *scale < 1.0)
+	*scale = 1.0;
+    /* Convolution adds the widths of the filters together */
+    width = ceil (filters[reconstruct].width + *scale * filters[sample].width);
+    /* If there will only be one sample, it must be 1.0 due to normalization,
+       and subsampling is useless. */
+    if (width <= 1)
+    {
+	width = 1;
+	*subsample_bits = 0;
+    }
+    else if (*subsample_bits < 0)
+    {
+	/* The intention was to do -n / scale rounded up to the next power of 2,
+	   but this non-linear function seems to work better. For large scale
+	   it is the width of the BOX.BOX filter. For small scale it reduces
+	   samples by 2 at maximum. */
+	double desired_samples = -*subsample_bits;
+	if (sample == PIXMAN_KERNEL_IMPULSE)
+	    ; /* For x.IMPULSE no scaling is done */
+	else if (*scale >= 1.0)
+	    desired_samples *= 2.0 / (*scale + 1.0);
+	else
+	    desired_samples *= 2.0 / ((*scale + 1.0) * *scale);
+	*subsample_bits = (int) ceil (log2(desired_samples) - .01);
+	if (*subsample_bits < 0)
+	    *subsample_bits = 0;
+	else if (*subsample_bits > 8)
+	    /* Assume we cannot see more than 256 different shades and limit subsampling */
+	    *subsample_bits = 8;
+    }
+    return width;
+}
+
 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
  * with the given kernels and scale parameters
  */
@@ -356,24 +397,10 @@ pixman_filter_create_separable_convolution (int             *n_values,
     int subsample_x, subsample_y;
     int width, height;
 
-    if (reconstruct_x == PIXMAN_KERNEL_IMPULSE && sx < 1.0)
-	sx = 1.0;
-    width = ceil (filters[reconstruct_x].width + sx * filters[sample_x].width);
-    if (width <= 1)
-    {
-	width = 1;
-	subsample_bits_x = 0;
-    }
+    width = filter_width(reconstruct_x, sample_x, &sx, &subsample_bits_x);
     subsample_x = (1 << subsample_bits_x);
 
-    if (reconstruct_y == PIXMAN_KERNEL_IMPULSE && sy < 1.0)
-	sy = 1.0;
-    height = ceil (filters[reconstruct_y].width + sy * filters[sample_y].width);
-    if (height <= 1)
-    {
-	height = 1;
-	subsample_bits_y = 0;
-    }
+    height = filter_width(reconstruct_y, sample_y, &sy, &subsample_bits_y);
     subsample_y = (1 << subsample_bits_y);
 
     *n_values = 4 + width * subsample_x + height * subsample_y;
-- 
1.9.1



More information about the Pixman mailing list