/* * libpipi Proper image processing implementation library * Copyright (c) 2004-2008 Sam Hocevar * 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 #include #include #include #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 #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" #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" #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" #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; }