diff options
author | Bill Spitzak <spitzak@gmail.com> | 2016-03-06 17:06:44 -0800 |
---|---|---|
committer | Søren Sandmann Pedersen <soren.sandmann@gmail.com> | 2016-03-11 00:00:45 -0500 |
commit | 287ff4cd89f1da45db3a50bc12c4cbe3ed5fe449 (patch) | |
tree | 739ca3d32a650ae138502f9c6259add63418506c | |
parent | 5cd193992007e6099224c2da55f0080161a002c7 (diff) |
pixman-filter: Correct Simpsons integration
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,0,6,0,6...,2,1.
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
v11: minor whitespace change
v14: more whitespace changes
Signed-off-by: Bill Spitzak <spitzak@gmail.com>
Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com>
-rw-r--r-- | pixman/pixman-filter.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c index c03a7f6d..bd5ac4c7 100644 --- a/pixman/pixman-filter.c +++ b/pixman/pixman-filter.c @@ -189,13 +189,19 @@ integral (pixman_kernel_t kernel1, 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[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale)) 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 kernel1, double x1, { double a1 = x1 + h * i; double a2 = x2 + h * i; + 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); - - if (i >= 2 && i < N_SEGMENTS - 1) - s += 4 * SAMPLE (a1, a2); } s += SAMPLE (x1 + width, x2 + width); |