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

Last change on this file since 2703 was 2703, checked in by Sam Hocevar, 13 years ago
  • convolution.c: support for wrap-around in convolutions.
  • pipi.c: add the "--wrap" flag to tell libpipi that a given image wraps around.
File size: 4.8 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
30#define FLAG_GRAY ((FLAGS) & SET_FLAG_GRAY)
31#define FLAG_WRAP ((FLAGS) & SET_FLAG_WRAP)
32
33#define SET_FLAG_GRAY 0x01
34#define SET_FLAG_WRAP 0x02
35
36static pipi_image_t *conv_std_rgba_f(pipi_image_t *src,
37                                     int m, int n, double mat[]);
38static pipi_image_t *conv_sep_rgba_f(pipi_image_t *src,
39                                     int m, double hvec[],
40                                     int n, double vvec[]);
41#undef FUNC1
42#undef FUNC2
43#undef PIXEL
44#undef FLAGS
45#define FUNC1 conv_std_rgba_f
46#define FUNC2 conv_sep_rgba_f
47#define PIXEL float
48#define FLAGS 0
49#include "convolution_template.h"
50
51static pipi_image_t *conv_std_y_f(pipi_image_t *src,
52                                  int m, int n, double mat[]);
53static pipi_image_t *conv_sep_y_f(pipi_image_t *src,
54                                  int m, double hvec[],
55                                  int n, double vvec[]);
56#undef FUNC1
57#undef FUNC2
58#undef PIXEL
59#undef FLAGS
60#define FUNC1 conv_std_y_f
61#define FUNC2 conv_sep_y_f
62#define PIXEL float
63#define FLAGS SET_FLAG_GRAY
64#include "convolution_template.h"
65
66static pipi_image_t *wrap_std_rgba_f(pipi_image_t *src,
67                                     int m, int n, double mat[]);
68static pipi_image_t *wrap_sep_rgba_f(pipi_image_t *src,
69                                     int m, double hvec[],
70                                     int n, double vvec[]);
71#undef FUNC1
72#undef FUNC2
73#undef PIXEL
74#undef FLAGS
75#define FUNC1 wrap_std_rgba_f
76#define FUNC2 wrap_sep_rgba_f
77#define PIXEL float
78#define FLAGS SET_FLAG_WRAP
79#include "convolution_template.h"
80
81static pipi_image_t *wrap_std_y_f(pipi_image_t *src,
82                                  int m, int n, double mat[]);
83static pipi_image_t *wrap_sep_y_f(pipi_image_t *src,
84                                  int m, double hvec[],
85                                  int n, double vvec[]);
86#undef FUNC1
87#undef FUNC2
88#undef PIXEL
89#undef FLAGS
90#define FUNC1 wrap_std_y_f
91#define FUNC2 wrap_sep_y_f
92#define PIXEL float
93#define FLAGS SET_FLAG_GRAY|SET_FLAG_WRAP
94#include "convolution_template.h"
95
96pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
97{
98    pipi_image_t *ret;
99    double tmp;
100    double *hvec, *vvec;
101    int i, j, besti = -1, bestj = -1;
102
103    /* Find the cell with the largest value */
104    tmp = 0.0;
105    for(i = 0; i < m * n; i++)
106        if(mat[i] * mat[i] > tmp)
107        {
108            tmp = mat[i] * mat[i];
109            besti = i % m;
110            bestj = i / m;
111        }
112
113    /* If the kernel is empty, return an empty picture */
114    if(tmp == 0.0)
115        return pipi_new(src->w, src->h);
116
117    /* Check whether the matrix rank is 1 */
118    for(j = 0; j < n; j++)
119    {
120        if(j == bestj)
121            continue;
122
123        for(i = 0; i < m; i++)
124        {
125            double p, q;
126
127            if(i == besti)
128                continue;
129
130            p = mat[j * m + i] * mat[bestj * m + besti];
131            q = mat[bestj * m + i] * mat[j * m + besti];
132
133            if(fabs(p - q) > 0.0001 * 0.0001)
134            {
135                if(src->last_modified == PIPI_PIXELS_Y_F)
136                {
137                    if(src->wrap)
138                        return wrap_std_y_f(src, m, n, mat);
139                    return conv_std_y_f(src, m, n, mat);
140                }
141                else
142                {
143                    if(src->wrap)
144                        return wrap_std_rgba_f(src, m, n, mat);
145                    return conv_std_rgba_f(src, m, n, mat);
146                }
147            }
148        }
149    }
150
151    /* Matrix rank is 1! Separate the filter */
152    hvec = malloc(m * sizeof(double));
153    vvec = malloc(n * sizeof(double));
154
155    tmp = sqrt(fabs(mat[bestj * m + besti]));
156    for(i = 0; i < m; i++)
157        hvec[i] = mat[bestj * m + i] / tmp;
158    for(j = 0; j < n; j++)
159        vvec[j] = mat[j * m + besti] / tmp;
160
161    if(src->last_modified == PIPI_PIXELS_Y_F)
162        ret = src->wrap ? wrap_sep_y_f(src, m, hvec, n, vvec)
163                        : conv_sep_y_f(src, m, hvec, n, vvec);
164    else
165        ret = src->wrap ? wrap_sep_rgba_f(src, m, hvec, n, vvec)
166                        : conv_sep_rgba_f(src, m, hvec, n, vvec);
167
168    free(hvec);
169    free(vvec);
170
171    return ret;
172}
173
Note: See TracBrowser for help on using the repository browser.