]> git.imager.perl.org - imager.git/blob - compose.im
the PERL_INITIALIZE_IMAGER_PERL_CALLBACKS was checking the wrong version number
[imager.git] / compose.im
1 #include "imager.h"
2 #include "imrender.h"
3 #include "imageri.h"
4
5 int
6 i_compose_mask(i_img *out, i_img *src, i_img *mask, 
7                int out_left, int out_top,
8                int src_left, int src_top,
9                int mask_left, int mask_top,
10                int width, int height,
11                int combine,
12                double opacity) {
13   i_render r;
14   int dy;
15   i_fill_combine_f combinef_8;
16   i_fill_combinef_f combinef_double;
17   int channel_zero = 0;
18
19   mm_log((1, "i_compose_mask(out %p, src %p, mask %p, out(%d, %d), src(%d, %d),"
20           " mask(%d,%d), size(%d,%d), combine %d opacity %f\n", out, src, 
21           mask, out_left, out_top, src_left, src_top, mask_left, mask_top, width,
22           height, combine, opacity));
23
24   i_clear_error();
25   if (out_left >= out->xsize
26       || out_top >= out->ysize
27       || src_left >= src->xsize
28       || src_top >= src->ysize
29       || width <= 0
30       || height <= 0
31       || out_left + width <= 0
32       || out_top + height <= 0
33       || src_left + width <= 0
34       || src_top + height <= 0
35       || mask_left >= mask->xsize
36       || mask_top >= mask->ysize
37       || mask_left + width <= 0
38       || mask_top + height <= 0)
39     return 0;
40
41   if (out_left < 0) {
42     width = out_left + width;
43     src_left -= out_left;
44     mask_left -= out_left;
45     out_left = 0;
46   }
47   if (out_left + width > out->xsize)
48     width = out->xsize - out_left;
49
50   if (out_top < 0) {
51     height = out_top + height;
52     mask_top -= out_top;
53     src_top -= out_top;
54     out_top = 0;
55   }
56   if (out_top + height > out->ysize)
57     height = out->ysize - out_top;
58
59   if (src_left < 0) {
60     width = src_left + width;
61     out_left -= src_left;
62     mask_left -= src_left;
63     src_left = 0;
64   }
65   if (src_left + width > src->xsize)
66     width = src->xsize - src_left;
67
68   if (src_top < 0) {
69     height = src_top + height;
70     out_top -= src_top;
71     mask_top -= src_top;
72     src_top = 0;
73   }
74   if (src_top + height > src->ysize)
75     height = src->ysize - src_top;
76
77   if (mask_left < 0) {
78     width = mask_left + width;
79     out_left -= mask_left;
80     src_left -= mask_left;
81     mask_left = 0;
82   }
83   if (mask_left + width > mask->xsize)
84     width = mask->xsize - mask_left;
85   
86   if (mask_top < 0) {
87     height = mask_top + height;
88     src_top -= mask_top;
89     out_top -= mask_top;
90     mask_top = 0;
91   }
92   if (mask_top + height > mask->ysize)
93     height = mask->ysize - mask_top;
94
95   if (opacity > 1.0)
96     opacity = 1.0;
97   else if (opacity <= 0) {
98     i_push_error(0, "opacity must be positive");
99     return 0;
100   }
101
102   mm_log((1, "after adjustments: (out(%d, %d), src(%d, %d),"
103           " mask(%d,%d), size(%d,%d)\n", 
104           out_left, out_top, src_left, src_top, mask_left, mask_top, width,
105           height));
106
107   i_get_combine(combine, &combinef_8, &combinef_double);
108
109   i_render_init(&r, out, width);
110 #code out->bits <= 8 && src->bits<= 8 && mask->bits <= 8
111   IM_COLOR *src_line = mymalloc(sizeof(IM_COLOR) * width);
112   IM_SAMPLE_T *mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
113   int adapt_channels = out->channels;
114
115   if (adapt_channels == 1 || adapt_channels == 3)
116     ++adapt_channels;
117
118   for (dy = 0; dy < height; ++dy) {
119     IM_GLIN(src, src_left, src_left + width, src_top + dy, src_line);
120     IM_ADAPT_COLORS(adapt_channels, src->channels, src_line, width);
121     IM_GSAMP(mask, mask_left, mask_left + width, mask_top + dy, 
122              mask_line, &channel_zero, 1);
123     if (opacity < 1.0) {
124       int i;
125       IM_SAMPLE_T *maskp = mask_line;
126       for (i = 0; i < width; ++i) {
127         *maskp = IM_ROUND(*maskp * opacity);
128         ++maskp;
129       }
130     }
131     IM_RENDER_LINE(&r, out_left, out_top+dy, width, mask_line, src_line,
132                    IM_SUFFIX(combinef));
133   }
134   myfree(src_line);
135   myfree(mask_line);
136   
137 #/code
138   i_render_done(&r);
139
140   return 1;
141 }
142
143 int
144 i_compose(i_img *out, i_img *src,
145           int out_left, int out_top,
146           int src_left, int src_top,
147           int width, int height,
148           int combine,
149           double opacity) {
150   i_render r;
151   int dy;
152   i_fill_combine_f combinef_8;
153   i_fill_combinef_f combinef_double;
154
155   mm_log((1, "i_compose(out %p, src %p, out(%d, %d), src(%d, %d), size(%d,%d),"
156           " combine %d opacity %f\n", out, src, out_left, out_top,
157           src_left, src_top, width, height, combine, opacity));
158
159   i_clear_error();
160   if (out_left >= out->xsize
161       || out_top >= out->ysize
162       || src_left >= src->xsize
163       || src_top >= src->ysize
164       || width <= 0
165       || height <= 0
166       || out_left + width <= 0
167       || out_top + height <= 0
168       || src_left + width <= 0
169       || src_top + height <= 0)
170     return 0;
171
172   if (out_left < 0) {
173     width = out_left + width;
174     src_left -= out_left;
175     out_left = 0;
176   }
177   if (out_left + width > out->xsize)
178     width = out->xsize - out_left;
179
180   if (out_top < 0) {
181     height = out_top + height;
182     src_top -= out_top;
183     out_top = 0;
184   }
185   if (out_top + height > out->ysize)
186     height = out->ysize - out_top;
187
188   if (src_left < 0) {
189     width = src_left + width;
190     out_left -= src_left;
191     src_left = 0;
192   }
193   if (src_left + width > src->xsize)
194     width = src->xsize - src_left;
195
196   if (src_top < 0) {
197     height = src_top + height;
198     out_top -= src_top;
199     src_top = 0;
200   }
201   if (src_top + height > src->ysize)
202     height = src->ysize - src_top;
203
204   if (opacity > 1.0)
205     opacity = 1.0;
206   else if (opacity <= 0) {
207     i_push_error(0, "opacity must be positive");
208     return 0;
209   }
210
211   i_get_combine(combine, &combinef_8, &combinef_double);
212
213   i_render_init(&r, out, width);
214 #code out->bits <= 8 && src->bits <= 8
215   IM_COLOR *src_line = mymalloc(sizeof(IM_COLOR) * width);
216   IM_SAMPLE_T *mask_line = NULL;
217   int adapt_channels = out->channels;
218
219   if (opacity != 1.0) {
220     int i;
221     IM_SAMPLE_T mask_value = IM_ROUND(opacity * IM_SAMPLE_MAX);
222     mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
223
224     for (i = 0; i < width; ++i)
225       mask_line[i] = mask_value;
226   }
227
228   if (adapt_channels == 1 || adapt_channels == 3)
229     ++adapt_channels;
230
231   for (dy = 0; dy < height; ++dy) {
232     IM_GLIN(src, src_left, src_left + width, src_top + dy, src_line);
233     IM_ADAPT_COLORS(adapt_channels, src->channels, src_line, width);
234     IM_RENDER_LINE(&r, out_left, out_top+dy, width, mask_line, src_line,
235                    IM_SUFFIX(combinef));
236   }
237   myfree(src_line);
238   if (mask_line)
239     myfree(mask_line);
240   
241 #/code
242   i_render_done(&r);
243
244   return 1;
245 }