source: libpipi/trunk/pipi/filter/convolution.c @ 2701

Last change on this file since 2701 was 2701, checked in by Sam Hocevar, 13 years ago
  • convolution_template.h: split convolution routines into separate functions for each pixel format.
File size: 3.3 KB
Line 
1/*
2 *  libpipi       Proper image processing implementation library
3 *  Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 * convolution.c: generic convolution functions
17 */
18
19#include "config.h"
20#include "common.h"
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <math.h>
26
27#include "pipi.h"
28#include "pipi_internals.h"
29
30static pipi_image_t *conv_std_rgba_f(pipi_image_t *src,
31                                     int m, int n, double mat[]);
32static pipi_image_t *conv_sep_rgba_f(pipi_image_t *src,
33                                     int m, double hvec[],
34                                     int n, double vvec[]);
35#undef FUNC1
36#undef FUNC2
37#undef PIXEL
38#undef GRAY
39#define FUNC1 conv_std_rgba_f
40#define FUNC2 conv_sep_rgba_f
41#define PIXEL float
42#define GRAY 0
43#include "convolution_template.h"
44
45static pipi_image_t *conv_std_y_f(pipi_image_t *src,
46                                  int m, int n, double mat[]);
47static pipi_image_t *conv_sep_y_f(pipi_image_t *src,
48                                  int m, double hvec[],
49                                  int n, double vvec[]);
50#undef FUNC1
51#undef FUNC2
52#undef PIXEL
53#undef GRAY
54#define FUNC1 conv_std_y_f
55#define FUNC2 conv_sep_y_f
56#define PIXEL float
57#define GRAY 1
58#include "convolution_template.h"
59
60pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
61{
62    pipi_image_t *ret;
63    double tmp;
64    double *hvec, *vvec;
65    int i, j, besti = -1, bestj = -1;
66
67    /* Find the cell with the largest value */
68    tmp = 0.0;
69    for(i = 0; i < m * n; i++)
70        if(mat[i] * mat[i] > tmp)
71        {
72            tmp = mat[i] * mat[i];
73            besti = i % m;
74            bestj = i / m;
75        }
76
77    /* If the kernel is empty, return an empty picture */
78    if(tmp == 0.0)
79        return pipi_new(src->w, src->h);
80
81    /* Check whether the matrix rank is 1 */
82    for(j = 0; j < n; j++)
83    {
84        if(j == bestj)
85            continue;
86
87        for(i = 0; i < m; i++)
88        {
89            double p, q;
90
91            if(i == besti)
92                continue;
93
94            p = mat[j * m + i] * mat[bestj * m + besti];
95            q = mat[bestj * m + i] * mat[j * m + besti];
96
97            if(fabs(p - q) > 0.0001 * 0.0001)
98            {
99                if(src->last_modified == PIPI_PIXELS_Y_F)
100                    return conv_std_y_f(src, m, n, mat);
101                else
102                    return conv_std_rgba_f(src, m, n, mat);
103            }
104        }
105    }
106
107    /* Matrix rank is 1! Separate the filter */
108    hvec = malloc(m * sizeof(double));
109    vvec = malloc(n * sizeof(double));
110
111    tmp = sqrt(fabs(mat[bestj * m + besti]));
112    for(i = 0; i < m; i++)
113        hvec[i] = mat[bestj * m + i] / tmp;
114    for(j = 0; j < n; j++)
115        vvec[j] = mat[j * m + besti] / tmp;
116
117    if(src->last_modified == PIPI_PIXELS_Y_F)
118        ret = conv_sep_y_f(src, m, hvec, n, vvec);
119    else
120        ret = conv_sep_rgba_f(src, m, hvec, n, vvec);
121
122    free(hvec);
123    free(vvec);
124
125    return ret;
126}
127
Note: See TracBrowser for help on using the repository browser.