huge spelling update and spell checking patch
[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, bg)
333
334 =item i_gsampf_bg(im, l, r, y, samples, out_channels, bg)
335
336 This is similar to i_adapt_colors_bg() except it can only strip an
337 alpha channel.  It cannot be used to convert a source RGB image to
338 greyscale.
339
340 The samples parameter MUST include enough space for all samples of the
341 source image.
342
343 =cut
344 */
345 int
346 #ifdef IM_EIGHT_BIT
347 i_gsamp_bg
348 #else
349 i_gsampf_bg
350 #endif
351 (i_img *im, int l, int r, int y, IM_SAMPLE_T *samples, 
352  int out_channels, IM_COLOR const *bg) {
353   if (out_channels == im->channels)
354     return IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
355   
356   switch (out_channels) {
357   case 1:
358     switch (im->channels) {
359     case 2:
360       {
361         int x;
362         IM_SAMPLE_T *inp = samples, *outp = samples;
363         IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg));
364         int count;
365
366         count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
367         if (!count)
368           return 0;
369         
370         for (x = l; x < r; ++x) {
371           *outp++ = ( inp[0] * inp[1] +
372                       grey_bg * (IM_SAMPLE_MAX - inp[1])) / IM_SAMPLE_MAX;
373           inp += 2;
374         }
375
376         return count;
377       }
378       break;
379
380     default:
381       i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
382       break;
383     }
384     break;
385   case 3:
386     switch (im->channels) {
387     case 1:
388       {
389         int channels[3] = { 0, 0, 0 };
390         return IM_GSAMP(im, l, r, y, samples, channels, out_channels);
391       }
392     case 2:
393       {
394         int x, ch;
395         IM_SAMPLE_T *inp = samples, *outp = samples;
396         int count;
397         int channels[4] = { 0, 0, 0, 1 };
398
399         count = IM_GSAMP(im, l, r, y, samples, channels, im->channels);
400         if (!count)
401           return 0;
402         
403         for (x = l; x < r; ++x) {
404           IM_WORK_T alpha = inp[3];
405           for (ch = 0; ch < 3; ++ch) {
406             *outp++ = ( *inp++ * alpha +
407                         bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX;
408           }
409           ++inp;
410         }
411
412         return count;
413       }
414
415     case 4:
416       {
417         int x, ch;
418         IM_SAMPLE_T *inp = samples, *outp = samples;
419         int count;
420
421         count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
422         if (!count)
423           return 0;
424         
425         for (x = l; x < r; ++x) {
426           IM_WORK_T alpha = inp[3];
427           for (ch = 0; ch < 3; ++ch) {
428             *outp++ = ( *inp++ * alpha +
429                         bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX;
430           }
431           ++inp;
432         }
433
434         return count;
435       }
436       break;
437     default:
438       i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
439       break;
440     }
441     break;
442
443   default:
444     i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
445   }
446
447   return 0;
448 }
449
450 #/code
451