diff options
Diffstat (limited to 'downscaling.c')
-rw-r--r-- | downscaling.c | 121 |
1 files changed, 85 insertions, 36 deletions
diff --git a/downscaling.c b/downscaling.c index 2dadb09..dc16c2e 100644 --- a/downscaling.c +++ b/downscaling.c @@ -274,22 +274,95 @@ create_gaussian_kernel (int r, int *n_params) return params; } +typedef double (* convolution_t) (int size, double x, double y); + static void -set_gaussian (pixman_image_t *image, int w, int h, double scale) +set_convolution (pixman_image_t *image, int w, int h, + int size, convolution_t convolution) { int n_params; + pixman_fixed_16_16_t *params; + double *dparams; + double sum; + int i, j; + + n_params = size * size + 2; + + dparams = g_malloc (n_params * sizeof (double)); + params = g_malloc (n_params * sizeof (pixman_fixed_16_16_t)); + + sum = 0.0; + for (i = 0; i < size; ++i) + { + for (j = 0; j < size; ++j) + { + int idx = i * size + j + 2; -#define RAD 5 + dparams[idx] = convolution (size, i - size / 2, j - size / 2); - pixman_fixed_16_16_t *params = - create_gaussian_kernel (RAD, &n_params); + sum += dparams[idx]; + } + } - params[0] = (RAD * 2 + 1) << 16; - params[1] = (RAD * 2 + 1) << 16; + g_print ("sum %f\n", sum); + for (i = 0; i < size; ++i) + { + for (j = 0; j < size; ++j) + { + int idx = i * size + j + 2; + + params[idx] = _cairo_fixed_16_16_from_double (dparams[idx] / sum); + + g_print ("%.4f ", dparams[idx] / sum); + } + + g_print ("\n"); + } + + params[0] = size << 16; + params[1] = size << 16; + pixman_image_set_filter (image, PIXMAN_FILTER_CONVOLUTION, params, n_params); +} - g_free (params); +static double +gaussian (int size, double x, double y) +{ + double sigma = (size / 2.0) / 2.0; + + return (1 / (2 * G_PI * sigma * sigma)) * exp (-(x * x + y * y) / (2 * sigma * sigma)); +} + +static void +set_gaussian (pixman_image_t *image, int w, int h, double scale) +{ + set_convolution (image, w, h, 5 / scale, gaussian); +} + +static double +lanczos (int size, double x, double y) +{ + double a = size; + double d = sqrt (x * x + y * y); + double res; + + if (fabs (d) < DBL_EPSILON) + { + res = 1.0; + } + else + { + res = (a * sin (G_PI * d) * sin ((G_PI * d)/ a)) / (G_PI * G_PI * d * d); + } + + return res; +} + +static void +set_lanczos (pixman_image_t *image, int w, int h, double scale) +{ + set_convolution (image, w, h, 5 / scale, lanczos); } static void @@ -304,10 +377,10 @@ set_nearest (pixman_image_t *image, int w, int h, double scale) pixman_image_set_filter (image, PIXMAN_FILTER_NEAREST, NULL, 0); } -static void -set_lanczos (pixman_image_t *image, int w, int h, double scale) +static double +box (int size, double x, double y) { - g_error ("Lanczos filter is not implemented yet"); + return 1; } static void @@ -315,35 +388,11 @@ set_box (pixman_image_t *image, int w, int h, double scale) { if (scale < 1.0) { - int size = (1.0 / scale + 0.5); - int n_params = size * size + 2; - pixman_fixed_16_16_t *params = g_malloc (n_params * sizeof (pixman_fixed_16_16_t)); - int i, j; - - params[0] = size << 16; - params[1] = size << 16; - - g_print ("size of box: %d\n", size); - - for (i = 0; i < size; ++i) - { - for (j = 0; j < size; ++j) - { - int idx = i * size + j + 2; - - g_assert (idx < n_params); - - params[idx] = _cairo_fixed_16_16_from_double (1.0 / (size * size)); - } - } - - pixman_image_set_filter (image, PIXMAN_FILTER_CONVOLUTION, params, n_params); - - g_free (params); + set_convolution (image, w, h, 1.0 / scale + 0.5, box); } else { - pixman_image_set_filter (image, PIXMAN_FILTER_NEAREST, NULL, 0); + pixman_image_set_filter (image, PIXMAN_FILTER_BILINEAR, NULL, 0); } } |