5e0c236aa3bade567ced5294f78516fa96335ef0
[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   i_clear_error();
20   if (out_left >= out->xsize
21       || out_top >= out->ysize
22       || src_left >= src->xsize
23       || src_top >= src->ysize
24       || width <= 0
25       || height <= 0
26       || out_left + width <= 0
27       || out_top + height <= 0
28       || src_left + width <= 0
29       || src_top + height <= 0
30       || mask_left >= mask->xsize
31       || mask_top >= mask->ysize
32       || mask_left + width <= 0
33       || mask_top + height <= 0)
34     return 0;
35
36   if (out_left < 0) {
37     width = out_left + width;
38     out_left = 0;
39   }
40   if (out_left + width > out->xsize)
41     width = out->xsize - out_left;
42
43   if (out_top < 0) {
44     height = out_top + height;
45     out_top = 0;
46   }
47   if (out_top + height > out->ysize)
48     height = out->ysize - out_top;
49
50   if (src_left < 0) {
51     width = src_left + width;
52     src_left = 0;
53   }
54   if (src_left + width > src->xsize)
55     width = src->xsize - src_left;
56
57   if (src_top < 0) {
58     height = src_top + height;
59     src_top = 0;
60   }
61   if (src_top + height > src->ysize)
62     height = src->ysize - src_left;
63
64   if (mask_left < 0) {
65     width = mask_left + width;
66     mask_left = 0;
67   }
68   if (mask_left + width > mask->xsize)
69     width = mask->xsize - mask_left;
70   
71   if (mask_top < 0) {
72     height = mask->ysize + height;
73     mask_top = 0;
74   }
75   if (mask_top + height > mask->ysize)
76     height = mask->xsize - mask_top;
77
78   if (opacity > 1.0)
79     opacity = 1.0;
80   else if (opacity <= 0)
81     return 0;
82
83   i_get_combine(combine, &combinef_8, &combinef_double);
84
85   i_render_init(&r, out, width);
86 #code out->bits <= 8 && src->bits<= 8 && mask->bits <= 8
87   IM_COLOR *src_line = mymalloc(sizeof(IM_COLOR) * width);
88   IM_SAMPLE_T *mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
89   int adapt_channels = out->channels;
90
91   if (adapt_channels == 1 || adapt_channels == 3)
92     ++adapt_channels;
93
94   for (dy = 0; dy < height; ++dy) {
95     IM_GLIN(src, src_left, src_left + width, src_top + dy, src_line);
96     IM_ADAPT_COLORS(adapt_channels, src->channels, src_line, width);
97     IM_GSAMP(mask, mask_left, mask_left + width, mask_top + dy, 
98              mask_line, &channel_zero, 1);
99     if (opacity < 1.0) {
100       int i;
101       IM_SAMPLE_T *maskp = mask_line;
102       for (i = 0; i < width; ++i) {
103         *maskp = IM_ROUND(*maskp * opacity);
104         ++maskp;
105       }
106     }
107     IM_RENDER_LINE(&r, out_left, out_top+dy, width, mask_line, src_line,
108                    IM_SUFFIX(combinef));
109   }
110   myfree(src_line);
111   myfree(mask_line);
112   
113 #/code
114   i_render_done(&r);
115
116   return 1;
117 }
118
119 int
120 i_compose(i_img *out, i_img *src,
121           int out_left, int out_top,
122           int src_left, int src_top,
123           int width, int height,
124           int combine,
125           double opacity) {
126   i_render r;
127   int dy;
128   i_fill_combine_f combinef_8;
129   i_fill_combinef_f combinef_double;
130
131   i_clear_error();
132   if (out_left >= out->xsize
133       || out_top >= out->ysize
134       || src_left >= src->xsize
135       || src_top >= src->ysize
136       || width <= 0
137       || height <= 0
138       || out_left + width <= 0
139       || out_top + height <= 0
140       || src_left + width <= 0
141       || src_top + height <= 0)
142     return 0;
143
144   if (out_left < 0) {
145     width = out_left + width;
146     out_left = 0;
147   }
148   if (out_left + width > out->xsize)
149     width = out->xsize - out_left;
150
151   if (out_top < 0) {
152     height = out_top + height;
153     out_top = 0;
154   }
155   if (out_top + height > out->ysize)
156     height = out->ysize - out_top;
157
158   if (src_left < 0) {
159     width = src_left + width;
160     src_left = 0;
161   }
162   if (src_left + width > src->xsize)
163     width = src->xsize - src_left;
164
165   if (src_top < 0) {
166     height = src_top + height;
167     src_top = 0;
168   }
169   if (src_top + height > src->ysize)
170     height = src->ysize - src_left;
171
172   if (opacity > 1.0)
173     opacity = 1.0;
174   else if (opacity <= 0)
175     return 0;
176
177   i_get_combine(combine, &combinef_8, &combinef_double);
178
179   i_render_init(&r, out, width);
180 #code out->bits <= 8 && src->bits <= 8
181   IM_COLOR *src_line = mymalloc(sizeof(IM_COLOR) * width);
182   IM_SAMPLE_T *mask_line = NULL;
183   int adapt_channels = out->channels;
184
185   if (opacity != 1.0) {
186     int i;
187     IM_SAMPLE_T mask_value = IM_ROUND(opacity * IM_SAMPLE_MAX);
188     mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
189
190     for (i = 0; i < width; ++i)
191       mask_line[i] = mask_value;
192   }
193
194   if (adapt_channels == 1 || adapt_channels == 3)
195     ++adapt_channels;
196
197   for (dy = 0; dy < height; ++dy) {
198     IM_GLIN(src, src_left, src_left + width, src_top + dy, src_line);
199     IM_ADAPT_COLORS(adapt_channels, src->channels, src_line, width);
200     IM_RENDER_LINE(&r, out_left, out_top+dy, width, mask_line, src_line,
201                    IM_SUFFIX(combinef));
202   }
203   myfree(src_line);
204   if (mask_line)
205     myfree(mask_line);
206   
207 #/code
208   i_render_done(&r);
209
210   return 1;
211 }