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