Re: [Pixman] [PATCH v9 03/15] pixman-image: Added enable-gnuplot config to view filters in gnuplot

2016-02-01 Thread Oded Gabbay
On Mon, Feb 1, 2016 at 4:10 PM, Oded Gabbay  wrote:
> On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
>> From: Bill Spitzak 
>>
>> If enable-gnuplot is configured, then you can pipe the output of a 
>> pixman-using program
>> to gnuplot and get a continuously-updated plot of the horizontal filter. This
>> works well with demos/scale to test the filter generation.
>>
>> The plot is all the different subposition filters shuffled together. This is
>> misleading in a few cases:
>>
>>   IMPULSE.BOX - goes up and down as the subfilters have different numbers of 
>> non-zero samples
>>   IMPULSE.TRIANGLE - somewhat crooked for the same reason
>>   1-wide filters - looks triangular, but a 1-wide box would be more accurate
>>
>> v8: Use config option
>> Moved code to the filter generator
>> Modified scale demo to not call filter generator a second time.
>>
>> v7: First time this ability was included

One more thing. The vX comments should be ordered from first to last
(old to new), so:
v7: ...
v8: ...

Oded

>>
>> Signed-off-by: Bill Spitzak 
>> ---
>>  configure.ac   | 13 +
>>  demos/scale.c  | 29 +++--
>>  pixman/pixman-filter.c | 45 +
>>  3 files changed, 77 insertions(+), 10 deletions(-)
>>
>> diff --git a/configure.ac b/configure.ac
>> index 6b2134e..8066cb2 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -834,6 +834,19 @@ fi
>>  AC_SUBST(PIXMAN_TIMERS)
>>
>>  dnl ===
>> +dnl gnuplot
>> +
>> +AC_ARG_ENABLE(gnuplot,
>> +   [AC_HELP_STRING([--enable-gnuplot],
>> +   [enable output of filters that can be piped to gnuplot 
>> [default=no]])],
>> +   [enable_gnuplot=$enableval], [enable_gnuplot=no])
>> +
>> +if test $enable_gnuplot = yes ; then
>> +   AC_DEFINE(PIXMAN_GNUPLOT, 1, [enable output that can be piped to 
>> gnuplot])
>> +fi
>> +AC_SUBST(PIXMAN_GNUPLOT)
>> +
>> +dnl ===
>>  dnl GTK+
>>
>>  AC_ARG_ENABLE(gtk,
>> diff --git a/demos/scale.c b/demos/scale.c
>> index 06821e3..881004e 100644
>> --- a/demos/scale.c
>> +++ b/demos/scale.c
>> @@ -258,16 +258,25 @@ rescale (GtkWidget *may_be_null, app_t *app)
>>  pixman_transform_from_pixman_f_transform (, );
>>  pixman_image_set_transform (app->original, );
>>
>> -params = pixman_filter_create_separable_convolution (
>> -_params,
>> -sx * 65536.0 + 0.5,
>> -   sy * 65536.0 + 0.5,
>> -   get_value (app, filters, "reconstruct_x_combo_box"),
>> -   get_value (app, filters, "reconstruct_y_combo_box"),
>> -   get_value (app, filters, "sample_x_combo_box"),
>> -   get_value (app, filters, "sample_y_combo_box"),
>> -   gtk_adjustment_get_value (app->subsample_adjustment),
>> -   gtk_adjustment_get_value (app->subsample_adjustment));
>> +if (get_value (app, filter_types, "filter_combo_box") ==
>> +   PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
>> +{
>> +   params = pixman_filter_create_separable_convolution (
>> +_params,
>> +   sx * 65536.0 + 0.5,
>> +   sy * 65536.0 + 0.5,
>> +   get_value (app, filters, "reconstruct_x_combo_box"),
>> +   get_value (app, filters, "reconstruct_y_combo_box"),
>> +   get_value (app, filters, "sample_x_combo_box"),
>> +   get_value (app, filters, "sample_y_combo_box"),
>> +   gtk_adjustment_get_value (app->subsample_adjustment),
>> +   gtk_adjustment_get_value (app->subsample_adjustment));
>> +}
>> +else
>> +{
>> +   params = 0;
>> +   n_params = 0;
>> +}
>
> Wait, what the above code has to do with this patch ?
> It wasn't in the previous version (v7) and I don't see how it is
> related to the gnuplot.
> This seems like a fix to the demo code.
> If what I said is correct, please split it into a different patch.
>
>>
>>  pixman_image_set_filter (app->original,
>> get_value (app, filter_types, "filter_combo_box"),
>> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
>> index b2bf53f..fe0d261 100644
>> --- a/pixman/pixman-filter.c
>> +++ b/pixman/pixman-filter.c
>> @@ -297,6 +297,47 @@ create_1d_filter (int *width,
>>  return params;
>>  }
>>
>> +#if PIXMAN_GNUPLOT
>
> To keep consistency with other defines checks, please use #ifdef when
> checking just one define
>
>> +/* If enable-gnuplot is configured, then you can pipe the output of a
>> + * pixman-using program to gnuplot and get a continuously-updated plot
>> + * of the horizontal filter. This works well with demos/scale to test
>> + * the filter generation.
>> + *
>> + * The plot is all the different subposition filters shuffled
>> + * together. This is misleading in a few cases:
>> + *
>> + *  IMPULSE.BOX - goes up and down as the subfilters have different
>> + *numbers of non-zero samples
>> + *  

Re: [Pixman] [PATCH v9 02/15] demos/scale: Added pulldown to choose PIXMAN_FILTER_* value

2016-02-01 Thread Oded Gabbay
On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> From: Bill Spitzak 
>
> This allows testing of GOOD/BEST and to do comparisons between
> the basic filters and PIXMAN_FILTER_SEPARABLE_CONVOLUTION settings.
>
> Signed-off-by: Bill Spitzak 
> ---
>  demos/scale.c  | 14 +-
>  demos/scale.ui | 40 ++--
>  2 files changed, 43 insertions(+), 11 deletions(-)
>
> diff --git a/demos/scale.c b/demos/scale.c
> index 0995ad0..06821e3 100644
> --- a/demos/scale.c
> +++ b/demos/scale.c
> @@ -127,6 +127,15 @@ typedef struct
>  intvalue;
>  } named_int_t;
>
> +static const named_int_t filter_types[] =
> +{
> +{ "Separable", PIXMAN_FILTER_SEPARABLE_CONVOLUTION },
> +{ "Nearest",   PIXMAN_FILTER_NEAREST },
> +{ "Bilinear",  PIXMAN_FILTER_BILINEAR },
> +{ "Good",  PIXMAN_FILTER_GOOD },
> +{ "Best",  PIXMAN_FILTER_BEST },
> +};
> +
>  static const named_int_t filters[] =
>  {
>  { "Box",   PIXMAN_KERNEL_BOX },
> @@ -260,7 +269,9 @@ rescale (GtkWidget *may_be_null, app_t *app)
> gtk_adjustment_get_value (app->subsample_adjustment),
> gtk_adjustment_get_value (app->subsample_adjustment));
>
> -pixman_image_set_filter (app->original, 
> PIXMAN_FILTER_SEPARABLE_CONVOLUTION, params, n_params);
> +pixman_image_set_filter (app->original,
> +   get_value (app, filter_types, "filter_combo_box"),
> +   params, n_params);
>
>  pixman_image_set_repeat (
>  app->original, get_value (app, repeats, "repeat_combo_box"));
> @@ -402,6 +413,7 @@ app_new (pixman_image_t *original)
>  widget = get_widget (app, "drawing_area");
>  g_signal_connect (widget, "expose_event", G_CALLBACK (on_expose), app);
>
> +set_up_combo_box (app, "filter_combo_box", G_N_ELEMENTS (filter_types), 
> filter_types);
>  set_up_filter_box (app, "reconstruct_x_combo_box");
>  set_up_filter_box (app, "reconstruct_y_combo_box");
>  set_up_filter_box (app, "sample_x_combo_box");
> diff --git a/demos/scale.ui b/demos/scale.ui
> index ee985dd..b62cbfb 100644
> --- a/demos/scale.ui
> +++ b/demos/scale.ui
> @@ -191,12 +191,23 @@
>  8
>  6
>  
> +  
> +True
> +1
> + translatable="yes">bFilter:/b
> +True
> +  
> +
> +
>
>  True
>  1
>   translatable="yes">bReconstruct X:/b
>  True
>
> +  
> +1
> +  
>  
>  
>
> @@ -206,7 +217,7 @@
>  True
>
>
> -1
> +2
>
>  
>  
> @@ -217,7 +228,7 @@
>  True
>
>
> -2
> +3
>
>  
>  
> @@ -228,7 +239,7 @@
>  True
>
>
> -3
> +4
>
>  
>  
> @@ -239,7 +250,7 @@
>  True
>
>
> -4
> +5
>
>  
>  
> @@ -250,7 +261,15 @@
>  True
>
>
> -5
> +6
> +  
> +
> +
> +  
> +True
> +  
> +  
> +1
>
>  
>  
> @@ -259,6 +278,7 @@
>
>
>  1
> +1
>
>  
>  
> @@ -267,7 +287,7 @@
>
>
>  1
> -1
> +2
>
>  
>  
> @@ -276,7 +296,7 @@
>
>
>  1
> -2
> +3
>   

Re: [Pixman] [PATCH v9 03/15] pixman-image: Added enable-gnuplot config to view filters in gnuplot

2016-02-01 Thread Oded Gabbay
On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> From: Bill Spitzak 
>
> If enable-gnuplot is configured, then you can pipe the output of a 
> pixman-using program
> to gnuplot and get a continuously-updated plot of the horizontal filter. This
> works well with demos/scale to test the filter generation.
>
> The plot is all the different subposition filters shuffled together. This is
> misleading in a few cases:
>
>   IMPULSE.BOX - goes up and down as the subfilters have different numbers of 
> non-zero samples
>   IMPULSE.TRIANGLE - somewhat crooked for the same reason
>   1-wide filters - looks triangular, but a 1-wide box would be more accurate
>
> v8: Use config option
> Moved code to the filter generator
> Modified scale demo to not call filter generator a second time.
>
> v7: First time this ability was included
>
> Signed-off-by: Bill Spitzak 
> ---
>  configure.ac   | 13 +
>  demos/scale.c  | 29 +++--
>  pixman/pixman-filter.c | 45 +
>  3 files changed, 77 insertions(+), 10 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index 6b2134e..8066cb2 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -834,6 +834,19 @@ fi
>  AC_SUBST(PIXMAN_TIMERS)
>
>  dnl ===
> +dnl gnuplot
> +
> +AC_ARG_ENABLE(gnuplot,
> +   [AC_HELP_STRING([--enable-gnuplot],
> +   [enable output of filters that can be piped to gnuplot 
> [default=no]])],
> +   [enable_gnuplot=$enableval], [enable_gnuplot=no])
> +
> +if test $enable_gnuplot = yes ; then
> +   AC_DEFINE(PIXMAN_GNUPLOT, 1, [enable output that can be piped to gnuplot])
> +fi
> +AC_SUBST(PIXMAN_GNUPLOT)
> +
> +dnl ===
>  dnl GTK+
>
>  AC_ARG_ENABLE(gtk,
> diff --git a/demos/scale.c b/demos/scale.c
> index 06821e3..881004e 100644
> --- a/demos/scale.c
> +++ b/demos/scale.c
> @@ -258,16 +258,25 @@ rescale (GtkWidget *may_be_null, app_t *app)
>  pixman_transform_from_pixman_f_transform (, );
>  pixman_image_set_transform (app->original, );
>
> -params = pixman_filter_create_separable_convolution (
> -_params,
> -sx * 65536.0 + 0.5,
> -   sy * 65536.0 + 0.5,
> -   get_value (app, filters, "reconstruct_x_combo_box"),
> -   get_value (app, filters, "reconstruct_y_combo_box"),
> -   get_value (app, filters, "sample_x_combo_box"),
> -   get_value (app, filters, "sample_y_combo_box"),
> -   gtk_adjustment_get_value (app->subsample_adjustment),
> -   gtk_adjustment_get_value (app->subsample_adjustment));
> +if (get_value (app, filter_types, "filter_combo_box") ==
> +   PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
> +{
> +   params = pixman_filter_create_separable_convolution (
> +_params,
> +   sx * 65536.0 + 0.5,
> +   sy * 65536.0 + 0.5,
> +   get_value (app, filters, "reconstruct_x_combo_box"),
> +   get_value (app, filters, "reconstruct_y_combo_box"),
> +   get_value (app, filters, "sample_x_combo_box"),
> +   get_value (app, filters, "sample_y_combo_box"),
> +   gtk_adjustment_get_value (app->subsample_adjustment),
> +   gtk_adjustment_get_value (app->subsample_adjustment));
> +}
> +else
> +{
> +   params = 0;
> +   n_params = 0;
> +}

Wait, what the above code has to do with this patch ?
It wasn't in the previous version (v7) and I don't see how it is
related to the gnuplot.
This seems like a fix to the demo code.
If what I said is correct, please split it into a different patch.

>
>  pixman_image_set_filter (app->original,
> get_value (app, filter_types, "filter_combo_box"),
> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
> index b2bf53f..fe0d261 100644
> --- a/pixman/pixman-filter.c
> +++ b/pixman/pixman-filter.c
> @@ -297,6 +297,47 @@ create_1d_filter (int *width,
>  return params;
>  }
>
> +#if PIXMAN_GNUPLOT

To keep consistency with other defines checks, please use #ifdef when
checking just one define

> +/* If enable-gnuplot is configured, then you can pipe the output of a
> + * pixman-using program to gnuplot and get a continuously-updated plot
> + * of the horizontal filter. This works well with demos/scale to test
> + * the filter generation.
> + *
> + * The plot is all the different subposition filters shuffled
> + * together. This is misleading in a few cases:
> + *
> + *  IMPULSE.BOX - goes up and down as the subfilters have different
> + *numbers of non-zero samples
> + *  IMPULSE.TRIANGLE - somewhat crooked for the same reason
> + *  1-wide filters - looks triangular, but a 1-wide box would be more
> + *   accurate
> + */
> +static void
> +gnuplot_filter(int width, int samples, const pixman_fixed_t* p)
> +{
> +int x,y;
> +printf("plot '-' with linespoints\n");
> +

Re: [Pixman] [PATCH v9 06/15] pixman-filter: Correct Simpsons integration

2016-02-01 Thread Bill Spitzak
DOH!

You are right, I should make sure each step compiles. I am also very much
tempted to change "scale" to "size" to avoid the fact that the value is
approximately the reciprocal of what must users would call the "scale" of
the transform. That will require testing each patch.


On Mon, Feb 1, 2016 at 6:34 AM, Oded Gabbay  wrote:

> On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> > From: Bill Spitzak 
> >
> > Simpsons uses cubic curve fitting, with 3 samples defining each cubic.
> This
> > makes the weights of the samples be in a pattern of 1,4,2,4,2...4,1, and
> then
> > dividing the result by 3.
> >
> > The previous code was using weights of 1,2,6,6...6,2,1. Since it divided
> by
> > 3 this produced about 2x the desired value (the normalization fixed
> this).
> > Also this is effectively a linear interpolation, not Simpsons
> integration.
> >
> > With this fix the integration is accurate enough that the number of
> samples
> > could be reduced a lot. Multiples of 12 seem to work best.
> >
> > v9: Changed samples from 16 to 12
> > v7: Merged with patch to reduce from 128 samples to 16
> >
> > Signed-off-by: Bill Spitzak 
> > ---
> >  pixman/pixman-filter.c | 29 +++--
> >  1 file changed, 19 insertions(+), 10 deletions(-)
> >
> > diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
> > index 55073c4..718649a 100644
> > --- a/pixman/pixman-filter.c
> > +++ b/pixman/pixman-filter.c
> > @@ -189,13 +189,19 @@ integral (pixman_kernel_t reconstruct, double x1,
> >  }
> >  else
> >  {
> > -   /* Integration via Simpson's rule */
> > -#define N_SEGMENTS 128
> > -#define SAMPLE(a1, a2) \
> > -   (filters[reconstruct].func ((a1)) * filters[sample].func ((a2) /
> scale))
> > -
> > +   /* Integration via Simpson's rule
> > +* See http://www.intmath.com/integration/6-simpsons-rule.php
> > +* 12 segments (6 cubic approximations) seems to produce best
> > +* result for lanczos3.linear, which was the combination that
> > +* showed the most errors.  This makes sense as the lanczos3
> > +* filter is 6 wide.
> > +*/
> > +#define N_SEGMENTS 12
> > +#define SAMPLE(a)  \
> > +   (filters[reconstruct].func ((a)) * filters[sample].func (((a) -
> pos) / scale))
> > +
> You changed the SAMPLE macro to get 1 parameter, but in all the calls
> you send 2 parameters, which make the compilation fail.
>
> Please fix this and resend the patch.
>
> Oded
>
> > double s = 0.0;
> > -   double h = width / (double)N_SEGMENTS;
> > +   double h = width / N_SEGMENTS;
> > int i;
> >
> > s = SAMPLE (x1, x2);
> > @@ -204,11 +210,14 @@ integral (pixman_kernel_t reconstruct, double x1,
> > {
> > double a1 = x1 + h * i;
> > double a2 = x2 + h * i;
> > +   s += 4 * SAMPLE(a1, a2);
> > +   }
> >
> > -   s += 2 * SAMPLE (a1, a2);
> > -
> > -   if (i >= 2 && i < N_SEGMENTS - 1)
> > -   s += 4 * SAMPLE (a1, a2);
> > +   for (i = 2; i < N_SEGMENTS; i += 2)
> > +   {
> > +   double a1 = x1 + h * i;
> > +   double a2 = x2 + h * i;
> > +   s += 2 * SAMPLE(a1, a2);
> > }
> >
> > s += SAMPLE (x1 + width, x2 + width);
> > --
> > 1.9.1
> >
> > ___
> > Pixman mailing list
> > Pixman@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/pixman
>
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 06/15] pixman-filter: reduce amount of malloc/free/memcpy to generate filter

2016-02-01 Thread spitzak
From: Bill Spitzak 

Rearranged so that the entire block of memory for the filter pair
is allocated first, and then filled in. Previous version allocated
and freed two temporary buffers for each filter and did an extra
memcpy.

v8: small refactor to remove the filter_width function

v10: Restored filter_width function but with arguments changed to
 match later patches

Signed-off-by: Bill Spitzak 

Reviewed-by: Oded Gabbay 
---
 pixman/pixman-filter.c | 59 ++
 1 file changed, 26 insertions(+), 33 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index acfb110..6c077b6 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -217,23 +217,17 @@ integral (pixman_kernel_t reconstruct, double x1,
 }
 }
 
-static pixman_fixed_t *
-create_1d_filter (int *width,
+static void
+create_1d_filter (int  width,
  pixman_kernel_t  reconstruct,
  pixman_kernel_t  sample,
  double   size,
- int  n_phases)
+ int  n_phases,
+ pixman_fixed_t *p)
 {
-pixman_fixed_t *params, *p;
 double step;
 int i;
 
-*width = ceil (size * filters[sample].width + filters[reconstruct].width);
-
-p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
-if (!params)
-return NULL;
-
 step = 1.0 / n_phases;
 
 for (i = 0; i < n_phases; ++i)
@@ -248,8 +242,8 @@ create_1d_filter (int *width,
 * and sample positions.
 */
 
-   x1 = ceil (frac - *width / 2.0 - 0.5);
-x2 = x1 + *width;
+   x1 = ceil (frac - width / 2.0 - 0.5);
+x2 = x1 + width;
 
total = 0;
 for (x = x1; x < x2; ++x)
@@ -277,7 +271,7 @@ create_1d_filter (int *width,
 }
 
/* Normalize */
-   p -= *width;
+   p -= width;
 total = 1 / total;
 new_total = 0;
for (x = x1; x < x2; ++x)
@@ -289,10 +283,8 @@ create_1d_filter (int *width,
}
 
if (new_total != pixman_fixed_1)
-   *(p - *width / 2) += (pixman_fixed_1 - new_total);
+   *(p - width / 2) += (pixman_fixed_1 - new_total);
 }
-
-return params;
 }
 
 #ifdef PIXMAN_GNUPLOT
@@ -336,6 +328,14 @@ gnuplot_filter(int width, int samples, const 
pixman_fixed_t* p)
 }
 #endif
 
+/* Besides calculating the width, this can modify the scale and subsample_bits 
*/
+static int
+filter_width(pixman_kernel_t reconstruct, pixman_kernel_t sample,
+double* size, int* subsample_bits)
+{
+return ceil (filters[reconstruct].width + *size * filters[sample].width);
+}
+
 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
  * with the given kernels and size parameters
  */
@@ -352,42 +352,35 @@ pixman_filter_create_separable_convolution (int   
  *n_values,
 {
 double sx = fabs (pixman_fixed_to_double (size_x));
 double sy = fabs (pixman_fixed_to_double (size_y));
-pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL;
+pixman_fixed_t *params;
 int subsample_x, subsample_y;
 int width, height;
 
+width = filter_width (reconstruct_x, sample_x, , _bits_x);
 subsample_x = (1 << subsample_bits_x);
-subsample_y = (1 << subsample_bits_y);
 
-horz = create_1d_filter (, reconstruct_x, sample_x, sx, subsample_x);
-vert = create_1d_filter (, reconstruct_y, sample_y, sy, 
subsample_y);
+height = filter_width (reconstruct_y, sample_y, , _bits_y);
+subsample_y = (1 << subsample_bits_y);
 
-if (!horz || !vert)
-goto out;
-
 *n_values = 4 + width * subsample_x + height * subsample_y;
-
+
 params = malloc (*n_values * sizeof (pixman_fixed_t));
 if (!params)
-goto out;
+return NULL;
 
 params[0] = pixman_int_to_fixed (width);
 params[1] = pixman_int_to_fixed (height);
 params[2] = pixman_int_to_fixed (subsample_bits_x);
 params[3] = pixman_int_to_fixed (subsample_bits_y);
 
-memcpy (params + 4, horz,
-   width * subsample_x * sizeof (pixman_fixed_t));
-memcpy (params + 4 + width * subsample_x, vert,
-   height * subsample_y * sizeof (pixman_fixed_t));
+create_1d_filter (width, reconstruct_x, sample_x, sx, subsample_x,
+ params + 4);
+create_1d_filter (height, reconstruct_y, sample_y, sy, subsample_y,
+ params + 4 + width * subsample_x);
 
 #ifdef PIXMAN_GNUPLOT
 gnuplot_filter(width, subsample_x, params+4);
 #endif
 
-out:
-free (horz);
-free (vert);
-
 return params;
 }
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 08/15] pixman-filter: Corrections to the integral() function

2016-02-01 Thread spitzak
From: Bill Spitzak 

The IMPULSE special-cases did not sample the center of the of the region.
This caused it to sample the filters outside their range, and produce
assymetric filters and other errors. Fixing this required changing the
arguments to integral() so the correct point could be determined.

I fixed the nice filter and the integration to directly produce normalized
values. Re-normalization is still needed for impulse.box or impulse.triangle
so I did not remove it.

Distribute fixed error over all filter samples, to remove a high-frequency
bit of noise in the center of some filters (lancoz at large scale value).

box.box, which I expect will be very common as it is the proposed "good" filter,
was made a lot faster and more accurate. This is easy as the caller already
intersected the two boxes, so the width is the integral.

v7: This is a merge of 4 patches and lots of new code cleanup and fixes
 determined by examining the gnuplot output

v9: Restored the recursion splitting at zero for linear filter

v10: Small change from here moved to previous Simpsons patch so it compiles

 Merged patch to get correct subsample positions when subsample_bits==0

Signed-off-by: Bill Spitzak 
---
 pixman/pixman-filter.c | 144 +
 1 file changed, 74 insertions(+), 70 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 13ee024..bd4e174 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -79,7 +79,7 @@ sinc (double x)
 }
 
 static double
-lanczos (double x, int n)
+lanczos (double x, double n)
 {
 return sinc (x) * sinc (x * (1.0 / n));
 }
@@ -99,7 +99,7 @@ lanczos3_kernel (double x)
 static double
 nice_kernel (double x)
 {
-return lanczos3_kernel (x * 0.75);
+return lanczos3_kernel (x * 0.75) * 0.75;
 }
 
 static double
@@ -147,45 +147,51 @@ static const filter_info_t filters[] =
 { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
 };
 
-/* This function scales the @sample filter by @size, then
- * aligns @x1 in @reconstruct with @x2 in @sample and
- * and integrates the product of the kernels across @width.
+/* This function scales the @sample filter by @size, shifts it by @pos,
+ * and then integrates the product of the kernels across low..high
  *
  * This function assumes that the intervals are within
  * the kernels in question. E.g., the caller must not
  * try to integrate a linear kernel ouside of [-1:1]
  */
 static double
-integral (pixman_kernel_t reconstruct, double x1,
- pixman_kernel_t sample, double size, double x2,
- double width)
+integral (pixman_kernel_t reconstruct,
+ pixman_kernel_t sample, double size, double pos,
+ double low, double high)
 {
+if (high < low)
+{
+   return 0.0;
+}
+else if (sample == PIXMAN_KERNEL_IMPULSE)
+{
+   return filters[reconstruct].func (-pos);
+}
+else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
+{
+   return filters[sample].func (-pos / size) / size;
+}
+else if (reconstruct == PIXMAN_KERNEL_BOX && sample == PIXMAN_KERNEL_BOX)
+{
+   assert (high <= low + 1.0);
+   return (high - low) / size;
+}
 /* If the integration interval crosses zero, break it into
  * two separate integrals. This ensures that filters such
  * as LINEAR that are not differentiable at 0 will still
  * integrate properly.
  */
-if (x1 < 0 && x1 + width > 0)
+else if (reconstruct == PIXMAN_KERNEL_LINEAR && low < 0 && high > 0)
 {
return
-   integral (reconstruct, x1, sample, size, x2, - x1) +
-   integral (reconstruct, 0, sample, size, x2 - x1, width + x1);
+   integral (reconstruct, sample, size, pos, low, 0) +
+   integral (reconstruct, sample, size, pos, 0, high);
 }
-else if (x2 < 0 && x2 + width > 0)
+else if (sample == PIXMAN_KERNEL_LINEAR && low < pos && high > pos)
 {
return
-   integral (reconstruct, x1, sample, size, x2, - x2) +
-   integral (reconstruct, x1 - x2, sample, size, 0, width + x2);
-}
-else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
-{
-   assert (width == 0.0);
-   return filters[sample].func (x2 / size);
-}
-else if (sample == PIXMAN_KERNEL_IMPULSE)
-{
-   assert (width == 0.0);
-   return filters[reconstruct].func (x1);
+   integral (reconstruct, sample, size, pos, low, pos) +
+   integral (reconstruct, sample, size, pos, pos, high);
 }
 else
 {
@@ -197,32 +203,30 @@ integral (pixman_kernel_t reconstruct, double x1,
 * filter is 6 wide.
 */
 #define N_SEGMENTS 12
-#define SAMPLE(a1, a2) \
-   (filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / size))
+#define SAMPLE(a)  \
+(filters[reconstruct].func 

[Pixman] [PATCH v10 04/15] pixman-image: Added enable-gnuplot config to view filters in gnuplot

2016-02-01 Thread spitzak
From: Bill Spitzak 

If enable-gnuplot is configured, then you can pipe the output of a pixman-using 
program
to gnuplot and get a continuously-updated plot of the horizontal filter. This
works well with demos/scale to test the filter generation.

The plot is all the different subposition filters shuffled together. This is
misleading in a few cases:

  IMPULSE.BOX - goes up and down as the subfilters have different numbers of 
non-zero samples
  IMPULSE.TRIANGLE - somewhat crooked for the same reason
  1-wide filters - looks triangular, but a 1-wide box would be more accurate

v7: First time this ability was included

v8: Use config option
Moved code to the filter generator
Modified scale demo to not call filter generator a second time.

v10: Only print if successful generation of plots
 Use #ifdef, not #if

Signed-off-by: Bill Spitzak 
---
 configure.ac   | 13 +
 pixman/pixman-filter.c | 45 +
 2 files changed, 58 insertions(+)

diff --git a/configure.ac b/configure.ac
index 6b2134e..8066cb2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -834,6 +834,19 @@ fi
 AC_SUBST(PIXMAN_TIMERS)
 
 dnl ===
+dnl gnuplot
+
+AC_ARG_ENABLE(gnuplot,
+   [AC_HELP_STRING([--enable-gnuplot],
+   [enable output of filters that can be piped to gnuplot 
[default=no]])],
+   [enable_gnuplot=$enableval], [enable_gnuplot=no])
+
+if test $enable_gnuplot = yes ; then 
+   AC_DEFINE(PIXMAN_GNUPLOT, 1, [enable output that can be piped to gnuplot])
+fi
+AC_SUBST(PIXMAN_GNUPLOT)
+
+dnl ===
 dnl GTK+
 
 AC_ARG_ENABLE(gtk,
diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index b2bf53f..11c8548 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -297,6 +297,47 @@ create_1d_filter (int *width,
 return params;
 }
 
+#ifdef PIXMAN_GNUPLOT
+/* If enable-gnuplot is configured, then you can pipe the output of a
+ * pixman-using program to gnuplot and get a continuously-updated plot
+ * of the horizontal filter. This works well with demos/scale to test
+ * the filter generation.
+ *
+ * The plot is all the different subposition filters shuffled
+ * together. This is misleading in a few cases:
+ *
+ *  IMPULSE.BOX - goes up and down as the subfilters have different
+ *numbers of non-zero samples
+ *  IMPULSE.TRIANGLE - somewhat crooked for the same reason
+ *  1-wide filters - looks triangular, but a 1-wide box would be more
+ *   accurate
+ */
+static void
+gnuplot_filter(int width, int samples, const pixman_fixed_t* p)
+{
+int x,y;
+printf("plot '-' with linespoints\n");
+printf("%g 0\n", - width * .5);
+for (x = 0; x < width; ++x) {
+   for (y = 0; y < samples; ++y) {
+   int yy;
+   if (width & 1)
+   yy = y;
+   else if (y >= samples / 2)
+   yy = y - samples / 2;
+   else
+   yy = samples / 2 + y;
+   printf("%g %g\n",
+  x - width * 0.5 + (y + 0.5) * (1.0 / samples),
+  pixman_fixed_to_double(p[(yy + 1) * width - x - 1]));
+   }
+}
+printf("%g 0\n", width * .5);
+printf("e\n");
+fflush(stdout);
+}
+#endif
+
 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
  * with the given kernels and scale parameters
  */
@@ -342,6 +383,10 @@ pixman_filter_create_separable_convolution (int
 *n_values,
 memcpy (params + 4 + width * subsample_x, vert,
height * subsample_y * sizeof (pixman_fixed_t));
 
+#ifdef PIXMAN_GNUPLOT
+gnuplot_filter(width, subsample_x, params+4);
+#endif
+
 out:
 free (horz);
 free (vert);
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 12/15] pixman-filter: Made reconstruct==impulse and scale < 1 set scale to 1

2016-02-01 Thread spitzak
From: Bill Spitzak 

This replaces settings that don't work (because the filter cannot be normalized)
with something that produces an image.

v7: First version with this. Previously you got lots of strange garbage filters
 that depended on the implementation.

v10: Moved code to filter_width function

Signed-off-by: Bill Spitzak 
---
 pixman/pixman-filter.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 520ce92..f28cc29 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -341,7 +341,10 @@ static int
 filter_width(pixman_kernel_t reconstruct, pixman_kernel_t sample,
 double* size, int* subsample_bits)
 {
-int width = ceil (filters[reconstruct].width + *size * 
filters[sample].width);
+int width;
+if (reconstruct == PIXMAN_KERNEL_IMPULSE && *size < 1.0)
+   *size = 1.0;
+width = ceil (filters[reconstruct].width + *size * filters[sample].width);
 if (width <= 1)
 {
width = 1;
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 14/15] pixman-filter: Add description to pixman_filter_create_separable_convolution()

2016-02-01 Thread spitzak
From: Bill Spitzak 

v9: Described arguments and more filter combinations, fixed some errors.

Signed-off-by: Bill Spitzak 

Reviewed-by: Oded Gabbay 
---
 pixman/pixman-filter.c | 45 +
 1 file changed, 45 insertions(+)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 6e8024a..d795573 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -379,6 +379,51 @@ filter_width(pixman_kernel_t reconstruct, pixman_kernel_t 
sample,
 
 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
  * with the given kernels and size parameters
+ *
+ * Returns pointer to the block of numbers
+ *
+ * n_values: pointer to integer to store size of the block
+ *
+ * scale_x/y: amount to stretch the sample filter. Note that scale
+ * is the inverse of how the image is being scaled, if the image is
+ * being made smaller, the filter gets larger.
+ *
+ * reconstruct_x/y: filter that is not scaled.
+ *
+ * sample_x/y: filter that is scaled. Resoult is convolved with reconstruct 
filter.
+ *
+ * subsample_bits_x/y: If positive there are 2^n subpixel positions computed 
for
+ * the filter. If negative then -n (rounded up to the next power of 2) 
positions
+ * are calculated when scale==1, but fewer are computed for larger scales and
+ * more for smaller scales.
+ *
+ * Some interesting reconstruct.sample combinations:
+ *
+ *  IMPULSE.x - Uses the sample function only. This is what many other pieces 
of
+ *  software do. Does not work for scale < 1.0.
+ *
+ *  BOX.x - For scale < 1.0 this produces square pixels. For scale > 1.0 this
+ *  approaches IMPULSE.x as scale gets larger.
+ *
+ *  x.IMPULSE - Uses the reconstruct function only, scale is ignored.
+ *
+ *  BOX.BOX, LINEAR.IMPULSE, IMPULSE.LINEAR - at scale==1 these all match and
+ *  also produce same result as bilinear filtering.
+ *
+ *  BOX.BOX - Produces a trapazoid-shape. Narrowest possible filter with 
antialiasing.
+ *Matches a lot of other software, some call it "box", others call 
it "linear"
+ *
+ *  BOX.LINEAR - At scale==1 this is what some software calls a Quadratic 
filter
+ *
+ *  IMPULSE.LINEAR - Some software calls this "linear" or "triangle". Not a 
good filter.
+ *
+ *  LINEAR.LINEAR - non-negative cubic. What some software calls "cubic 
interpolation".
+ *
+ *  IMPULSE.LANCZOS2 - Close to what a lot of other software calls "cubic 
interpolation"
+ *
+ *  IMPULSE.CUBIC - Called "Mitchell" in other software
+ *
+ *  IMPULSE.GAUSSIAN - Best removal of aliasing but usually considered too 
blurry
  */
 PIXMAN_EXPORT pixman_fixed_t *
 pixman_filter_create_separable_convolution (int *n_values,
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 15/15] pixman-image: Implement PIXMAN_FILTER_GOOD/BEST as separable convolutions

2016-02-01 Thread spitzak
From: Bill Spitzak 

Detects and uses PIXMAN_FILTER_NEAREST for all 8 90-degree rotations and
reflections when the scale is 1.0 and integer translation.

GOOD uses:

 scale < 1/16 : BOX.BOX at size 16
 scale < 3/4 : BOX.BOX at size 1/scale
 larger : BOX.BOX at size 1

 If both directions have a scale >= 3/4 or a scale of 1/2 and an integer
 translation, the faster PIXMAN_FILTER_BILINEAR code is used. This is
 compatable at these scales with older versions of pixman where bilinear
 was always used for GOOD.

BEST uses:

 scale < 1/24 : BOX.BOX at size 24
 scale < 1/16 : BOX.BOX at size 1/scale
 scale < 1 : IMPULSE.LANCZOS2 at size 1/scale
 scale < 2.333 : IMPULSE.LANCZOS2 at size 1
 scale < 128 : BOX.LANCZOS2 at size 1/(scale-1) (antialiased square pixels)
 larger : BOX.LANCZOS2 at size 1/127 (antialias blur gets thicker)

v8: Cutoff in BEST between IMPULSE.LANCZOS2 and BOX.LANCZOS2 adjusted for
a better match between the filters.

v9: Use the new negative subsample controls to scale the subsamples. These
were chosen by finding the lowest number that did not add visible
artifacts to the zone plate image.

Scale demo altered to default to GOOD and locked-together x+y scale

Fixed divide-by-zero from all-zero matrix found by stress-test

Signed-off-by: Bill Spitzak 
---
 demos/scale.c |  10 +-
 demos/scale.ui|   1 +
 pixman/pixman-image.c | 289 --
 3 files changed, 216 insertions(+), 84 deletions(-)

diff --git a/demos/scale.c b/demos/scale.c
index 881004e..3df4442 100644
--- a/demos/scale.c
+++ b/demos/scale.c
@@ -340,7 +340,7 @@ on_expose (GtkWidget *da, GdkEvent *event, gpointer data)
 
 static void
 set_up_combo_box (app_t *app, const char *box_name,
-  int n_entries, const named_int_t table[])
+  int n_entries, const named_int_t table[], int active)
 {
 GtkWidget *widget = get_widget (app, box_name);
 GtkListStore *model;
@@ -366,7 +366,7 @@ set_up_combo_box (app_t *app, const char *box_name,
gtk_list_store_set (model, , 0, info->name, -1);
 }
 
-gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+gtk_combo_box_set_active (GTK_COMBO_BOX (widget), active);
 
 g_signal_connect (widget, "changed", G_CALLBACK (rescale), app);
 }
@@ -374,7 +374,7 @@ set_up_combo_box (app_t *app, const char *box_name,
 static void
 set_up_filter_box (app_t *app, const char *box_name)
 {
-set_up_combo_box (app, box_name, G_N_ELEMENTS (filters), filters);
+set_up_combo_box (app, box_name, G_N_ELEMENTS (filters), filters, 0);
 }
 
 static char *
@@ -422,14 +422,14 @@ app_new (pixman_image_t *original)
 widget = get_widget (app, "drawing_area");
 g_signal_connect (widget, "expose_event", G_CALLBACK (on_expose), app);
 
-set_up_combo_box (app, "filter_combo_box", G_N_ELEMENTS (filter_types), 
filter_types);
+set_up_combo_box (app, "filter_combo_box", G_N_ELEMENTS (filter_types), 
filter_types, 3);
 set_up_filter_box (app, "reconstruct_x_combo_box");
 set_up_filter_box (app, "reconstruct_y_combo_box");
 set_up_filter_box (app, "sample_x_combo_box");
 set_up_filter_box (app, "sample_y_combo_box");
 
 set_up_combo_box (
-app, "repeat_combo_box", G_N_ELEMENTS (repeats), repeats);
+   app, "repeat_combo_box", G_N_ELEMENTS (repeats), repeats, 0);
 
 g_signal_connect (
gtk_builder_get_object (app->builder, "lock_checkbutton"),
diff --git a/demos/scale.ui b/demos/scale.ui
index 1e77f56..13e0e0d 100644
--- a/demos/scale.ui
+++ b/demos/scale.ui
@@ -177,6 +177,7 @@
  id="lock_checkbutton">
Lock X and Y 
Dimensions
0.0
+   True
  
   
 False
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 1ff1a49..c381260 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "pixman-private.h"
 
@@ -274,112 +275,242 @@ compute_image_info (pixman_image_t *image)
  FAST_PATH_X_UNIT_POSITIVE |
  FAST_PATH_Y_UNIT_ZERO |
  FAST_PATH_AFFINE_TRANSFORM);
+   switch (image->common.filter)
+   {
+   case PIXMAN_FILTER_CONVOLUTION:
+   break;
+   case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
+   flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
+   break;
+   default:
+   flags |= (FAST_PATH_NEAREST_FILTER | 
FAST_PATH_NO_CONVOLUTION_FILTER);
+   break;
+   }
 }
 else
 {
+   pixman_fixed_t (*m)[3] = image->common.transform->matrix;
+   double dx, dy;
+   int nearest_ok, bilinear_ok;
+
flags |= FAST_PATH_HAS_TRANSFORM;
 
-   if (image->common.transform->matrix[2][0] == 0  &&
-   image->common.transform->matrix[2][1] 

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

2016-02-01 Thread spitzak
From: Bill Spitzak 

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.

Signed-off-by: Bill Spitzak 
---
 demos/scale.ui |  5 +++--
 pixman/pixman-filter.c | 24 
 2 files changed, 27 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 @@
 10
   
   
-0
+-256
 12
 1
 1
 0
-4
+-12
   
   
 
@@ -321,6 +321,7 @@
   
 True
subsample_adjustment
+   -12
   
   
 1
diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index f28cc29..6e8024a 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -342,14 +342,38 @@ filter_width(pixman_kernel_t reconstruct, pixman_kernel_t 
sample,
 double* size, int* subsample_bits)
 {
 int width;
+/* IMPULSE.x does not work for size < 1.0 */
 if (reconstruct == PIXMAN_KERNEL_IMPULSE && *size < 1.0)
*size = 1.0;
+/* Convolution adds the widths of the filters together */
 width = ceil (filters[reconstruct].width + *size * 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 / 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);
+   *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;
 }
 
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 11/15] pixman-filter: Turn off subsampling for width=1 filters

2016-02-01 Thread spitzak
From: Bill Spitzak 

Due to normalization these filters must all be identical (a single 1.0).

Also make IMPULSE.IMPULSE produce a width=1 filter, rather than zero
(which did not work).

v7: Replaced earlier tests for BOX.IMPULSE
v10: Moved code to filter_width function

Signed-off-by: Bill Spitzak 
---
 pixman/pixman-filter.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 10fa398..520ce92 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -341,7 +341,13 @@ static int
 filter_width(pixman_kernel_t reconstruct, pixman_kernel_t sample,
 double* size, int* subsample_bits)
 {
-return ceil (filters[reconstruct].width + *size * filters[sample].width);
+int width = ceil (filters[reconstruct].width + *size * 
filters[sample].width);
+if (width <= 1)
+{
+   width = 1;
+   *subsample_bits = 0;
+}
+return width;
 }
 
 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 01/15] demos/scale: Compute filter size using boundary of xformed ellipse, not rectangle

2016-02-01 Thread spitzak
From: Bill Spitzak 

This is much more accurate and less blurry. In particular the filtering does
not change as the image is rotated.

Signed-off-by: Bill Spitzak 

Reviewed-by: Oded Gabbay 
---
 demos/scale.c | 102 +++---
 1 file changed, 61 insertions(+), 41 deletions(-)

diff --git a/demos/scale.c b/demos/scale.c
index d00307e..0995ad0 100644
--- a/demos/scale.c
+++ b/demos/scale.c
@@ -55,50 +55,70 @@ get_widget (app_t *app, const char *name)
 return widget;
 }
 
-static double
-min4 (double a, double b, double c, double d)
-{
-double m1, m2;
-
-m1 = MIN (a, b);
-m2 = MIN (c, d);
-return MIN (m1, m2);
-}
-
-static double
-max4 (double a, double b, double c, double d)
-{
-double m1, m2;
-
-m1 = MAX (a, b);
-m2 = MAX (c, d);
-return MAX (m1, m2);
-}
-
+/* Figure out the boundary of a diameter=1 circle transformed into an ellipse
+ * by trans. Proof that this is the correct calculation:
+ *
+ * Transform x,y to u,v by this matrix calculation:
+ *
+ *  |u|   |a c| |x|
+ *  |v| = |b d|*|y|
+ *
+ * Horizontal component:
+ *
+ *  u = ax+cy (1)
+ *
+ * For each x,y on a radius-1 circle (p is angle to the point):
+ *
+ *  x^2+y^2 = 1
+ *  x = cos(p)
+ *  y = sin(p)
+ *  dx/dp = -sin(p) = -y
+ *  dy/dp = cos(p) = x
+ *
+ * Figure out derivative of (1) relative to p:
+ *
+ *  du/dp = a(dx/dp) + c(dy/dp)
+ *= -ay + cx
+ *
+ * The min and max u are when du/dp is zero:
+ *
+ *  -ay + cx = 0
+ *  cx = ay
+ *  c = ay/x  (2)
+ *  y = cx/a  (3)
+ *
+ * Substitute (2) into (1) and simplify:
+ *
+ *  u = ax + ay^2/x
+ *= a(x^2+y^2)/x
+ *= a/x (because x^2+y^2 = 1)
+ *  x = a/u (4)
+ *
+ * Substitute (4) into (3) and simplify:
+ *
+ *  y = c(a/u)/a
+ *  y = c/u (5)
+ *
+ * Square (4) and (5) and add:
+ *
+ *  x^2+y^2 = (a^2+c^2)/u^2
+ *
+ * But x^2+y^2 is 1:
+ *
+ *  1 = (a^2+c^2)/u^2
+ *  u^2 = a^2+c^2
+ *  u = hypot(a,c)
+ *
+ * Similarily the max/min of v is at:
+ *
+ *  v = hypot(b,d)
+ *
+ */
 static void
 compute_extents (pixman_f_transform_t *trans, double *sx, double *sy)
 {
-double min_x, max_x, min_y, max_y;
-pixman_f_vector_t v[4] =
-{
-   { { 1, 1, 1 } },
-   { { -1, 1, 1 } },
-   { { -1, -1, 1 } },
-   { { 1, -1, 1 } },
-};
-
-pixman_f_transform_point (trans, [0]);
-pixman_f_transform_point (trans, [1]);
-pixman_f_transform_point (trans, [2]);
-pixman_f_transform_point (trans, [3]);
-
-min_x = min4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
-max_x = max4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
-min_y = min4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
-max_y = max4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
-
-*sx = (max_x - min_x) / 2.0;
-*sy = (max_y - min_y) / 2.0;
+*sx = hypot (trans->m[0][0], trans->m[0][1]) / trans->m[2][2];
+*sy = hypot (trans->m[1][0], trans->m[1][1]) / trans->m[2][2];
 }
 
 typedef struct
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 03/15] demos/scale: Only generate filters when used for separable

2016-02-01 Thread spitzak
From: Bill Spitzak 

This makes the speed of the demo more accurate, as the filter generation
is a visible fraction of the time it takes to do a transform. This also
prevents the output of unused filters in the gnuplot option in the next
patch.

Signed-off-by: Bill Spitzak 
---
 demos/scale.c | 29 +++--
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/demos/scale.c b/demos/scale.c
index 06821e3..881004e 100644
--- a/demos/scale.c
+++ b/demos/scale.c
@@ -258,16 +258,25 @@ rescale (GtkWidget *may_be_null, app_t *app)
 pixman_transform_from_pixman_f_transform (, );
 pixman_image_set_transform (app->original, );
 
-params = pixman_filter_create_separable_convolution (
-_params,
-sx * 65536.0 + 0.5,
-   sy * 65536.0 + 0.5,
-   get_value (app, filters, "reconstruct_x_combo_box"),
-   get_value (app, filters, "reconstruct_y_combo_box"),
-   get_value (app, filters, "sample_x_combo_box"),
-   get_value (app, filters, "sample_y_combo_box"),
-   gtk_adjustment_get_value (app->subsample_adjustment),
-   gtk_adjustment_get_value (app->subsample_adjustment));
+if (get_value (app, filter_types, "filter_combo_box") ==
+   PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
+{
+   params = pixman_filter_create_separable_convolution (
+_params,
+   sx * 65536.0 + 0.5,
+   sy * 65536.0 + 0.5,
+   get_value (app, filters, "reconstruct_x_combo_box"),
+   get_value (app, filters, "reconstruct_y_combo_box"),
+   get_value (app, filters, "sample_x_combo_box"),
+   get_value (app, filters, "sample_y_combo_box"),
+   gtk_adjustment_get_value (app->subsample_adjustment),
+   gtk_adjustment_get_value (app->subsample_adjustment));
+}
+else
+{
+   params = 0;
+   n_params = 0;
+}
 
 pixman_image_set_filter (app->original,
get_value (app, filter_types, "filter_combo_box"),
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 05/15] pixman-filter: Consistency in arg names to integral ()

2016-02-01 Thread spitzak
From: Bill Spitzak 

Rename kernel1/2 to reconstruct/sample to match the other functions.
Rename "scale" to "size" to avoid confusion with the scale being applied
to the image, which is the reciprocol of this value.

v10: Renamed "scale" to "size"

Signed-off-by: Bill Spitzak 

Reviewed-by: Oded Gabbay 
---
 pixman/pixman-filter.c | 48 +++-
 pixman/pixman.h|  6 +++---
 2 files changed, 26 insertions(+), 28 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 11c8548..acfb110 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -147,8 +147,8 @@ static const filter_info_t filters[] =
 { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
 };
 
-/* This function scales @kernel2 by @scale, then
- * aligns @x1 in @kernel1 with @x2 in @kernel2 and
+/* This function scales the @sample filter by @size, then
+ * aligns @x1 in @reconstruct with @x2 in @sample and
  * and integrates the product of the kernels across @width.
  *
  * This function assumes that the intervals are within
@@ -156,8 +156,8 @@ static const filter_info_t filters[] =
  * try to integrate a linear kernel ouside of [-1:1]
  */
 static double
-integral (pixman_kernel_t kernel1, double x1,
- pixman_kernel_t kernel2, double scale, double x2,
+integral (pixman_kernel_t reconstruct, double x1,
+ pixman_kernel_t sample, double size, double x2,
  double width)
 {
 /* If the integration interval crosses zero, break it into
@@ -168,31 +168,31 @@ integral (pixman_kernel_t kernel1, double x1,
 if (x1 < 0 && x1 + width > 0)
 {
return
-   integral (kernel1, x1, kernel2, scale, x2, - x1) +
-   integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
+   integral (reconstruct, x1, sample, size, x2, - x1) +
+   integral (reconstruct, 0, sample, size, x2 - x1, width + x1);
 }
 else if (x2 < 0 && x2 + width > 0)
 {
return
-   integral (kernel1, x1, kernel2, scale, x2, - x2) +
-   integral (kernel1, x1 - x2, kernel2, scale, 0, width + x2);
+   integral (reconstruct, x1, sample, size, x2, - x2) +
+   integral (reconstruct, x1 - x2, sample, size, 0, width + x2);
 }
-else if (kernel1 == PIXMAN_KERNEL_IMPULSE)
+else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
 {
assert (width == 0.0);
-   return filters[kernel2].func (x2 * scale);
+   return filters[sample].func (x2 / size);
 }
-else if (kernel2 == PIXMAN_KERNEL_IMPULSE)
+else if (sample == PIXMAN_KERNEL_IMPULSE)
 {
assert (width == 0.0);
-   return filters[kernel1].func (x1);
+   return filters[reconstruct].func (x1);
 }
 else
 {
/* Integration via Simpson's rule */
 #define N_SEGMENTS 128
 #define SAMPLE(a1, a2) \
-   (filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
+   (filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / size))

double s = 0.0;
double h = width / (double)N_SEGMENTS;
@@ -221,16 +221,14 @@ static pixman_fixed_t *
 create_1d_filter (int *width,
  pixman_kernel_t  reconstruct,
  pixman_kernel_t  sample,
- double   scale,
+ double   size,
  int  n_phases)
 {
 pixman_fixed_t *params, *p;
 double step;
-double size;
 int i;
 
-size = scale * filters[sample].width + filters[reconstruct].width;
-*width = ceil (size);
+*width = ceil (size * filters[sample].width + filters[reconstruct].width);
 
 p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
 if (!params)
@@ -259,8 +257,8 @@ create_1d_filter (int *width,
double pos = x + 0.5 - frac;
double rlow = - filters[reconstruct].width / 2.0;
double rhigh = rlow + filters[reconstruct].width;
-   double slow = pos - scale * filters[sample].width / 2.0;
-   double shigh = slow + scale * filters[sample].width;
+   double slow = pos - size * filters[sample].width / 2.0;
+   double shigh = slow + size * filters[sample].width;
double c = 0.0;
double ilow, ihigh;
 
@@ -270,7 +268,7 @@ create_1d_filter (int *width,
ihigh = MIN (shigh, rhigh);
 
c = integral (reconstruct, ilow,
- sample, 1.0 / scale, ilow - pos,
+ sample, size, ilow - pos,
  ihigh - ilow);
}
 
@@ -339,12 +337,12 @@ gnuplot_filter(int width, int samples, const 
pixman_fixed_t* p)
 #endif
 
 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
- * with the given kernels and scale parameters
+ * with the 

[Pixman] [PATCH v10 10/15] pixman-filter: Gaussian fixes

2016-02-01 Thread spitzak
From: Bill Spitzak 

The SIGMA term drops out on simplification.

Expanded the size slightly (from ~4.25 to 5) to make the cutoff less noticable.
The filter is truncated at a value of .001 instead of .006, this new
value is less than 1/2 of 1/255, rather than greater than it.

Signed-off-by: Bill Spitzak 

Acked-by: Oded Gabbay 
---
 pixman/pixman-filter.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index b6f8eb4..10fa398 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -63,10 +63,7 @@ linear_kernel (double x)
 static double
 gaussian_kernel (double x)
 {
-#define SQRT2 (1.4142135623730950488016887242096980785696718753769480)
-#define SIGMA (SQRT2 / 2.0)
-
-return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI));
+return exp (- x * x) / sqrt (M_PI);
 }
 
 static double
@@ -139,7 +136,7 @@ static const filter_info_t filters[] =
 { PIXMAN_KERNEL_BOX,   box_kernel,   1.0 },
 { PIXMAN_KERNEL_LINEAR,linear_kernel,2.0 },
 { PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
-{ PIXMAN_KERNEL_GAUSSIAN,  gaussian_kernel,  6 * SIGMA },
+{ PIXMAN_KERNEL_GAUSSIAN,  gaussian_kernel,  5.0 },
 { PIXMAN_KERNEL_LANCZOS2,  lanczos2_kernel,  4.0 },
 { PIXMAN_KERNEL_LANCZOS3,  lanczos3_kernel,  6.0 },
 { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 02/15] demos/scale: Added pulldown to choose PIXMAN_FILTER_* value

2016-02-01 Thread spitzak
From: Bill Spitzak 

This allows testing of GOOD/BEST and to do comparisons between
the basic filters and PIXMAN_FILTER_SEPARABLE_CONVOLUTION settings.

Signed-off-by: Bill Spitzak 

Reviewed-by: Oded Gabbay 
---
 demos/scale.c  | 14 +-
 demos/scale.ui | 40 ++--
 2 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/demos/scale.c b/demos/scale.c
index 0995ad0..06821e3 100644
--- a/demos/scale.c
+++ b/demos/scale.c
@@ -127,6 +127,15 @@ typedef struct
 intvalue;
 } named_int_t;
 
+static const named_int_t filter_types[] =
+{
+{ "Separable", PIXMAN_FILTER_SEPARABLE_CONVOLUTION },
+{ "Nearest",   PIXMAN_FILTER_NEAREST },
+{ "Bilinear",  PIXMAN_FILTER_BILINEAR },
+{ "Good",  PIXMAN_FILTER_GOOD },
+{ "Best",  PIXMAN_FILTER_BEST },
+};
+
 static const named_int_t filters[] =
 {
 { "Box",   PIXMAN_KERNEL_BOX },
@@ -260,7 +269,9 @@ rescale (GtkWidget *may_be_null, app_t *app)
gtk_adjustment_get_value (app->subsample_adjustment),
gtk_adjustment_get_value (app->subsample_adjustment));
 
-pixman_image_set_filter (app->original, 
PIXMAN_FILTER_SEPARABLE_CONVOLUTION, params, n_params);
+pixman_image_set_filter (app->original,
+   get_value (app, filter_types, "filter_combo_box"),
+   params, n_params);
 
 pixman_image_set_repeat (
 app->original, get_value (app, repeats, "repeat_combo_box"));
@@ -402,6 +413,7 @@ app_new (pixman_image_t *original)
 widget = get_widget (app, "drawing_area");
 g_signal_connect (widget, "expose_event", G_CALLBACK (on_expose), app);
 
+set_up_combo_box (app, "filter_combo_box", G_N_ELEMENTS (filter_types), 
filter_types);
 set_up_filter_box (app, "reconstruct_x_combo_box");
 set_up_filter_box (app, "reconstruct_y_combo_box");
 set_up_filter_box (app, "sample_x_combo_box");
diff --git a/demos/scale.ui b/demos/scale.ui
index ee985dd..b62cbfb 100644
--- a/demos/scale.ui
+++ b/demos/scale.ui
@@ -191,12 +191,23 @@
 8
 6
 
+  
+True
+1
+bFilter:/b
+True
+  
+
+
   
 True
 1
 bReconstruct X:/b
 True
   
+  
+1
+  
 
 
   
@@ -206,7 +217,7 @@
 True
   
   
-1
+2
   
 
 
@@ -217,7 +228,7 @@
 True
   
   
-2
+3
   
 
 
@@ -228,7 +239,7 @@
 True
   
   
-3
+4
   
 
 
@@ -239,7 +250,7 @@
 True
   
   
-4
+5
   
 
 
@@ -250,7 +261,15 @@
 True
   
   
-5
+6
+  
+
+
+  
+True
+  
+  
+1
   
 
 
@@ -259,6 +278,7 @@
   
   
 1
+1
   
 
 
@@ -267,7 +287,7 @@
   
   
 1
-1
+2
   
 
 
@@ -276,7 +296,7 @@
   
   
 1
-2
+3
   
 
 
@@ -285,7 +305,7 @@
   
   
 1
-3
+4
   
 
 
@@ -294,7 +314,7 @@
   
   

[Pixman] [PATCH v10] Implement PIXMAN_FILTER_GOOD/BEST

2016-02-01 Thread spitzak
Changes from previous version:
- Some refactor to reduce size of each patch
- Fixed rebase error that made some patches not compile
- Renamed "scale" to "size" to avoid confusion with the transform scale

Compatibiliy notes:

For the default filter of GOOD this produces the same BILINEAR result for any 
scale 
greater than 3/4, and also for a scale of 1/2 if there is no rotation or 
translation.
For BEST the output is changed for all transforms other than the identity. For
other filter settings the result is unchanged.

These changes match those done to Cairo about 1.5 years ago, with the same 
amount
of incompatability. Making these changes will allow Cairo to use pixman directly
rather than generate it's own filters.


___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 09/15] pixman-filter: don't range-check in filter functions

2016-02-01 Thread spitzak
From: Bill Spitzak 

The integral will not be called outside the width so there is no need
to check against these.

v9: merged commits for cubic and impulse into same one

Signed-off-by: Bill Spitzak 
---
 pixman/pixman-filter.c | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index bd4e174..b6f8eb4 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -45,7 +45,7 @@ typedef struct
 static double
 impulse_kernel (double x)
 {
-return (x == 0.0)? 1.0 : 0.0;
+return 1;
 }
 
 static double
@@ -109,18 +109,16 @@ general_cubic (double x, double B, double C)
 
 if (ax < 1)
 {
-   return ((12 - 9 * B - 6 * C) * ax * ax * ax +
-   (-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
-}
-else if (ax >= 1 && ax < 2)
-{
-   return ((-B - 6 * C) * ax * ax * ax +
-   (6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
-   ax + (8 * B + 24 * C)) / 6;
+   return (((12 - 9 * B - 6 * C) * ax +
+(-18 + 12 * B + 6 * C)) * ax * ax +
+   (6 - 2 * B)) / 6;
 }
 else
 {
-   return 0;
+   return -B - 6 * C) * ax +
+(6 * B + 30 * C)) * ax +
+   (-12 * B - 48 * C)) * ax +
+   (8 * B + 24 * C)) / 6;
 }
 }
 
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH v10 07/15] pixman-filter: Correct Simpsons integration

2016-02-01 Thread spitzak
From: Bill Spitzak 

Simpsons uses cubic curve fitting, with 3 samples defining each cubic. This
makes the weights of the samples be in a pattern of 1,4,2,4,2...4,1, and then
dividing the result by 3.

The previous code was using weights of 1,2,6,6...6,2,1. Since it divided by
3 this produced about 2x the desired value (the normalization fixed this).
Also this is effectively a linear interpolation, not Simpsons integration.

With this fix the integration is accurate enough that the number of samples
could be reduced a lot. Multiples of 12 seem to work best.

v7: Merged with patch to reduce from 128 samples to 16
v9: Changed samples from 16 to 12
v10: Fixed rebase error that made it not compile

Signed-off-by: Bill Spitzak 
---
 pixman/pixman-filter.c | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 6c077b6..13ee024 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -189,13 +189,19 @@ integral (pixman_kernel_t reconstruct, double x1,
 }
 else
 {
-   /* Integration via Simpson's rule */
-#define N_SEGMENTS 128
+   /* Integration via Simpson's rule
+* See http://www.intmath.com/integration/6-simpsons-rule.php
+* 12 segments (6 cubic approximations) seems to produce best
+* result for lanczos3.linear, which was the combination that
+* showed the most errors.  This makes sense as the lanczos3
+* filter is 6 wide.
+*/
+#define N_SEGMENTS 12
 #define SAMPLE(a1, a2) \
(filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / size))
-   
+
double s = 0.0;
-   double h = width / (double)N_SEGMENTS;
+   double h = width / N_SEGMENTS;
int i;
 
s = SAMPLE (x1, x2);
@@ -204,11 +210,14 @@ integral (pixman_kernel_t reconstruct, double x1,
{
double a1 = x1 + h * i;
double a2 = x2 + h * i;
+   s += 4 * SAMPLE(a1, a2);
+   }
 
-   s += 2 * SAMPLE (a1, a2);
-
-   if (i >= 2 && i < N_SEGMENTS - 1)
-   s += 4 * SAMPLE (a1, a2);
+   for (i = 2; i < N_SEGMENTS; i += 2)
+   {
+   double a1 = x1 + h * i;
+   double a2 = x2 + h * i;
+   s += 2 * SAMPLE(a1, a2);
}
 
s += SAMPLE (x1 + width, x2 + width);
-- 
1.9.1

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


Re: [Pixman] [PATCH v9 05/15] pixman-filter: reduce amount of malloc/free/memcpy to generate filter

2016-02-01 Thread Oded Gabbay
On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> From: Bill Spitzak 
>
> Rearranged so that the entire block of memory for the filter pair
> is allocated first, and then filled in. Previous version allocated
> and freed two temporary buffers for each filter and did an extra
> memcpy.
>
> v8: small refactor to remove the filter_width function
>
> v1: first version

No need for  as the commit message represents that.


>
> Signed-off-by: Bill Spitzak 
> ---
>  pixman/pixman-filter.c | 51 
> +-
>  1 file changed, 17 insertions(+), 34 deletions(-)
>
> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
> index aaa7de9..55073c4 100644
> --- a/pixman/pixman-filter.c
> +++ b/pixman/pixman-filter.c
> @@ -217,25 +217,17 @@ integral (pixman_kernel_t reconstruct, double x1,
>  }
>  }
>
> -static pixman_fixed_t *
> -create_1d_filter (int *width,
> +static void
> +create_1d_filter (int  width,
>   pixman_kernel_t  reconstruct,
>   pixman_kernel_t  sample,
>   double   scale,
> - int  n_phases)
> + int  n_phases,
> + pixman_fixed_t *p)
>  {
> -pixman_fixed_t *params, *p;
>  double step;
> -double size;
>  int i;
>
> -size = scale * filters[sample].width + filters[reconstruct].width;
> -*width = ceil (size);
> -
> -p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
> -if (!params)
> -return NULL;
> -
>  step = 1.0 / n_phases;
>
>  for (i = 0; i < n_phases; ++i)
> @@ -250,8 +242,8 @@ create_1d_filter (int *width,
>  * and sample positions.
>  */
>
> -   x1 = ceil (frac - *width / 2.0 - 0.5);
> -x2 = x1 + *width;
> +   x1 = ceil (frac - width / 2.0 - 0.5);
> +x2 = x1 + width;
>
> total = 0;
>  for (x = x1; x < x2; ++x)
> @@ -279,7 +271,7 @@ create_1d_filter (int *width,
>  }
>
> /* Normalize */
> -   p -= *width;
> +   p -= width;
>  total = 1 / total;
>  new_total = 0;
> for (x = x1; x < x2; ++x)
> @@ -291,10 +283,8 @@ create_1d_filter (int *width,
> }
>
> if (new_total != pixman_fixed_1)
> -   *(p - *width / 2) += (pixman_fixed_1 - new_total);
> +   *(p - width / 2) += (pixman_fixed_1 - new_total);
>  }
> -
> -return params;
>  }
>
>  #if PIXMAN_GNUPLOT
> @@ -354,38 +344,31 @@ pixman_filter_create_separable_convolution (int 
> *n_values,
>  {
>  double sx = fabs (pixman_fixed_to_double (scale_x));
>  double sy = fabs (pixman_fixed_to_double (scale_y));
> -pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL;
> +pixman_fixed_t *params;
>  int subsample_x, subsample_y;
>  int width, height;
>
>  subsample_x = (1 << subsample_bits_x);
>  subsample_y = (1 << subsample_bits_y);
>
> -horz = create_1d_filter (, reconstruct_x, sample_x, sx, 
> subsample_x);
> -vert = create_1d_filter (, reconstruct_y, sample_y, sy, 
> subsample_y);
> +width = ceil (filters[reconstruct_x].width + sx * 
> filters[sample_x].width);
> +height = ceil (filters[reconstruct_y].width + sy * 
> filters[sample_y].width);
>
> -if (!horz || !vert)
> -goto out;
> -
>  *n_values = 4 + width * subsample_x + height * subsample_y;
> -
> +
>  params = malloc (*n_values * sizeof (pixman_fixed_t));
>  if (!params)
> -goto out;
> +return NULL;
>
>  params[0] = pixman_int_to_fixed (width);
>  params[1] = pixman_int_to_fixed (height);
>  params[2] = pixman_int_to_fixed (subsample_bits_x);
>  params[3] = pixman_int_to_fixed (subsample_bits_y);
>
> -memcpy (params + 4, horz,
> -   width * subsample_x * sizeof (pixman_fixed_t));
> -memcpy (params + 4 + width * subsample_x, vert,
> -   height * subsample_y * sizeof (pixman_fixed_t));
> -
> -out:
> -free (horz);
> -free (vert);
> +create_1d_filter (width, reconstruct_x, sample_x, sx, subsample_x,
> + params + 4);
> +create_1d_filter (height, reconstruct_y, sample_y, sy, subsample_y,
> + params + 4 + width * subsample_x);
>
>  #if PIXMAN_GNUPLOT
>  gnuplot_filter(width, subsample_x, params+4);
> --
> 1.9.1
>
> ___
> Pixman mailing list
> Pixman@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pixman

With the v1: removed, consider this patch:

Reviewed-by: Oded Gabbay 
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


Re: [Pixman] [PATCH v9 06/15] pixman-filter: Correct Simpsons integration

2016-02-01 Thread Oded Gabbay
On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> From: Bill Spitzak 
>
> Simpsons uses cubic curve fitting, with 3 samples defining each cubic. This
> makes the weights of the samples be in a pattern of 1,4,2,4,2...4,1, and then
> dividing the result by 3.
>
> The previous code was using weights of 1,2,6,6...6,2,1. Since it divided by
> 3 this produced about 2x the desired value (the normalization fixed this).
> Also this is effectively a linear interpolation, not Simpsons integration.
>
> With this fix the integration is accurate enough that the number of samples
> could be reduced a lot. Multiples of 12 seem to work best.
>
> v9: Changed samples from 16 to 12
> v7: Merged with patch to reduce from 128 samples to 16
>
> Signed-off-by: Bill Spitzak 
> ---
>  pixman/pixman-filter.c | 29 +++--
>  1 file changed, 19 insertions(+), 10 deletions(-)
>
> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
> index 55073c4..718649a 100644
> --- a/pixman/pixman-filter.c
> +++ b/pixman/pixman-filter.c
> @@ -189,13 +189,19 @@ integral (pixman_kernel_t reconstruct, double x1,
>  }
>  else
>  {
> -   /* Integration via Simpson's rule */
> -#define N_SEGMENTS 128
> -#define SAMPLE(a1, a2) \
> -   (filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / 
> scale))
> -
> +   /* Integration via Simpson's rule
> +* See http://www.intmath.com/integration/6-simpsons-rule.php
> +* 12 segments (6 cubic approximations) seems to produce best
> +* result for lanczos3.linear, which was the combination that
> +* showed the most errors.  This makes sense as the lanczos3
> +* filter is 6 wide.
> +*/
> +#define N_SEGMENTS 12
> +#define SAMPLE(a)  \
> +   (filters[reconstruct].func ((a)) * filters[sample].func (((a) - pos) 
> / scale))
> +
You changed the SAMPLE macro to get 1 parameter, but in all the calls
you send 2 parameters, which make the compilation fail.

Please fix this and resend the patch.

Oded

> double s = 0.0;
> -   double h = width / (double)N_SEGMENTS;
> +   double h = width / N_SEGMENTS;
> int i;
>
> s = SAMPLE (x1, x2);
> @@ -204,11 +210,14 @@ integral (pixman_kernel_t reconstruct, double x1,
> {
> double a1 = x1 + h * i;
> double a2 = x2 + h * i;
> +   s += 4 * SAMPLE(a1, a2);
> +   }
>
> -   s += 2 * SAMPLE (a1, a2);
> -
> -   if (i >= 2 && i < N_SEGMENTS - 1)
> -   s += 4 * SAMPLE (a1, a2);
> +   for (i = 2; i < N_SEGMENTS; i += 2)
> +   {
> +   double a1 = x1 + h * i;
> +   double a2 = x2 + h * i;
> +   s += 2 * SAMPLE(a1, a2);
> }
>
> s += SAMPLE (x1 + width, x2 + width);
> --
> 1.9.1
>
> ___
> Pixman mailing list
> Pixman@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pixman
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


Re: [Pixman] [PATCH v9 04/15] pixman-filter: Consistency in arg names to integral ()

2016-02-01 Thread Oded Gabbay
On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> From: Bill Spitzak 
>
> Rename kernel1/2 to reconstruct/sample and use 1/scale as the
> scale argument, thus matching the names in other functions.
>
> Signed-off-by: Bill Spitzak 
> ---
>  pixman/pixman-filter.c | 28 ++--
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
> index fe0d261..aaa7de9 100644
> --- a/pixman/pixman-filter.c
> +++ b/pixman/pixman-filter.c
> @@ -147,8 +147,8 @@ static const filter_info_t filters[] =
>  { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
>  };
>
> -/* This function scales @kernel2 by @scale, then
> - * aligns @x1 in @kernel1 with @x2 in @kernel2 and
> +/* This function scales @sample by @scale, then
> + * aligns @x1 in @reconstruct with @x2 in @sample and
>   * and integrates the product of the kernels across @width.
>   *
>   * This function assumes that the intervals are within
> @@ -156,8 +156,8 @@ static const filter_info_t filters[] =
>   * try to integrate a linear kernel ouside of [-1:1]
>   */
>  static double
> -integral (pixman_kernel_t kernel1, double x1,
> - pixman_kernel_t kernel2, double scale, double x2,
> +integral (pixman_kernel_t reconstruct, double x1,
> + pixman_kernel_t sample, double scale, double x2,
>   double width)
>  {
>  /* If the integration interval crosses zero, break it into
> @@ -168,31 +168,31 @@ integral (pixman_kernel_t kernel1, double x1,
>  if (x1 < 0 && x1 + width > 0)
>  {
> return
> -   integral (kernel1, x1, kernel2, scale, x2, - x1) +
> -   integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
> +   integral (reconstruct, x1, sample, scale, x2, - x1) +
> +   integral (reconstruct, 0, sample, scale, x2 - x1, width + x1);
>  }
>  else if (x2 < 0 && x2 + width > 0)
>  {
> return
> -   integral (kernel1, x1, kernel2, scale, x2, - x2) +
> -   integral (kernel1, x1 - x2, kernel2, scale, 0, width + x2);
> +   integral (reconstruct, x1, sample, scale, x2, - x2) +
> +   integral (reconstruct, x1 - x2, sample, scale, 0, width + x2);
>  }
> -else if (kernel1 == PIXMAN_KERNEL_IMPULSE)
> +else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
>  {
> assert (width == 0.0);
> -   return filters[kernel2].func (x2 * scale);
> +   return filters[sample].func (x2 / scale);
>  }
> -else if (kernel2 == PIXMAN_KERNEL_IMPULSE)
> +else if (sample == PIXMAN_KERNEL_IMPULSE)
>  {
> assert (width == 0.0);
> -   return filters[kernel1].func (x1);
> +   return filters[reconstruct].func (x1);
>  }
>  else
>  {
> /* Integration via Simpson's rule */
>  #define N_SEGMENTS 128
>  #define SAMPLE(a1, a2) \
> -   (filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
> +   (filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / 
> scale))
>
> double s = 0.0;
> double h = width / (double)N_SEGMENTS;
> @@ -270,7 +270,7 @@ create_1d_filter (int *width,
> ihigh = MIN (shigh, rhigh);
>
> c = integral (reconstruct, ilow,
> - sample, 1.0 / scale, ilow - pos,
> + sample, scale, ilow - pos,
>   ihigh - ilow);
> }
>
> --
> 1.9.1
>
> ___
> Pixman mailing list
> Pixman@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pixman

Reviewed-by: Oded Gabbay 
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


Re: [Pixman] [PATCH v9 14/15] pixman-filter: Added big comment to filter

2016-02-01 Thread Oded Gabbay
On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> From: Bill Spitzak 
>
The title of the patch confused me a bit.
Maybe rewrite it as:
pixman-filter: Add description to pixman_filter_create_separable_convolution()

> v9: Described arguments and more filter combinations, fixed some errors.
> v8: first version

No need of v8:first version
>
> Signed-off-by: Bill Spitzak 
> ---
>  pixman/pixman-filter.c | 46 +-
>  1 file changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
> index 639d5e6..74819fe 100644
> --- a/pixman/pixman-filter.c
> +++ b/pixman/pixman-filter.c
> @@ -378,7 +378,51 @@ filter_width(pixman_kernel_t reconstruct, 
> pixman_kernel_t sample,
>  }
>
>  /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
> - * with the given kernels and scale parameters
> + *
> + * Returns pointer to the block of numbers
> + *
> + * n_values: pointer to integer to store size of the block
> + *
> + * scale_x/y: amount to stretch the sample filter. Note that scale
> + * is the inverse of how the image is being scaled, if the image is
> + * being made smaller, the filter gets larger.
> + *
> + * reconstruct_x/y: filter that is not scaled.
> + *
> + * sample_x/y: filter that is scaled. Resoult is convolved with reconstruct 
> filter.
> + *
> + * subsample_bits_x/y: If positive there are 2^n subpixel positions computed 
> for
> + * the filter. If negative then -n (rounded up to the next power of 2) 
> positions
> + * are calculated when scale==1, but fewer are computed for larger scales and
> + * more for smaller scales.
> + *
> + * Some interesting reconstruct.sample combinations:
> + *
> + *  IMPULSE.x - Uses the sample function only. This is what many other 
> pieces of
> + *  software do. Does not work for scale < 1.0.
> + *
> + *  BOX.x - For scale < 1.0 this produces square pixels. For scale > 1.0 this
> + *  approaches IMPULSE.x as scale gets larger.
> + *
> + *  x.IMPULSE - Uses the reconstruct function only, scale is ignored.
> + *
> + *  BOX.BOX, LINEAR.IMPULSE, IMPULSE.LINEAR - at scale==1 these all match and
> + *  also produce same result as bilinear filtering.
> + *
> + *  BOX.BOX - Produces a trapazoid-shape. Narrowest possible filter with 
> antialiasing.
> + *Matches a lot of other software, some call it "box", others 
> call it "linear"
> + *
> + *  BOX.LINEAR - At scale==1 this is what some software calls a Quadratic 
> filter
> + *
> + *  IMPULSE.LINEAR - Some software calls this "linear" or "triangle". Not a 
> good filter.
> + *
> + *  LINEAR.LINEAR - non-negative cubic. What some software calls "cubic 
> interpolation".
> + *
> + *  IMPULSE.LANCZOS2 - Close to what a lot of other software calls "cubic 
> interpolation"
> + *
> + *  IMPULSE.CUBIC - Called "Mitchell" in other software
> + *
> + *  IMPULSE.GAUSSIAN - Best removal of aliasing but usually considered too 
> blurry
>   */
>  PIXMAN_EXPORT pixman_fixed_t *
>  pixman_filter_create_separable_convolution (int *n_values,
> --
> 1.9.1
>
> ___
> Pixman mailing list
> Pixman@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pixman

With those changes, this patch is:

Reviewed-by: Oded Gabbay 
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


Re: [Pixman] [PATCH v9 07/15] pixman-filter: Corrections to the integral() function

2016-02-01 Thread Oded Gabbay
On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> From: Bill Spitzak 
>
> The IMPULSE special-cases did not sample the center of the of the region.
> This caused it to sample the filters outside their range, and produce
> assymetric filters and other errors. Fixing this required changing the
> arguments to integral() so the correct point could be determined.
>
> I fixed the nice filter and the integration to directly produce normalized
> values. Re-normalization is still needed for impulse.box or impulse.triangle
> so I did not remove it.
>
> Distribute fixed error over all filter samples, to remove a high-frequency
> bit of noise in the center of some filters (lancoz at large scale value).
>
> box.box, which I expect will be very common as it is the proposed "good" 
> filter,
> was made a lot faster and more accurate. This is easy as the caller already
> intersected the two boxes, so the width is the integral.
>
> v9: Restored the recursion splitting at zero for linear filter
> v7: This is a merge of 4 patches and lots of new code cleanup and fixes
>  determined by examining the gnuplot output
>
> Signed-off-by: Bill Spitzak 
> ---
>  pixman/pixman-filter.c | 135 
> +
>  1 file changed, 68 insertions(+), 67 deletions(-)
>
> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
> index 718649a..768e1f6 100644
> --- a/pixman/pixman-filter.c
> +++ b/pixman/pixman-filter.c
> @@ -79,7 +79,7 @@ sinc (double x)
>  }
>
>  static double
> -lanczos (double x, int n)
> +lanczos (double x, double n)
>  {
>  return sinc (x) * sinc (x * (1.0 / n));
>  }
> @@ -99,7 +99,7 @@ lanczos3_kernel (double x)
>  static double
>  nice_kernel (double x)
>  {
> -return lanczos3_kernel (x * 0.75);
> +return lanczos3_kernel (x * 0.75) * 0.75;
>  }
>
>  static double
> @@ -147,45 +147,51 @@ static const filter_info_t filters[] =
>  { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
>  };
>
> -/* This function scales @sample by @scale, then
> - * aligns @x1 in @reconstruct with @x2 in @sample and
> - * and integrates the product of the kernels across @width.
> +/* This function scales @sample by @scale, shifts it by @pos,
> + * and then integrates the product of the kernels across low..high
>   *
>   * This function assumes that the intervals are within
>   * the kernels in question. E.g., the caller must not
>   * try to integrate a linear kernel ouside of [-1:1]
>   */
>  static double
> -integral (pixman_kernel_t reconstruct, double x1,
> - pixman_kernel_t sample, double scale, double x2,
> - double width)
> +integral (pixman_kernel_t reconstruct,
> + pixman_kernel_t sample, double scale, double pos,
> + double low, double high)
>  {
> +if (high < low)
> +{
> +   return 0.0;
> +}
> +else if (sample == PIXMAN_KERNEL_IMPULSE)
> +{
> +   return filters[reconstruct].func (-pos);
> +}
> +else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
> +{
> +   return filters[sample].func (-pos / scale) / scale;
> +}
> +else if (reconstruct == PIXMAN_KERNEL_BOX && sample == PIXMAN_KERNEL_BOX)
> +{
> +   assert (high <= low + 1.0);
> +   return (high - low) / scale;
> +}
>  /* If the integration interval crosses zero, break it into
>   * two separate integrals. This ensures that filters such
>   * as LINEAR that are not differentiable at 0 will still
>   * integrate properly.
>   */
> -if (x1 < 0 && x1 + width > 0)
> +else if (reconstruct == PIXMAN_KERNEL_LINEAR && low < 0 && high > 0)
>  {
> return
> -   integral (reconstruct, x1, sample, scale, x2, - x1) +
> -   integral (reconstruct, 0, sample, scale, x2 - x1, width + x1);
> +   integral (reconstruct, sample, scale, pos, low, 0) +
> +   integral (reconstruct, sample, scale, pos, 0, high);
>  }
> -else if (x2 < 0 && x2 + width > 0)
> +else if (sample == PIXMAN_KERNEL_LINEAR && low < pos && high > pos)
>  {
> return
> -   integral (reconstruct, x1, sample, scale, x2, - x2) +
> -   integral (reconstruct, x1 - x2, sample, scale, 0, width + x2);
> -}
> -else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
> -{
> -   assert (width == 0.0);
> -   return filters[sample].func (x2 / scale);
> -}
> -else if (sample == PIXMAN_KERNEL_IMPULSE)
> -{
> -   assert (width == 0.0);
> -   return filters[reconstruct].func (x1);
> +   integral (reconstruct, sample, scale, pos, low, pos) +
> +   integral (reconstruct, sample, scale, pos, pos, high);
>  }
>  else
>  {
> @@ -201,28 +207,26 @@ integral (pixman_kernel_t reconstruct, double x1,
> (filters[reconstruct].func ((a)) * filters[sample].func (((a) - pos) 
> / scale))
>
> double s = 0.0;
> -   double h = width / N_SEGMENTS;
> +   double h = (high 

Re: [Pixman] [PATCH v9 10/15] pixman-filter: Gaussian fixes

2016-02-01 Thread Oded Gabbay
On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> From: Bill Spitzak 
>
> The SIGMA term drops out on simplification.
>
> Expanded the size slightly (from ~4.25 to 5) to make the cutoff less 
> noticable.
> The filter is truncated at a value of .001 instead of .006, this new
> value is less than 1/2 of 1/255, rather than greater than it.
>
> v1: initial version

No need for v1:
>
> Signed-off-by: Bill Spitzak 
> ---
>  pixman/pixman-filter.c | 7 ++-
>  1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
> index 3062448..20d0fcb 100644
> --- a/pixman/pixman-filter.c
> +++ b/pixman/pixman-filter.c
> @@ -63,10 +63,7 @@ linear_kernel (double x)
>  static double
>  gaussian_kernel (double x)
>  {
> -#define SQRT2 (1.4142135623730950488016887242096980785696718753769480)
> -#define SIGMA (SQRT2 / 2.0)
> -
> -return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI));
> +return exp (- x * x) / sqrt (M_PI);
>  }
>
>  static double
> @@ -139,7 +136,7 @@ static const filter_info_t filters[] =
>  { PIXMAN_KERNEL_BOX,   box_kernel,   1.0 },
>  { PIXMAN_KERNEL_LINEAR,linear_kernel,2.0 },
>  { PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
> -{ PIXMAN_KERNEL_GAUSSIAN,  gaussian_kernel,  6 * SIGMA },
> +{ PIXMAN_KERNEL_GAUSSIAN,  gaussian_kernel,  5.0 },
>  { PIXMAN_KERNEL_LANCZOS2,  lanczos2_kernel,  4.0 },
>  { PIXMAN_KERNEL_LANCZOS3,  lanczos3_kernel,  6.0 },
>  { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
> --
> 1.9.1
>
> ___
> Pixman mailing list
> Pixman@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pixman

With v1: removed, this patch is

Acked-by: Oded Gabbay 
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


Re: [Pixman] [PATCH v9 03/15] pixman-image: Added enable-gnuplot config to view filters in gnuplot

2016-02-01 Thread Bill Spitzak
On Mon, Feb 1, 2016 at 6:11 AM, Oded Gabbay  wrote:

> On Mon, Feb 1, 2016 at 4:10 PM, Oded Gabbay  wrote:
> > On Fri, Jan 22, 2016 at 11:42 AM,   wrote:
> >> From: Bill Spitzak 
> >>
> >> If enable-gnuplot is configured, then you can pipe the output of a
> pixman-using program
> >> to gnuplot and get a continuously-updated plot of the horizontal
> filter. This
> >> works well with demos/scale to test the filter generation.
> >>
> >> The plot is all the different subposition filters shuffled together.
> This is
> >> misleading in a few cases:
> >>
> >>   IMPULSE.BOX - goes up and down as the subfilters have different
> numbers of non-zero samples
> >>   IMPULSE.TRIANGLE - somewhat crooked for the same reason
> >>   1-wide filters - looks triangular, but a 1-wide box would be more
> accurate
> >>
> >> v8: Use config option
> >> Moved code to the filter generator
> >> Modified scale demo to not call filter generator a second time.
> >>
> >> v7: First time this ability was included
>
> One more thing. The vX comments should be ordered from first to last
> (old to new), so:
> v7: ...
> v8: ...
>

Okay thank you, I will fix all of them.
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


Re: [Pixman] [PATCH v9 03/15] pixman-image: Added enable-gnuplot config to view filters in gnuplot

2016-02-01 Thread Bill Spitzak
On Mon, Feb 1, 2016 at 6:10 AM, Oded Gabbay  wrote:

>
> > -params = pixman_filter_create_separable_convolution (
> > -_params,
> > -sx * 65536.0 + 0.5,
> > -   sy * 65536.0 + 0.5,
> > -   get_value (app, filters, "reconstruct_x_combo_box"),
> > -   get_value (app, filters, "reconstruct_y_combo_box"),
> > -   get_value (app, filters, "sample_x_combo_box"),
> > -   get_value (app, filters, "sample_y_combo_box"),
> > -   gtk_adjustment_get_value (app->subsample_adjustment),
> > -   gtk_adjustment_get_value (app->subsample_adjustment));
> > +if (get_value (app, filter_types, "filter_combo_box") ==
> > +   PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
> > +{
> > +   params = pixman_filter_create_separable_convolution (
> > +_params,
> > +   sx * 65536.0 + 0.5,
> > +   sy * 65536.0 + 0.5,
> > +   get_value (app, filters, "reconstruct_x_combo_box"),
> > +   get_value (app, filters, "reconstruct_y_combo_box"),
> > +   get_value (app, filters, "sample_x_combo_box"),
> > +   get_value (app, filters, "sample_y_combo_box"),
> > +   gtk_adjustment_get_value (app->subsample_adjustment),
> > +   gtk_adjustment_get_value (app->subsample_adjustment));
> > +}
> > +else
> > +{
> > +   params = 0;
> > +   n_params = 0;
> > +}
>
> Wait, what the above code has to do with this patch ?
> It wasn't in the previous version (v7) and I don't see how it is
> related to the gnuplot.
> This seems like a fix to the demo code.
> If what I said is correct, please split it into a different patch.
>

I had to patch it so it did not run the filter generator twice when set to
good/best, otherwise the plot flashed back and forth annoyingly.

But this also makes the demo a bit faster showing accurately the speed at
which transforms are done, so I think putting this in an earlier patch is a
good idea.

> +#if PIXMAN_GNUPLOT
>
> To keep consistency with other defines checks, please use #ifdef when
> checking just one define
>

OK


> > @@ -346,5 +387,9 @@ out:
> >  free (horz);
> >  free (vert);
> >
> > +#if PIXMAN_GNUPLOT
>
> To keep consistency with other defines checks, please use #ifdef when
> checking just one define
>
> > +gnuplot_filter(width, subsample_x, params+4);
> > +#endif
> > +
>
> What's the point in printing the filter after the out: label ?
> You can get here in cases where there were errors in the function.
> Why not put the call to gnuplot_filter() just before the out: label ?
>

You are correct it should only do this on success. My mistake.
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


Re: [Pixman] [PATCH v9 01/15] demos/scale: Compute filter size using boundary of xformed ellipse, not rectangle

2016-02-01 Thread Bill Spitzak
Okay, thanks for the info. Will try to fix them all.

On Mon, Feb 1, 2016 at 5:51 AM, Oded Gabbay  wrote:

> On Fri, Jan 22, 2016 at 11:41 AM,  wrote:
> >
> > From: Bill Spitzak 
> >
> > This is much more accurate and less blurry. In particular the filtering
> does
> > not change as the image is rotated.
> >
> > Signed-off-by: Bill Spitzak 
> > ---
> >  demos/scale.c | 102
> +++---
> >  1 file changed, 61 insertions(+), 41 deletions(-)
> >
> > diff --git a/demos/scale.c b/demos/scale.c
> > index d00307e..0995ad0 100644
> > --- a/demos/scale.c
> > +++ b/demos/scale.c
> > @@ -55,50 +55,70 @@ get_widget (app_t *app, const char *name)
> >  return widget;
> >  }
> >
> > -static double
> > -min4 (double a, double b, double c, double d)
> > -{
> > -double m1, m2;
> > -
> > -m1 = MIN (a, b);
> > -m2 = MIN (c, d);
> > -return MIN (m1, m2);
> > -}
> > -
> > -static double
> > -max4 (double a, double b, double c, double d)
> > -{
> > -double m1, m2;
> > -
> > -m1 = MAX (a, b);
> > -m2 = MAX (c, d);
> > -return MAX (m1, m2);
> > -}
> > -
> > +/* Figure out the boundary of a diameter=1 circle transformed into an
> ellipse
> > + * by trans. Proof that this is the correct calculation:
> > + *
> > + * Transform x,y to u,v by this matrix calculation:
> > + *
> > + *  |u|   |a c| |x|
> > + *  |v| = |b d|*|y|
> > + *
> > + * Horizontal component:
> > + *
> > + *  u = ax+cy (1)
> > + *
> > + * For each x,y on a radius-1 circle (p is angle to the point):
> > + *
> > + *  x^2+y^2 = 1
> > + *  x = cos(p)
> > + *  y = sin(p)
> > + *  dx/dp = -sin(p) = -y
> > + *  dy/dp = cos(p) = x
> > + *
> > + * Figure out derivative of (1) relative to p:
> > + *
> > + *  du/dp = a(dx/dp) + c(dy/dp)
> > + *= -ay + cx
> > + *
> > + * The min and max u are when du/dp is zero:
> > + *
> > + *  -ay + cx = 0
> > + *  cx = ay
> > + *  c = ay/x  (2)
> > + *  y = cx/a  (3)
> > + *
> > + * Substitute (2) into (1) and simplify:
> > + *
> > + *  u = ax + ay^2/x
> > + *= a(x^2+y^2)/x
> > + *= a/x (because x^2+y^2 = 1)
> > + *  x = a/u (4)
> > + *
> > + * Substitute (4) into (3) and simplify:
> > + *
> > + *  y = c(a/u)/a
> > + *  y = c/u (5)
> > + *
> > + * Square (4) and (5) and add:
> > + *
> > + *  x^2+y^2 = (a^2+c^2)/u^2
> > + *
> > + * But x^2+y^2 is 1:
> > + *
> > + *  1 = (a^2+c^2)/u^2
> > + *  u^2 = a^2+c^2
> > + *  u = hypot(a,c)
> > + *
> > + * Similarily the max/min of v is at:
> > + *
> > + *  v = hypot(b,d)
> > + *
> > + */
> >  static void
> >  compute_extents (pixman_f_transform_t *trans, double *sx, double *sy)
> >  {
> > -double min_x, max_x, min_y, max_y;
> > -pixman_f_vector_t v[4] =
> > -{
> > -   { { 1, 1, 1 } },
> > -   { { -1, 1, 1 } },
> > -   { { -1, -1, 1 } },
> > -   { { 1, -1, 1 } },
> > -};
> > -
> > -pixman_f_transform_point (trans, [0]);
> > -pixman_f_transform_point (trans, [1]);
> > -pixman_f_transform_point (trans, [2]);
> > -pixman_f_transform_point (trans, [3]);
> > -
> > -min_x = min4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
> > -max_x = max4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
> > -min_y = min4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
> > -max_y = max4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
> > -
> > -*sx = (max_x - min_x) / 2.0;
> > -*sy = (max_y - min_y) / 2.0;
> > +*sx = hypot (trans->m[0][0], trans->m[0][1]) / trans->m[2][2];
> > +*sy = hypot (trans->m[1][0], trans->m[1][1]) / trans->m[2][2];
> >  }
> >
> >  typedef struct
> > --
> > 1.9.1
> >
> > ___
> > Pixman mailing list
> > Pixman@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/pixman
>
> Reviewed-by: Oded Gabbay 
>
> p.s. if we have additional versions of this patch series, and patches
> that got r-b are not modified, then please add my r-b to the patch so
> I would know I don't need to spend even a second over that patch.
>
> Thanks
>
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman