]> git.imager.perl.org - imager.git/blob - conv.im
doc cleanups for Imager::Fill
[imager.git] / conv.im
1 #include "imager.h"
2 #include "imageri.h"
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
9   coeff: (double array) coefficients for filter
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
15 int
16 i_conv(i_img *im, const double *coeff,int len) {
17   i_img_dim xo, yo; /* output pixel co-ordinate */
18   int c, ch, center;
19   double pc;
20   double res[MAXCHANNELS];
21   i_img *timg;
22
23   mm_log((1,"i_conv(im %p, coeff %p, len %d)\n",im,coeff,len));
24   i_clear_error();
25
26   if (len < 1) {
27     i_push_error(0, "there must be at least one coefficient");
28     return 0;
29   }
30  
31   center=(len-1)/2;
32
33   pc = 0;
34   for (c = 0; c < len; ++c)
35     pc += coeff[c];
36
37   if (pc == 0) {
38     i_push_error(0, "sum of coefficients is zero");
39     return 0;
40   }
41
42   timg = i_sametype(im, im->xsize, im->ysize);
43
44 #code im->bits <= 8
45   IM_COLOR rcolor;
46   /* don't move the calculation of pc up here, it depends on which pixels
47      are readable */
48   for(yo = 0; yo < im->ysize; yo++) {
49     for(xo = 0; xo < im->xsize; xo++) {
50       for(ch = 0;ch < im->channels; ch++) 
51         res[ch] = 0;
52       for(c = 0;c < len; c++) {
53         i_img_dim xi = xo + c - center;
54         if (xi < 0)
55           xi = 0;
56         else if (xi >= im->xsize)
57           xi = im->xsize - 1;
58
59         if (IM_GPIX(im, xi, yo, &rcolor)!=-1) {
60           for(ch = 0; ch < im->channels; ch++) 
61             res[ch] += (rcolor.channel[ch])  *coeff[c];
62         }
63       }
64       im_assert(pc != 0);
65       for(ch = 0; ch < im->channels; ch++) {
66         double temp = res[ch] / pc;
67         rcolor.channel[ch] = 
68           temp < 0 ? 0 : temp > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : (IM_SAMPLE_T)temp;
69       }
70       IM_PPIX(timg, xo, yo, &rcolor);
71     }
72   }
73
74   for(xo = 0; xo < im->xsize; xo++) {
75     for(yo = 0;yo < im->ysize; yo++) {
76       for(ch =  0; ch < im->channels; ch++)
77         res[ch] = 0;
78       for(c = 0; c < len; c++) {
79         i_img_dim yi = yo + c - center;
80         if (yi < 0)
81           yi = 0;
82         else if (yi >= im->ysize)
83           yi = im->ysize - 1;
84         if (IM_GPIX(timg, xo, yi, &rcolor) != -1) {
85           for(ch = 0;ch < im->channels; ch++) 
86             res[ch] += (rcolor.channel[ch]) * coeff[c];
87         }
88       }
89       im_assert(pc != 0);
90       for(ch = 0;ch < im->channels; ch++) {
91         double temp = res[ch] / pc;
92         rcolor.channel[ch] = 
93           temp < 0 ? 0 : temp > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : (IM_SAMPLE_T)temp;
94       }
95       IM_PPIX(im, xo, yo,&rcolor);
96     }
97   }
98 #/code
99
100   i_img_destroy(timg);
101
102   return 1;
103 }