i_img_info() (C API) no longer tries to handle a NULL image object pointer.
[imager.git] / paste.im
CommitLineData
9b1ec2b8 1#include "imager.h"
6d068d36 2#include "imageri.h"
9b1ec2b8
TC
3
4/*
5715f7c3 5=item i_copyto(C<dest>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>)
9b1ec2b8
TC
6
7=category Image
8
5715f7c3
TC
9Copies image data from the area (C<x1>,C<y1>)-[C<x2>,C<y2>] in the
10source image to a rectangle the same size with it's top-left corner at
11(C<tx>,C<ty>) in the destination image.
9b1ec2b8 12
5715f7c3
TC
13If C<x1> > C<x2> or C<y1> > C<y2> then the corresponding co-ordinates
14are swapped.
9b1ec2b8
TC
15
16=cut
17*/
18
19void
8d14daab 20i_copyto(i_img *im, i_img *src, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, i_img_dim tx, i_img_dim ty) {
98747309 21 i_img_dim y, t, tty;
9b1ec2b8
TC
22
23 if (x2<x1) { t=x1; x1=x2; x2=t; }
24 if (y2<y1) { t=y1; y1=y2; y2=t; }
25 if (tx < 0) {
26 /* adjust everything equally */
27 x1 += -tx;
28 x2 += -tx;
29 tx = 0;
30 }
31 if (ty < 0) {
32 y1 += -ty;
33 y2 += -ty;
34 ty = 0;
35 }
36 if (x1 >= src->xsize || y1 >= src->ysize)
37 return; /* nothing to do */
38 if (x2 > src->xsize)
39 x2 = src->xsize;
40 if (y2 > src->ysize)
41 y2 = src->ysize;
42 if (x1 == x2 || y1 == y2)
43 return; /* nothing to do */
44
8d14daab
TC
45 mm_log((1,"i_copyto(im* %p, src %p, p1(" i_DFp "), p2(" i_DFp "), t("
46 i_DFp "))\n",
47 im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty)));
9b1ec2b8
TC
48
49#code im->bits == i_8_bits
50 IM_COLOR *row = mymalloc(sizeof(IM_COLOR) * (x2-x1));
51 tty = ty;
52 for(y=y1; y<y2; y++) {
9b1ec2b8
TC
53 IM_GLIN(src, x1, x2, y, row);
54 if (src->channels != im->channels)
55 IM_ADAPT_COLORS(im->channels, src->channels, row, x2-x1);
56 IM_PLIN(im, tx, tx+x2-x1, tty, row);
57 tty++;
58 }
59 myfree(row);
60#/code
61}
62
9b1ec2b8
TC
63#code
64void
65#ifdef IM_EIGHT_BIT
66i_adapt_colors
67#else
68i_adapt_fcolors
69#endif
70(int out_channels, int in_channels, IM_COLOR *colors,
71 size_t count) {
9b1ec2b8
TC
72 if (out_channels == in_channels)
73 return;
74 if (count == 0)
75 return;
76
77 switch (out_channels) {
78 case 1:
79 {
80 switch (in_channels) {
81 case 2:
82 /* apply alpha against a black background */
83 while (count) {
84 colors->channel[0] = colors->channel[0] * colors->channel[1] / IM_SAMPLE_MAX;
85 ++colors;
86 --count;
87 }
88 return;
89
90 case 3:
91 /* convert to grey */
92 while (count) {
93 colors->channel[0] = IM_ROUND(color_to_grey(colors));
94 ++colors;
95 --count;
96 }
97 return;
98
99 case 4:
100 while (count) {
101 colors->channel[0] = IM_ROUND(color_to_grey(colors) * colors->channel[3] / IM_SAMPLE_MAX);
102 ++colors;
103 --count;
104 }
105 return;
106
107 default:
108 i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels);
109 return; /* avoid warnings */
110 }
111 }
112
113 case 2:
114 {
115 switch (in_channels) {
116 case 1:
117 while (count) {
118 colors->channel[1] = IM_SAMPLE_MAX;
119 ++colors;
120 --count;
121 }
122 return;
123
124 case 3:
125 while (count) {
126 colors->channel[0] = IM_ROUND(color_to_grey(colors));
127 colors->channel[1] = IM_SAMPLE_MAX;
128 ++colors;
129 --count;
130 }
131 return;
132
133 case 4:
134 while (count) {
135 colors->channel[0] = IM_ROUND(color_to_grey(colors));
136 colors->channel[1] = colors->channel[3];
137 ++colors;
138 --count;
139 }
140 return;
141
142 default:
143 i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels);
144 return; /* avoid warnings */
145 }
146 }
147
148 case 3:
149 {
150 switch (in_channels) {
151 case 1:
152 while (count) {
153 colors->channel[1] = colors->channel[2] = colors->channel[0];
154 ++colors;
155 --count;
156 }
157 return;
158
159 case 2:
160 while (count) {
161 int alpha = colors->channel[1];
162 colors->channel[0] = colors->channel[1] = colors->channel[2] =
163 IM_ROUND(colors->channel[0] * alpha / IM_SAMPLE_MAX);
164 ++colors;
165 --count;
166 }
167 return;
168
169 case 4:
170 while (count) {
171 int alpha = colors->channel[3];
172 colors->channel[0] =
173 IM_ROUND(colors->channel[0] * alpha / IM_SAMPLE_MAX);
174 colors->channel[1] =
175 IM_ROUND(colors->channel[1] * alpha / IM_SAMPLE_MAX);
176 colors->channel[2] =
177 IM_ROUND(colors->channel[2] * alpha / IM_SAMPLE_MAX);
178 ++colors;
179 --count;
180 }
181 return;
182
183 default:
184 i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels);
185 return; /* avoid warnings */
186 }
187 }
188
189 case 4:
190 {
191 switch (in_channels) {
192 case 1:
193 while (count) {
194 colors->channel[1] = colors->channel[2] = colors->channel[0];
195 colors->channel[3] = IM_SAMPLE_MAX;
196 ++colors;
197 --count;
198 }
199 return;
200
201 case 2:
202 while (count) {
203 colors->channel[3] = colors->channel[1];
204 colors->channel[1] = colors->channel[2] = colors->channel[0];
205 ++colors;
206 --count;
207 }
208 return;
209
210 case 3:
211 while (count) {
212 colors->channel[3] = IM_SAMPLE_MAX;
213 ++colors;
214 --count;
215 }
216 return;
217
218 default:
219 i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels);
220 return; /* avoid warnings */
221 }
222 }
223
224 default:
225 i_fatal(3, "i_adapt_colors: out_channels of %d invalid\n", out_channels);
226 return; /* avoid warnings */
227 }
228}
229
6e4af7d4
TC
230void
231#ifdef IM_EIGHT_BIT
232i_adapt_colors_bg
233#else
234i_adapt_fcolors_bg
235#endif
236(int out_channels, int in_channels, IM_COLOR *colors,
237 size_t count, IM_COLOR const *bg) {
238 if (out_channels == in_channels)
239 return;
240 if (count == 0)
241 return;
242
243 switch (out_channels) {
244 case 2:
245 case 4:
246 IM_ADAPT_COLORS(out_channels, in_channels, colors, count);
247 return;
248
249 case 1:
250 switch (in_channels) {
251 case 3:
252 IM_ADAPT_COLORS(out_channels, in_channels, colors, count);
253 return;
254
255 case 2:
256 {
257 /* apply alpha against our given background */
258 IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg));
259 while (count) {
260 colors->channel[0] =
261 (colors->channel[0] * colors->channel[1] +
262 grey_bg * (IM_SAMPLE_MAX - colors->channel[1])) / IM_SAMPLE_MAX;
263 ++colors;
264 --count;
265 }
266 }
267 break;
268
269 case 4:
270 {
271 IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg));
272 while (count) {
273 IM_WORK_T src_grey = IM_ROUND(color_to_grey(colors));
274 colors->channel[0] =
275 (src_grey * colors->channel[3]
276 + grey_bg * (IM_SAMPLE_MAX - colors->channel[3])) / IM_SAMPLE_MAX;
277 ++colors;
278 --count;
279 }
280 }
281 break;
282 }
283 break;
284
285 case 3:
286 switch (in_channels) {
287 case 1:
288 IM_ADAPT_COLORS(out_channels, in_channels, colors, count);
289 return;
290
291 case 2:
292 {
293 while (count) {
294 int ch;
295 IM_WORK_T src_grey = colors->channel[0];
296 IM_WORK_T src_alpha = colors->channel[1];
297 for (ch = 0; ch < 3; ++ch) {
298 colors->channel[ch] =
299 (src_grey * src_alpha
300 + bg->channel[ch] * (IM_SAMPLE_MAX - src_alpha))
301 / IM_SAMPLE_MAX;
302 }
303 ++colors;
304 --count;
305 }
306 }
307 break;
308
309 case 4:
310 {
311 while (count) {
312 int ch;
313 IM_WORK_T src_alpha = colors->channel[3];
314 for (ch = 0; ch < 3; ++ch) {
315 colors->channel[ch] =
316 (colors->channel[ch] * src_alpha
317 + bg->channel[ch] * (IM_SAMPLE_MAX - src_alpha))
318 / IM_SAMPLE_MAX;
319 }
320 ++colors;
321 --count;
322 }
323 }
324 break;
325 }
326 break;
327 }
2a31a4b4
TC
328}
329
330/*
797a9f9c 331=item i_gsamp_bg(im, l, r, y, samples, out_channels, background)
2a31a4b4 332
797a9f9c 333=category Drawing
2a31a4b4 334
797a9f9c
TC
335Like C<i_gsampf()> but applies the source image color over a supplied
336background color.
2a31a4b4 337
797a9f9c
TC
338This is intended for output to image formats that don't support alpha
339channels.
340
50c75381
TC
341=cut
342
797a9f9c
TC
343=item i_gsampf_bg(im, l, r, y, samples, out_channels, background)
344
345=category Drawing
346
347Like C<i_gsampf()> but applies the source image color over a supplied
348background color.
349
350This is intended for output to image formats that don't support alpha
351channels.
2a31a4b4
TC
352
353=cut
354*/
355int
356#ifdef IM_EIGHT_BIT
357i_gsamp_bg
358#else
359i_gsampf_bg
360#endif
8d14daab 361(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, IM_SAMPLE_T *samples,
2a31a4b4
TC
362 int out_channels, IM_COLOR const *bg) {
363 if (out_channels == im->channels)
364 return IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
365
366 switch (out_channels) {
367 case 1:
368 switch (im->channels) {
369 case 2:
370 {
8d14daab 371 i_img_dim x;
2a31a4b4
TC
372 IM_SAMPLE_T *inp = samples, *outp = samples;
373 IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg));
8d14daab 374 i_img_dim count;
2a31a4b4
TC
375
376 count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
377 if (!count)
378 return 0;
379
380 for (x = l; x < r; ++x) {
381 *outp++ = ( inp[0] * inp[1] +
382 grey_bg * (IM_SAMPLE_MAX - inp[1])) / IM_SAMPLE_MAX;
383 inp += 2;
384 }
385
386 return count;
387 }
388 break;
389
390 default:
391 i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
392 break;
393 }
394 break;
395 case 3:
396 switch (im->channels) {
397 case 1:
398 {
399 int channels[3] = { 0, 0, 0 };
400 return IM_GSAMP(im, l, r, y, samples, channels, out_channels);
401 }
402 case 2:
403 {
8d14daab
TC
404 i_img_dim x;
405 int ch;
2a31a4b4 406 IM_SAMPLE_T *inp = samples, *outp = samples;
8d14daab 407 i_img_dim count;
2a31a4b4
TC
408 int channels[4] = { 0, 0, 0, 1 };
409
410 count = IM_GSAMP(im, l, r, y, samples, channels, im->channels);
411 if (!count)
412 return 0;
413
414 for (x = l; x < r; ++x) {
415 IM_WORK_T alpha = inp[3];
416 for (ch = 0; ch < 3; ++ch) {
417 *outp++ = ( *inp++ * alpha +
418 bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX;
419 }
420 ++inp;
421 }
422
423 return count;
424 }
425
426 case 4:
427 {
8d14daab
TC
428 i_img_dim x;
429 int ch;
2a31a4b4 430 IM_SAMPLE_T *inp = samples, *outp = samples;
8d14daab 431 i_img_dim count;
2a31a4b4
TC
432
433 count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
434 if (!count)
435 return 0;
436
437 for (x = l; x < r; ++x) {
438 IM_WORK_T alpha = inp[3];
439 for (ch = 0; ch < 3; ++ch) {
440 *outp++ = ( *inp++ * alpha +
441 bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX;
442 }
443 ++inp;
444 }
445
446 return count;
447 }
448 break;
449 default:
450 i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
451 break;
452 }
453 break;
454
455 default:
456 i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
457 }
6e4af7d4 458
2a31a4b4 459 return 0;
6e4af7d4
TC
460}
461
9b1ec2b8
TC
462#/code
463