commit changes from draw branch
[imager.git] / paste.im
1 #include "imager.h"
2
3 /*
4 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
5
6 =category Image
7
8 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
9 a rectangle the same size with it's top-left corner at (tx,ty) in the
10 destination image.
11
12 If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
13
14 =cut
15 */
16
17 void
18 i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
19   int x, y, t, ttx, tty;
20   
21   if (x2<x1) { t=x1; x1=x2; x2=t; }
22   if (y2<y1) { t=y1; y1=y2; y2=t; }
23   if (tx < 0) {
24     /* adjust everything equally */
25     x1 += -tx;
26     x2 += -tx;
27     tx = 0;
28   }
29   if (ty < 0) {
30     y1 += -ty;
31     y2 += -ty;
32     ty = 0;
33   }
34   if (x1 >= src->xsize || y1 >= src->ysize)
35     return; /* nothing to do */
36   if (x2 > src->xsize)
37     x2 = src->xsize;
38   if (y2 > src->ysize)
39     y2 = src->ysize;
40   if (x1 == x2 || y1 == y2)
41     return; /* nothing to do */
42
43   mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
44           im, src, x1, y1, x2, y2, tx, ty));
45
46 #code im->bits == i_8_bits
47   IM_COLOR *row = mymalloc(sizeof(IM_COLOR) * (x2-x1));
48   tty = ty;
49   for(y=y1; y<y2; y++) {
50     ttx = tx;
51     IM_GLIN(src, x1, x2, y, row);
52     if (src->channels != im->channels)
53       IM_ADAPT_COLORS(im->channels, src->channels, row, x2-x1);
54     IM_PLIN(im, tx, tx+x2-x1, tty, row);
55     tty++;
56   }
57   myfree(row);
58 #/code
59 }
60
61 #define color_to_grey(col) ((col)->rgb.r * 0.222  + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071)
62
63 #code
64 void
65 #ifdef IM_EIGHT_BIT
66 i_adapt_colors
67 #else
68 i_adapt_fcolors
69 #endif
70 (int out_channels, int in_channels, IM_COLOR *colors, 
71                size_t count) {
72   int i;
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 #/code
232