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

2016-02-04 Thread Oded Gabbay
On Tue, Feb 2, 2016 at 8:28 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.

I'm just wondering how did you get to this result ?

Oded

>
> 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 mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


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

2016-02-04 Thread Oded Gabbay
On Tue, Feb 2, 2016 at 8:28 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
>
> v10: Restored filter_width function but with arguments changed to
>  match later patches
>
> Signed-off-by: Bill Spitzak 
>
> Reviewed-by: Oded Gabbay 

When you change and then re-change the patch, you definitely can't
keep this tag :)
Only when you resend it without *any* changes or when you fix
according to a specific comment you can keep it.

> ---
>  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 */
Well, it doesn't modify them, so I think we should match the comment
to the function, no ?
And if you intend to change it in the future, then specifically write
it like that, i.e. "in the future, this function can be re-written to
also modify the size & subsample bits"

> +static int
> +filter_width(pixman_kernel_t reconstruct, pixman_kernel_t sample,
> +double* size, int* subsample_bits)
1. Why do we need *subsample_bits if we don't use it in the function ?
Please remove it.
2. Why pass size as pointer ? We don't change it, so why not by value ?
And if in the future you do want to change them, then do it in the
future patches, not here. It is very confusing.

> +{
> +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;
>
>  

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

2016-02-04 Thread Oded Gabbay
On Tue, Feb 2, 2016 at 8:28 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.
>
> 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 

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

2016-02-04 Thread Oded Gabbay
On Tue, Feb 2, 2016 at 8:28 AM,   wrote:
> 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

I would need to see some form of test/example that is affected by this
patch, as I don't have the knowledge to even ACK it.

Otherwise, you will need to get someone else to review this (Soren ?).

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


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

2016-02-04 Thread Oded Gabbay
On Tue, Feb 2, 2016 at 8:28 AM,   wrote:
> 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

I would need to see some form of test/example that is affected by this
patch, as I don't have the knowledge to even ACK it.

Otherwise, you will need to get someone else to review this (Soren ?).

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


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

2016-02-04 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

v11: Whitespace fixes

Signed-off-by: Bill Spitzak 

Acked-by: Oded Gabbay 
---
 pixman/pixman-filter.c | 154 +
 1 file changed, 79 insertions(+), 75 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 8b8fb82..e82871f 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) 

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

2016-02-04 Thread spitzak
From: Bill Spitzak 

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

