Commit | Line | Data |
---|---|---|
92bda632 | 1 | #include "imager.h" |
6a3cbaef | 2 | #include "imageri.h" |
02d1d628 AMH |
3 | |
4 | /* | |
5 | General convolution for 2d decoupled filters | |
6 | end effects are acounted for by increasing | |
7 | scaling the result with the sum of used coefficients | |
8 | ||
8d14daab | 9 | coeff: (double array) coefficients for filter |
02d1d628 AMH |
10 | len: length of filter.. number of coefficients |
11 | note that this has to be an odd number | |
12 | (since the filter is even); | |
13 | */ | |
14 | ||
6a3cbaef TC |
15 | int |
16 | i_conv(i_img *im, const double *coeff,int len) { | |
8d14daab | 17 | i_img_dim xo, yo; /* output pixel co-ordinate */ |
6a3cbaef | 18 | int c, ch, center; |
bd8052a6 | 19 | double pc; |
6a3cbaef | 20 | double res[MAXCHANNELS]; |
bd8052a6 | 21 | i_img *timg; |
02d1d628 | 22 | |
a73aeb5f | 23 | mm_log((1,"i_conv(im %p, coeff %p, len %d)\n",im,coeff,len)); |
6a3cbaef | 24 | i_clear_error(); |
02d1d628 | 25 | |
02d1d628 AMH |
26 | center=(len-1)/2; |
27 | ||
6a3cbaef TC |
28 | pc = 0; |
29 | for (c = 0; c < len; ++c) | |
30 | pc += coeff[c]; | |
31 | ||
32 | if (pc == 0) { | |
33 | i_push_error(0, "sum of coefficients is zero"); | |
34 | return 0; | |
35 | } | |
36 | ||
37 | timg = i_sametype(im, im->xsize, im->ysize); | |
38 | ||
bd8052a6 TC |
39 | #code im->bits <= 8 |
40 | IM_COLOR rcolor; | |
6e473a59 TC |
41 | /* don't move the calculation of pc up here, it depends on which pixels |
42 | are readable */ | |
6a3cbaef TC |
43 | for(yo = 0; yo < im->ysize; yo++) { |
44 | for(xo = 0; xo < im->xsize; xo++) { | |
45 | for(ch = 0;ch < im->channels; ch++) | |
46 | res[ch] = 0; | |
47 | for(c = 0;c < len; c++) { | |
8d14daab | 48 | i_img_dim xi = xo + c - center; |
6a3cbaef TC |
49 | if (xi < 0) |
50 | xi = 0; | |
51 | else if (xi >= im->xsize) | |
52 | xi = im->xsize - 1; | |
53 | ||
54 | if (IM_GPIX(im, xi, yo, &rcolor)!=-1) { | |
55 | for(ch = 0; ch < im->channels; ch++) | |
56 | res[ch] += (rcolor.channel[ch]) *coeff[c]; | |
02d1d628 | 57 | } |
6a3cbaef TC |
58 | } |
59 | im_assert(pc != 0); | |
60 | for(ch = 0; ch < im->channels; ch++) { | |
61 | double temp = res[ch] / pc; | |
0b76fec8 | 62 | rcolor.channel[ch] = |
bd8052a6 | 63 | temp < 0 ? 0 : temp > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : (IM_SAMPLE_T)temp; |
0b76fec8 | 64 | } |
6a3cbaef | 65 | IM_PPIX(timg, xo, yo, &rcolor); |
02d1d628 AMH |
66 | } |
67 | } | |
68 | ||
6a3cbaef TC |
69 | for(xo = 0; xo < im->xsize; xo++) { |
70 | for(yo = 0;yo < im->ysize; yo++) { | |
71 | for(ch = 0; ch < im->channels; ch++) | |
72 | res[ch] = 0; | |
73 | for(c = 0; c < len; c++) { | |
8d14daab | 74 | i_img_dim yi = yo + c - center; |
6a3cbaef TC |
75 | if (yi < 0) |
76 | yi = 0; | |
77 | else if (yi >= im->ysize) | |
78 | yi = im->ysize - 1; | |
79 | if (IM_GPIX(timg, xo, yi, &rcolor) != -1) { | |
80 | for(ch = 0;ch < im->channels; ch++) | |
81 | res[ch] += (rcolor.channel[ch]) * coeff[c]; | |
02d1d628 | 82 | } |
bd8052a6 | 83 | } |
6a3cbaef TC |
84 | im_assert(pc != 0); |
85 | for(ch = 0;ch < im->channels; ch++) { | |
86 | double temp = res[ch] / pc; | |
87 | rcolor.channel[ch] = | |
bd8052a6 TC |
88 | temp < 0 ? 0 : temp > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : (IM_SAMPLE_T)temp; |
89 | } | |
6a3cbaef | 90 | IM_PPIX(im, xo, yo,&rcolor); |
02d1d628 | 91 | } |
bd8052a6 TC |
92 | } |
93 | #/code | |
94 | ||
95 | i_img_destroy(timg); | |
02d1d628 | 96 | |
6a3cbaef TC |
97 | return 1; |
98 | } |