[Pixman] [PATCH v12 11/14] pixman-filter: Negative subsample values produces scaled result
Oded Gabbay
oded.gabbay at gmail.com
Mon Feb 8 09:24:21 CET 2016
On Mon, Feb 8, 2016 at 10:06 AM, <spitzak at gmail.com> wrote:
> From: Bill Spitzak <spitzak at gmail.com>
>
> The intention here is to produce approximately the same number of samples for
> each filter size (ie width*samples is the same). This means the caller can
> pass a constant rather than a different value for each size. To avoid conflict
> with existing code, negative numbers are used to indicate that -n samples are
> needed at size==1.
>
> For larger size the width of a BOX.BOX filter is used (the number of samples
> is scaled by 2/(size+1)). This may be more than are needed for other filters
> which increase in width faster.
>
> For smaller filters it seems 1/size would be needed to keep the same number
> of samples on the high-frequency portions. But it appears to be acceptable to
> reduce them, I used 2/((size+1)*size) which makes about 1/2 as many samples
> as size approaches zero.
>
> These functions were arrived at experimentally by testing for visible
> artifacts in the scaling of the zone plate image.
>
> The computed value is then rounded up to the next power of 2 to get the
> subsample_bits.
>
> 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
> v12: More info in the commit message
>
> Signed-off-by: Bill Spitzak <spitzak at 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/pixman
This patch is:
Acked-by: Oded Gabbay <oded.gabbay at gmail.com>
More information about the Pixman
mailing list