v11: Further correction, in particular replaced "scale" with "size"

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

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index e57b154..b23d348 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -379,6 +379,56 @@ subsample_bits (int subsample_bits, pixman_kernel_t 
sample, double size)
 
 /* 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
+ *
+ * size_x/y: amount to stretch the sample filter. The best value to
+ * use is the derivative of the sample location. This value is
+ * approximately 1/scale when scaling an image. If size < 1.0 then you
+ * will get square pixels as an image is enlarged, using 1.0 instead
+ * will get the more customary "blurry" enlargement.
+ *
+ * reconstruct_x/y: filter that is not resized.
+ *
+ * sample_x/y: filter that is resized. Result 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 size==1, but fewer are computed for larger sizes and
+ * more for smaller sizes.
+ *
+ * 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 size < 1.0.
+ *
+ *  x.IMPULSE - Uses the reconstruct function only, size is ignored. This is
+ *  what many pieces of software do for size < 1.0.
+ *
+ *  LINEAR.IMPULSE - Same as the bilinear filter
+ *
+ *  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". At size==1 this matches LINEAR.IMPULSE, 
IMPULSE.LINEAR, and
+ *the bilinear filter, allowing transitions at those points.
+ *
+ *  BOX.x - For size < 1.0 this produces square pixels. For size > 1.0 this
+ *  approaches IMPULSE.x as size gets larger.
+ *
+ *  BOX.LINEAR - At size==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 - At size==1 this is what some software calls "cubic 
interpolation".
+ *
+ *  IMPULSE.LANCZOS2 - Close to what a lot of other software calls "cubic 
interpolation"
+ *
+ *  IMPULSE.CUBIC - A third thing often called "cubic interpolation", 
sometimes 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 v11 05/14] pixman-filter: Consistency in arg names to integral ()

2016-02-04 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 3981c8b..b70da1f 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 v11 14/14] demos/scale: default to GOOD and locked-together axis

2016-02-04 Thread spitzak
From: Bill Spitzak 

This makes the demo match normal behavior of pixman/cairo at startup.

Signed-off-by: Bill Spitzak 
---
 demos/scale.c  | 10 +-
 demos/scale.ui |  1 +
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/demos/scale.c b/demos/scale.c
index 6d7ad2a..d1fce5d 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
-- 
1.9.1

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


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

2016-02-04 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 v11] Implement PIXMAN_FILTER_GOOD/BEST

2016-02-04 Thread spitzak
Changes form previous version:
- whitespace and formatting fixes
- removed "fixes" for IMPULSE.x at size < 1 or IMPULSE.IMPULSE, just let them
  produce unusable filters, since caller can avoid doing this.
- removed patch that deleted range checks
- simplification of the filter_width function
- fixed the comment to use "size" instead of "scale"


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


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

2016-02-04 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

v11: small whitespace fixes

Signed-off-by: Bill Spitzak 

Reviewed-by: Oded Gabbay 
---
 configure.ac   | 13 +
 pixman/pixman-filter.c | 45 +
 2 files changed, 58 insertions(+)

diff --git a/configure.ac b/configure.ac
index 6b2134e..e833e45 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..3981c8b 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 v11 03/14] demos/scale: Only generate filters when used for separable

2016-02-04 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 

Reviewed-by: Oded Gabbay 
---
 demos/scale.c | 29 +++--
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/demos/scale.c b/demos/scale.c
index 06821e3..6d7ad2a 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 v11 06/14] pixman-filter: reduce amount of malloc/free/memcpy to generate filter

2016-02-04 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

v11: Removed unused arg and pointer from filter_width function
 Whitespace fixes.

Signed-off-by: Bill Spitzak 
---
 pixman/pixman-filter.c | 55 +-
 1 file changed, 23 insertions(+), 32 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index b70da1f..69ac3ab 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,12 @@ gnuplot_filter(int width, int samples, const 
pixman_fixed_t* p)
 }
 #endif
 
+static int
+filter_width (pixman_kernel_t reconstruct, pixman_kernel_t sample, double size)
+{
+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 +350,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, sx);
 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, sy);
+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 v11 09/14] pixman-filter: Nested polynomial for cubic

2016-02-04 Thread spitzak
From: Bill Spitzak 

v11: Restored range checks

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

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index e82871f..e5ef8e6 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -109,14 +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;
+   return (((12 - 9 * B - 6 * C) * ax +
+(-18 + 12 * B + 6 * C)) * ax * ax +
+   (6 - 2 * B)) / 6;
 }
-else if (ax >= 1 && ax < 2)
+else if (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 -B - 6 * C) * ax +
+ (6 * B + 30 * C)) * ax +
+(-12 * B - 48 * C)) * ax +
+   (8 * B + 24 * C)) / 6;
 }
 else
 {
-- 
1.9.1

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


Re: [Pixman] [PATCH 1/2] Add test for _intersect_rect(, )

2016-02-04 Thread Siarhei Siamashka
Hello Bill,

Thanks for the patches. By the way, they are a little bit
mangled, maybe because you did not use "git send-email" to
send them? This is easily fixable for small patches like
this, but may become a problem for larger patch sets.


On Tue, 2 Feb 2016 17:35:28 -0800
Bill McCloskey  wrote:

> This test ensures that calling _intersect_rect on an empty
> rectangle produces an empty region.
>
> Reviewed-by: Siarhei Siamashka 

Your "Signed-off-by: Bill McCloskey "
should be also here.

Also adding my "Reviewed-by" was a little bit premature because
I had no idea how this patch would look in the end. I only
promised that getting my "Reviewed-by" would be easy.

> ---
>  test/region-test.c | 9 +
>  1 file changed, 9 insertions(+)
> 
> diff --git a/test/region-test.c b/test/region-test.c
> index bfc219b..e5743e8 100644
> --- a/test/region-test.c
> +++ b/test/region-test.c
> @@ -116,10 +116,19 @@ main ()
> 
> assert (pixman_region32_equal (, ));
> pixman_region32_fini ();
> pixman_region32_fini ();
> 
>  }
>  pixman_image_unref (fill);
> 
> +/* This would produce a region containing an empty
> + * rectangle in it. Such regions are considered malformed,
> + * but using an empty rectangle for initialization should
> + * work.
> + */

Do I understand it right that you are trying to describe the
implementation details of the current bug in this comment? But
after we fix the bug, this description would instantly become
obsolete and will just confuse the people reading the code.

I think that just using the commit message here would make a
perfect comment:

"This test ensures that calling _intersect_rect on an empty
rectangle produces an empty region."

> +pixman_region32_init_rects (, boxes, 3);
> +pixman_region32_intersect_rect (, , 11, 11, 0, 0);
> +assert (!pixman_region32_not_empty());

This is not too critical, but having "pixman_region32_fini ();"
here would be nice.

> +
>  return 0;
>  }

You can send a v2 patch (trying to use "git send-email" this time).

Or if you prefer, I can push this patch with the above mentioned
adjustments.

-- 
Best regards,
Siarhei Siamashka
___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


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

2016-02-04 Thread Bill Spitzak

On 02/04/2016 05:42 AM, Oded Gabbay wrote:

On Tue, Feb 2, 2016 at 8:28 AM,   wrote:

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


Let's separate pixman core changes and demo changes. It's bad for
bisectability and maintainability.

Do the core changes first, then another patch for the scale demo.



 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;
+   

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

2016-02-04 Thread Oded Gabbay
On Tue, Feb 2, 2016 at 8:28 AM,   wrote:
> 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

Let's separate pixman core changes and demo changes. It's bad for
bisectability and maintainability.

Do the core changes first, then another patch for the scale demo.

>
> 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;
> +