From: Bill Spitzak <spit...@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. This produces much more useful subsampling without the caller having to alter the subsamples depending on the scale.
The scale demo is modified to allow these negative numbers, and initially uses -12. v11: Put subsample calculation in it's own function Minor changes to comments Signed-off-by: Bill Spitzak <spit...@gmail.com> --- demos/scale.ui | 5 +++-- pixman/pixman-filter.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 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 56e25b1..e57b154 100644 --- a/pixman/pixman-filter.c +++ b/pixman/pixman-filter.c @@ -346,6 +346,37 @@ filter_width (pixman_kernel_t reconstruct, pixman_kernel_t sample, double size) return ceil (filters[reconstruct].width + size * filters[sample].width); } +/* Turn negative number into approximately ceil(ln2(-n / size)) + * Actual function is somewhat non-linear. For size > 1 it uses + * the width/2 of BOX.BOX instead of size. For size < 1 it reduces + * the samples by 1/2 as size approaches zero. + */ +static int +subsample_bits (int subsample_bits, pixman_kernel_t sample, double size) +{ + if (subsample_bits < 0) + { + /* The intention was to do -n / size rounded up to the next power of 2, + but this non-linear function seems to work better. For large size + it is the width of the BOX.BOX filter. For small size 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 (size >= 1.0) + desired_samples *= 2.0 / (size + 1.0); + else + desired_samples *= 2.0 / ((size + 1.0) * size); + if (desired_samples <= 1.0) + subsample_bits = 0; + else if (desired_samples >= 256.0) + subsample_bits = 8; + else + subsample_bits = (int) ceil (log2(desired_samples) - .01); + } + return subsample_bits; +} + /* Create the parameter list for a SEPARABLE_CONVOLUTION filter * with the given kernels and size parameters */ @@ -367,9 +398,11 @@ pixman_filter_create_separable_convolution (int *n_values, int width, height; width = filter_width (reconstruct_x, sample_x, sx); + subsample_bits_x = subsample_bits (subsample_bits_x, sample_x, sx); subsample_x = (1 << subsample_bits_x); height = filter_width (reconstruct_y, sample_y, sy); + subsample_bits_y = subsample_bits (subsample_bits_y, sample_y, sy); subsample_y = (1 << subsample_bits_y); *n_values = 4 + width * subsample_x + height * subsample_y; -- 1.9.1 _______________________________________________ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman