On Mon, Feb 8, 2016 at 10:06 AM,  <spit...@gmail.com> wrote:
> From: Bill Spitzak <spit...@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 <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
> https://lists.freedesktop.org/mailman/listinfo/pixman

This patch is:
Acked-by: Oded Gabbay <oded.gab...@gmail.com>
_______________________________________________
Pixman mailing list
Pixman@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pixman

Reply via email to