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