]> git.imager.perl.org - imager.git/blob - paste.im
convert t/t55trans.t to Test::More
[imager.git] / paste.im
1 #include "imager.h"
2
3 /*
4 =item i_copyto(C<dest>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>)
5
6 =category Image
7
8 Copies image data from the area (C<x1>,C<y1>)-[C<x2>,C<y2>] in the
9 source image to a rectangle the same size with it's top-left corner at
10 (C<tx>,C<ty>) in the destination image.
11
12 If C<x1> > C<x2> or C<y1> > C<y2> then the corresponding co-ordinates
13 are swapped.
14
15 =cut
16 */
17
18 void
19 i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
20   int y, t, ttx, tty;
21   
22   if (x2<x1) { t=x1; x1=x2; x2=t; }
23   if (y2<y1) { t=y1; y1=y2; y2=t; }
24   if (tx < 0) {
25     /* adjust everything equally */
26     x1 += -tx;
27     x2 += -tx;
28     tx = 0;
29   }
30   if (ty < 0) {
31     y1 += -ty;
32     y2 += -ty;
33     ty = 0;
34   }
35   if (x1 >= src->xsize || y1 >= src->ysize)
36     return; /* nothing to do */
37   if (x2 > src->xsize)
38     x2 = src->xsize;
39   if (y2 > src->ysize)
40     y2 = src->ysize;
41   if (x1 == x2 || y1 == y2)
42     return; /* nothing to do */
43
44   mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
45           im, src, x1, y1, x2, y2, tx, ty));
46
47 #code im->bits == i_8_bits
48   IM_COLOR *row = mymalloc(sizeof(IM_COLOR) * (x2-x1));
49   tty = ty;
50   for(y=y1; y<y2; y++) {
51     ttx = tx;
52     IM_GLIN(src, x1, x2, y, row);
53     if (src->channels != im->channels)
54       IM_ADAPT_COLORS(im->channels, src->channels, row, x2-x1);
55     IM_PLIN(im, tx, tx+x2-x1, tty, row);
56     tty++;
57   }
58   myfree(row);
59 #/code
60 }
61
62 #define color_to_grey(col) ((col)->rgb.r * 0.222  + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071)
63
64 #code
65 void
66 #ifdef IM_EIGHT_BIT
67 i_adapt_colors
68 #else
69 i_adapt_fcolors
70 #endif
71 (int out_channels, int in_channels, IM_COLOR *colors, 
72                size_t count) {
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
231 void
232 #ifdef IM_EIGHT_BIT
233 i_adapt_colors_bg
234 #else
235 i_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   }
329 }
330
331 /*
332 =item i_gsamp_bg(im, l, r, y, samples, out_channels, background)
333
334 =category Drawing
335
336 Like C<i_gsampf()> but applies the source image color over a supplied
337 background color.
338
339 This is intended for output to image formats that don't support alpha
340 channels.
341
342 =cut
343
344 =item i_gsampf_bg(im, l, r, y, samples, out_channels, background)
345
346 =category Drawing
347
348 Like C<i_gsampf()> but applies the source image color over a supplied
349 background color.
350
351 This is intended for output to image formats that don't support alpha
352 channels.
353
354 =cut
355 */
356 int
357 #ifdef IM_EIGHT_BIT
358 i_gsamp_bg
359 #else
360 i_gsampf_bg
361 #endif
362 (i_img *im, int l, int r, int y, IM_SAMPLE_T *samples, 
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       {
372         int x;
373         IM_SAMPLE_T *inp = samples, *outp = samples;
374         IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg));
375         int count;
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       {
405         int x, ch;
406         IM_SAMPLE_T *inp = samples, *outp = samples;
407         int count;
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       {
428         int x, ch;
429         IM_SAMPLE_T *inp = samples, *outp = samples;
430         int count;
431
432         count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
433         if (!count)
434           return 0;
435         
436         for (x = l; x < r; ++x) {
437           IM_WORK_T alpha = inp[3];
438           for (ch = 0; ch < 3; ++ch) {
439             *outp++ = ( *inp++ * alpha +
440                         bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX;
441           }
442           ++inp;
443         }
444
445         return count;
446       }
447       break;
448     default:
449       i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
450       break;
451     }
452     break;
453
454   default:
455     i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
456   }
457
458   return 0;
459 }
460
461 #/code
462