]> mj.ucw.cz Git - libucw.git/blob - images/scale-gen.h
Merge with git+ssh://cvs.ucw.cz/projects/sherlock/GIT/sherlock.git
[libucw.git] / images / scale-gen.h
1 /*
2  *      Image Library -- Image scaling algorithms
3  *
4  *      (c) 2006 Pavel Charvat <pchar@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #ifndef IMAGE_SCALE_CHANNELS
11 #  define IMAGE_SCALE_CHANNELS IMAGE_SCALE_PIXEL_SIZE
12 #endif
13
14 static void
15 IMAGE_SCALE_PREFIX(downsample)(struct image *dest, struct image *src)
16 {
17   /* FIXME slow */
18   byte *rsrc = src->pixels, *psrc;
19   byte *rdest = dest->pixels, *pdest;
20   uns x_inc = (dest->cols << 16) / src->cols, x_pos, x_inc_frac = 0xffffff / x_inc;
21   uns y_inc = (dest->rows << 16) / src->rows, y_pos = 0, y_inc_frac = 0xffffff / y_inc;
22   uns final_mul = ((u64)x_inc * y_inc) >> 16;
23   uns buf_size = dest->cols * IMAGE_SCALE_CHANNELS;
24   u32 buf[buf_size], *pbuf;
25   buf_size *= sizeof(u32);
26   bzero(buf, buf_size);
27   for (uns rows_counter = src->rows; rows_counter--; )
28     {
29       pbuf = buf;
30       psrc = rsrc;
31       rsrc += src->row_size;
32       x_pos = 0;
33       y_pos += y_inc;
34       if (y_pos <= 0x10000)
35         {
36           for (uns cols_counter = src->cols; cols_counter--; )
37             {
38               x_pos += x_inc;
39               if (x_pos <= 0x10000)
40                 {
41                   pbuf[0] += psrc[0];
42 #                 if IMAGE_SCALE_CHANNELS >= 2
43                   pbuf[1] += psrc[1];
44 #                 endif
45 #                 if IMAGE_SCALE_CHANNELS >= 3
46                   pbuf[2] += psrc[2];
47 #                 endif
48 #                 if IMAGE_SCALE_CHANNELS >= 4
49                   pbuf[3] += psrc[3];
50 #                 endif
51                 }
52               else
53                 {
54                   x_pos -= 0x10000;
55                   uns mul2 = x_pos * x_inc_frac;
56                   uns mul1 = 0xffffff - mul2;
57                   pbuf[0] += (psrc[0] * mul1) >> 24;
58                   pbuf[0 + IMAGE_SCALE_CHANNELS] += (psrc[0] * mul2) >> 24;
59 #                 if IMAGE_SCALE_CHANNELS >= 2
60                   pbuf[1] += (psrc[1] * mul1) >> 24;
61                   pbuf[1 + IMAGE_SCALE_CHANNELS] += (psrc[1] * mul2) >> 24;
62 #                 endif
63 #                 if IMAGE_SCALE_CHANNELS >= 3
64                   pbuf[2] += (psrc[2] * mul1) >> 24;
65                   pbuf[2 + IMAGE_SCALE_CHANNELS] += (psrc[2] * mul2) >> 24;
66 #                 endif
67 #                 if IMAGE_SCALE_CHANNELS >= 4
68                   pbuf[3] += (psrc[3] * mul1) >> 24;
69                   pbuf[3 + IMAGE_SCALE_CHANNELS] += (psrc[3] * mul2) >> 24;
70 #                 endif
71                   pbuf += IMAGE_SCALE_CHANNELS;
72                 }
73               psrc += IMAGE_SCALE_PIXEL_SIZE;
74             }
75         }
76       else
77         {
78           y_pos -= 0x10000;
79           pdest = rdest;
80           rdest += dest->row_size;
81           uns mul2 = y_pos * y_inc_frac;
82           uns mul1 = 0xffffff - mul2;
83           uns a0 = 0;
84 #         if IMAGE_SCALE_CHANNELS >= 2
85           uns a1 = 0;
86 #         endif
87 #         if IMAGE_SCALE_CHANNELS >= 3
88           uns a2 = 0;
89 #         endif
90 #         if IMAGE_SCALE_CHANNELS >= 4
91           uns a3 = 0;
92 #         endif
93           for (uns cols_counter = src->cols; cols_counter--; )
94             {
95               x_pos += x_inc;
96               if (x_pos <= 0x10000)
97                 {
98                   pbuf[0] += ((psrc[0] * mul1) >> 24);
99                   a0 += (psrc[0] * mul2) >> 24;
100 #                 if IMAGE_SCALE_CHANNELS >= 2
101                   pbuf[1] += ((psrc[1] * mul1) >> 24);
102                   a1 += (psrc[1] * mul2) >> 24;
103 #                 endif
104 #                 if IMAGE_SCALE_CHANNELS >= 3
105                   pbuf[2] += ((psrc[2] * mul1) >> 24);
106                   a2 += (psrc[2] * mul2) >> 24;
107 #                 endif
108 #                 if IMAGE_SCALE_CHANNELS >= 4
109                   pbuf[3] += ((psrc[3] * mul1) >> 24);
110                   a3 += (psrc[3] * mul2) >> 24;
111 #                 endif
112                 }
113               else
114                 {
115                   x_pos -= 0x10000;
116                   uns mul4 = x_pos * x_inc_frac;
117                   uns mul3 = 0xffffff - mul4;
118                   uns mul13 = ((u64)mul1 * mul3) >> 24;
119                   uns mul23 = ((u64)mul2 * mul3) >> 24;
120                   uns mul14 = ((u64)mul1 * mul4) >> 24;
121                   uns mul24 = ((u64)mul2 * mul4) >> 24;
122                   pdest[0] = ((((psrc[0] * mul13) >> 24) + pbuf[0]) * final_mul) >> 16;
123                   pbuf[0] = ((psrc[0] * mul23) >> 24) + a0;
124                   pbuf[0 + IMAGE_SCALE_CHANNELS] += ((psrc[0 + IMAGE_SCALE_PIXEL_SIZE] * mul14) >> 24);
125                   a0 = ((psrc[0 + IMAGE_SCALE_PIXEL_SIZE] * mul24) >> 24);
126 #                 if IMAGE_SCALE_CHANNELS >= 2
127                   pdest[1] = ((((psrc[1] * mul13) >> 24) + pbuf[1]) * final_mul) >> 16;
128                   pbuf[1] = ((psrc[1] * mul23) >> 24) + a1;
129                   pbuf[1 + IMAGE_SCALE_CHANNELS] += ((psrc[1 + IMAGE_SCALE_PIXEL_SIZE] * mul14) >> 24);
130                   a1 = ((psrc[1 + IMAGE_SCALE_PIXEL_SIZE] * mul24) >> 24);
131 #                 endif
132 #                 if IMAGE_SCALE_CHANNELS >= 3
133                   pdest[2] = ((((psrc[2] * mul13) >> 24) + pbuf[2]) * final_mul) >> 16;
134                   pbuf[2] = ((psrc[2] * mul23) >> 24) + a2;
135                   pbuf[2 + IMAGE_SCALE_CHANNELS] += ((psrc[2 + IMAGE_SCALE_PIXEL_SIZE] * mul14) >> 24);
136                   a2 = ((psrc[2 + IMAGE_SCALE_PIXEL_SIZE] * mul24) >> 24);
137 #                 endif
138 #                 if IMAGE_SCALE_CHANNELS >= 4
139                   pdest[3] = ((((psrc[3] * mul13) >> 24) + pbuf[3]) * final_mul) >> 16;
140                   pbuf[3] = ((psrc[3] * mul23) >> 24) + a3;
141                   pbuf[3 + IMAGE_SCALE_CHANNELS] += ((psrc[3 + IMAGE_SCALE_PIXEL_SIZE] * mul14) >> 24);
142                   a3 = ((psrc[3 + IMAGE_SCALE_PIXEL_SIZE] * mul24) >> 24);
143 #                 endif
144                   pbuf += IMAGE_SCALE_CHANNELS;
145                   pdest += IMAGE_SCALE_PIXEL_SIZE;
146                 }
147               psrc += IMAGE_SCALE_PIXEL_SIZE;
148             }
149           pdest[0] = (pbuf[0] * final_mul) >> 16;
150           pbuf[0] = a0;
151 #         if IMAGE_SCALE_CHANNELS >= 2
152           pdest[1] = (pbuf[1] * final_mul) >> 16;
153           pbuf[1] = a1;
154 #         endif
155 #         if IMAGE_SCALE_CHANNELS >= 3
156           pdest[2] = (pbuf[2] * final_mul) >> 16;
157           pbuf[2] = a2;
158 #         endif
159 #         if IMAGE_SCALE_CHANNELS >= 4
160           pdest[3] = (pbuf[3] * final_mul) >> 16;
161           pbuf[3] = a3;
162 #         endif
163         }
164     }
165   pdest = rdest;
166   pbuf = buf;
167   for (uns cols_counter = dest->cols; cols_counter--; )
168     {
169       pdest[0] = (pbuf[0] * final_mul) >> 16;
170 #     if IMAGE_SCALE_CHANNELS >= 2
171       pdest[1] = (pbuf[1] * final_mul) >> 16;
172 #     endif
173 #     if IMAGE_SCALE_CHANNELS >= 3
174       pdest[2] = (pbuf[2] * final_mul) >> 16;
175 #     endif
176 #     if IMAGE_SCALE_CHANNELS >= 4
177       pdest[3] = (pbuf[3] * final_mul) >> 16;
178 #     endif
179       pbuf += IMAGE_SCALE_CHANNELS;
180       pdest += IMAGE_SCALE_PIXEL_SIZE;
181     }
182 }
183
184 #undef IMAGE_SCALE_PREFIX
185 #undef IMAGE_SCALE_PIXEL_SIZE
186 #undef IMAGE_SCALE_CHANNELS