|
- /*
- * libpipi Proper image processing implementation library
- * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
- * All Rights Reserved
- *
- * $Id$
- *
- * This library is free software. It comes without any warranty, to
- * the extent permitted by applicable law. You can redistribute it
- * and/or modify it under the terms of the Do What The Fuck You Want
- * To Public License, Version 2, as published by Sam Hocevar. See
- * http://sam.zoy.org/wtfpl/COPYING for more details.
- */
-
- /*
- * convolution.c: generic convolution functions
- */
-
- #include "config.h"
- #include "common.h"
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
-
- #include "pipi.h"
- #include "pipi_internals.h"
-
- #define FLAG_GRAY ((FLAGS) & SET_FLAG_GRAY)
- #define FLAG_WRAP ((FLAGS) & SET_FLAG_WRAP)
-
- #define SET_FLAG_GRAY 0x01
- #define SET_FLAG_WRAP 0x02
-
- static pipi_image_t *conv_std_rgba_f(pipi_image_t *src,
- int m, int n, double mat[]);
- static pipi_image_t *conv_sep_rgba_f(pipi_image_t *src,
- int m, double hvec[],
- int n, double vvec[]);
- #undef FUNC1
- #undef FUNC2
- #undef PIXEL
- #undef FLAGS
- #define FUNC1 conv_std_rgba_f
- #define FUNC2 conv_sep_rgba_f
- #define PIXEL float
- #define FLAGS 0
- #include "convolution_template.h"
-
- static pipi_image_t *conv_std_y_f(pipi_image_t *src,
- int m, int n, double mat[]);
- static pipi_image_t *conv_sep_y_f(pipi_image_t *src,
- int m, double hvec[],
- int n, double vvec[]);
- #undef FUNC1
- #undef FUNC2
- #undef PIXEL
- #undef FLAGS
- #define FUNC1 conv_std_y_f
- #define FUNC2 conv_sep_y_f
- #define PIXEL float
- #define FLAGS SET_FLAG_GRAY
- #include "convolution_template.h"
-
- static pipi_image_t *wrap_std_rgba_f(pipi_image_t *src,
- int m, int n, double mat[]);
- static pipi_image_t *wrap_sep_rgba_f(pipi_image_t *src,
- int m, double hvec[],
- int n, double vvec[]);
- #undef FUNC1
- #undef FUNC2
- #undef PIXEL
- #undef FLAGS
- #define FUNC1 wrap_std_rgba_f
- #define FUNC2 wrap_sep_rgba_f
- #define PIXEL float
- #define FLAGS SET_FLAG_WRAP
- #include "convolution_template.h"
-
- static pipi_image_t *wrap_std_y_f(pipi_image_t *src,
- int m, int n, double mat[]);
- static pipi_image_t *wrap_sep_y_f(pipi_image_t *src,
- int m, double hvec[],
- int n, double vvec[]);
- #undef FUNC1
- #undef FUNC2
- #undef PIXEL
- #undef FLAGS
- #define FUNC1 wrap_std_y_f
- #define FUNC2 wrap_sep_y_f
- #define PIXEL float
- #define FLAGS SET_FLAG_GRAY|SET_FLAG_WRAP
- #include "convolution_template.h"
-
- pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
- {
- pipi_image_t *ret;
- double tmp;
- double *hvec, *vvec;
- int i, j, besti = -1, bestj = -1;
-
- /* Find the cell with the largest value */
- tmp = 0.0;
- for(i = 0; i < m * n; i++)
- if(mat[i] * mat[i] > tmp)
- {
- tmp = mat[i] * mat[i];
- besti = i % m;
- bestj = i / m;
- }
-
- /* If the kernel is empty, return an empty picture */
- if(tmp == 0.0)
- return pipi_new(src->w, src->h);
-
- /* Check whether the matrix rank is 1 */
- for(j = 0; j < n; j++)
- {
- if(j == bestj)
- continue;
-
- for(i = 0; i < m; i++)
- {
- double p, q;
-
- if(i == besti)
- continue;
-
- p = mat[j * m + i] * mat[bestj * m + besti];
- q = mat[bestj * m + i] * mat[j * m + besti];
-
- if(fabs(p - q) > 0.0001 * 0.0001)
- {
- if(src->last_modified == PIPI_PIXELS_Y_F)
- {
- if(src->wrap)
- return wrap_std_y_f(src, m, n, mat);
- return conv_std_y_f(src, m, n, mat);
- }
- else
- {
- if(src->wrap)
- return wrap_std_rgba_f(src, m, n, mat);
- return conv_std_rgba_f(src, m, n, mat);
- }
- }
- }
- }
-
- /* Matrix rank is 1! Separate the filter */
- hvec = malloc(m * sizeof(double));
- vvec = malloc(n * sizeof(double));
-
- tmp = sqrt(fabs(mat[bestj * m + besti]));
- for(i = 0; i < m; i++)
- hvec[i] = mat[bestj * m + i] / tmp;
- for(j = 0; j < n; j++)
- vvec[j] = mat[j * m + besti] / tmp;
-
- if(src->last_modified == PIPI_PIXELS_Y_F)
- ret = src->wrap ? wrap_sep_y_f(src, m, hvec, n, vvec)
- : conv_sep_y_f(src, m, hvec, n, vvec);
- else
- ret = src->wrap ? wrap_sep_rgba_f(src, m, hvec, n, vvec)
- : conv_sep_rgba_f(src, m, hvec, n, vvec);
-
- free(hvec);
- free(vvec);
-
- return ret;
- }
|