Add VCS links
[debian-dgen.git] / scale2x / scalebit.c
blob80bdb26ed8c06d2d30505303817bcb7d7973eda6
1 /*
2 * This file is part of the Scale2x project.
4 * Copyright (C) 2003, 2004 Andrea Mazzoleni
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * This file contains an example implementation of the Scale effect
23 * applyed to a generic bitmap.
25 * You can find an high level description of the effect at :
27 * http://scale2x.sourceforge.net/
29 * Alternatively at the previous license terms, you are allowed to use this
30 * code in your program with these conditions:
31 * - the program is not used in commercial activities.
32 * - the whole source code of the program is released with the binary.
33 * - derivative works of the program are allowed.
36 #if HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #include "scale2x.h"
41 #include "scale3x.h"
43 #if HAVE_ALLOCA_H
44 #include <alloca.h>
45 #endif
47 #include <assert.h>
48 #include <stdlib.h>
50 #define SSDST(bits, num) (scale2x_uint##bits *)dst##num
51 #define SSSRC(bits, num) (const scale2x_uint##bits *)src##num
53 /**
54 * Apply the Scale2x effect on a group of rows. Used internally.
56 static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
58 switch (pixel) {
59 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
60 case 1 : scale2x_8_mmx(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
61 case 2 : scale2x_16_mmx(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
62 case 4 : scale2x_32_mmx(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
63 #else
64 case 1 : scale2x_8_def(SSDST(8,0), SSDST(8,1), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
65 case 2 : scale2x_16_def(SSDST(16,0), SSDST(16,1), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
66 case 4 : scale2x_32_def(SSDST(32,0), SSDST(32,1), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
67 #endif
71 /**
72 * Apply the Scale2x3 effect on a group of rows. Used internally.
74 static inline void stage_scale2x3(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
76 switch (pixel) {
77 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
78 case 1 : scale2x3_8_mmx(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
79 case 2 : scale2x3_16_mmx(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
80 case 4 : scale2x3_32_mmx(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
81 #else
82 case 1 : scale2x3_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
83 case 2 : scale2x3_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
84 case 4 : scale2x3_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
85 #endif
89 /**
90 * Apply the Scale2x4 effect on a group of rows. Used internally.
92 static inline void stage_scale2x4(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
94 switch (pixel) {
95 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
96 case 1 : scale2x4_8_mmx(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
97 case 2 : scale2x4_16_mmx(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
98 case 4 : scale2x4_32_mmx(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
99 #else
100 case 1 : scale2x4_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSDST(8,3), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
101 case 2 : scale2x4_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSDST(16,3), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
102 case 4 : scale2x4_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSDST(32,3), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
103 #endif
108 * Apply the Scale3x effect on a group of rows. Used internally.
110 static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
112 switch (pixel) {
113 case 1 : scale3x_8_def(SSDST(8,0), SSDST(8,1), SSDST(8,2), SSSRC(8,0), SSSRC(8,1), SSSRC(8,2), pixel_per_row); break;
114 case 2 : scale3x_16_def(SSDST(16,0), SSDST(16,1), SSDST(16,2), SSSRC(16,0), SSSRC(16,1), SSSRC(16,2), pixel_per_row); break;
115 case 4 : scale3x_32_def(SSDST(32,0), SSDST(32,1), SSDST(32,2), SSSRC(32,0), SSSRC(32,1), SSSRC(32,2), pixel_per_row); break;
120 * Apply the Scale4x effect on a group of rows. Used internally.
122 static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row)
124 stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);
125 stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);
128 #define SCDST(i) (dst+(i)*dst_slice)
129 #define SCSRC(i) (src+(i)*src_slice)
130 #define SCMID(i) (mid[(i)])
133 * Apply the Scale2x effect on a bitmap.
134 * The destination bitmap is filled with the scaled version of the source bitmap.
135 * The source bitmap isn't modified.
136 * The destination bitmap must be manually allocated before calling the function,
137 * note that the resulting size is exactly 2x2 times the size of the source bitmap.
138 * \param void_dst Pointer at the first pixel of the destination bitmap.
139 * \param dst_slice Size in bytes of a destination bitmap row.
140 * \param void_src Pointer at the first pixel of the source bitmap.
141 * \param src_slice Size in bytes of a source bitmap row.
142 * \param pixel Bytes per pixel of the source and destination bitmap.
143 * \param width Horizontal size in pixels of the source bitmap.
144 * \param height Vertical size in pixels of the source bitmap.
146 static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
148 unsigned char* dst = (unsigned char*)void_dst;
149 const unsigned char* src = (const unsigned char*)void_src;
150 unsigned count;
152 assert(height >= 2);
154 count = height;
156 stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
158 dst = SCDST(2);
160 count -= 2;
161 while (count) {
162 stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
164 dst = SCDST(2);
165 src = SCSRC(1);
167 --count;
170 stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);
172 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
173 scale2x_mmx_emms();
174 #endif
178 * Apply the Scale2x3 effect on a bitmap.
179 * The destination bitmap is filled with the scaled version of the source bitmap.
180 * The source bitmap isn't modified.
181 * The destination bitmap must be manually allocated before calling the function,
182 * note that the resulting size is exactly 2x3 times the size of the source bitmap.
183 * \param void_dst Pointer at the first pixel of the destination bitmap.
184 * \param dst_slice Size in bytes of a destination bitmap row.
185 * \param void_src Pointer at the first pixel of the source bitmap.
186 * \param src_slice Size in bytes of a source bitmap row.
187 * \param pixel Bytes per pixel of the source and destination bitmap.
188 * \param width Horizontal size in pixels of the source bitmap.
189 * \param height Vertical size in pixels of the source bitmap.
191 static void scale2x3(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
193 unsigned char* dst = (unsigned char*)void_dst;
194 const unsigned char* src = (const unsigned char*)void_src;
195 unsigned count;
197 assert(height >= 2);
199 count = height;
201 stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
203 dst = SCDST(3);
205 count -= 2;
206 while (count) {
207 stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
209 dst = SCDST(3);
210 src = SCSRC(1);
212 --count;
215 stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);
217 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
218 scale2x_mmx_emms();
219 #endif
223 * Apply the Scale2x4 effect on a bitmap.
224 * The destination bitmap is filled with the scaled version of the source bitmap.
225 * The source bitmap isn't modified.
226 * The destination bitmap must be manually allocated before calling the function,
227 * note that the resulting size is exactly 2x4 times the size of the source bitmap.
228 * \param void_dst Pointer at the first pixel of the destination bitmap.
229 * \param dst_slice Size in bytes of a destination bitmap row.
230 * \param void_src Pointer at the first pixel of the source bitmap.
231 * \param src_slice Size in bytes of a source bitmap row.
232 * \param pixel Bytes per pixel of the source and destination bitmap.
233 * \param width Horizontal size in pixels of the source bitmap.
234 * \param height Vertical size in pixels of the source bitmap.
236 static void scale2x4(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
238 unsigned char* dst = (unsigned char*)void_dst;
239 const unsigned char* src = (const unsigned char*)void_src;
240 unsigned count;
242 assert(height >= 2);
244 count = height;
246 stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
248 dst = SCDST(4);
250 count -= 2;
251 while (count) {
252 stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
254 dst = SCDST(4);
255 src = SCSRC(1);
257 --count;
260 stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);
262 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
263 scale2x_mmx_emms();
264 #endif
268 * Apply the Scale3x effect on a bitmap.
269 * The destination bitmap is filled with the scaled version of the source bitmap.
270 * The source bitmap isn't modified.
271 * The destination bitmap must be manually allocated before calling the function,
272 * note that the resulting size is exactly 3x3 times the size of the source bitmap.
273 * \param void_dst Pointer at the first pixel of the destination bitmap.
274 * \param dst_slice Size in bytes of a destination bitmap row.
275 * \param void_src Pointer at the first pixel of the source bitmap.
276 * \param src_slice Size in bytes of a source bitmap row.
277 * \param pixel Bytes per pixel of the source and destination bitmap.
278 * \param width Horizontal size in pixels of the source bitmap.
279 * \param height Vertical size in pixels of the source bitmap.
281 static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
283 unsigned char* dst = (unsigned char*)void_dst;
284 const unsigned char* src = (const unsigned char*)void_src;
285 unsigned count;
287 assert(height >= 2);
289 count = height;
291 stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
293 dst = SCDST(3);
295 count -= 2;
296 while (count) {
297 stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
299 dst = SCDST(3);
300 src = SCSRC(1);
302 --count;
305 stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(1), pixel, width);
309 * Apply the Scale4x effect on a bitmap.
310 * The destination bitmap is filled with the scaled version of the source bitmap.
311 * The source bitmap isn't modified.
312 * The destination bitmap must be manually allocated before calling the function,
313 * note that the resulting size is exactly 4x4 times the size of the source bitmap.
314 * \note This function requires also a small buffer bitmap used internally to store
315 * intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,
316 * and a vertical size of 6 rows. The memory of this buffer must not be allocated
317 * in video memory because it's also read and not only written. Generally
318 * a heap (malloc) or a stack (alloca) buffer is the best choice.
319 * \param void_dst Pointer at the first pixel of the destination bitmap.
320 * \param dst_slice Size in bytes of a destination bitmap row.
321 * \param void_mid Pointer at the first pixel of the buffer bitmap.
322 * \param mid_slice Size in bytes of a buffer bitmap row.
323 * \param void_src Pointer at the first pixel of the source bitmap.
324 * \param src_slice Size in bytes of a source bitmap row.
325 * \param pixel Bytes per pixel of the source and destination bitmap.
326 * \param width Horizontal size in pixels of the source bitmap.
327 * \param height Vertical size in pixels of the source bitmap.
329 static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
331 unsigned char* dst = (unsigned char*)void_dst;
332 const unsigned char* src = (const unsigned char*)void_src;
333 unsigned count;
334 unsigned char* mid[6];
336 assert(height >= 4);
338 count = height;
340 /* set the 6 buffer pointers */
341 mid[0] = (unsigned char*)void_mid;
342 mid[1] = mid[0] + mid_slice;
343 mid[2] = mid[1] + mid_slice;
344 mid[3] = mid[2] + mid_slice;
345 mid[4] = mid[3] + mid_slice;
346 mid[5] = mid[4] + mid_slice;
348 stage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
349 stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
350 stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width);
351 stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width);
353 dst = SCDST(4);
355 stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width);
357 dst = SCDST(4);
359 count -= 4;
360 while (count) {
361 unsigned char* tmp;
363 stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);
364 stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
366 dst = SCDST(4);
367 src = SCSRC(1);
369 tmp = SCMID(0); /* shift by 2 position */
370 SCMID(0) = SCMID(2);
371 SCMID(2) = SCMID(4);
372 SCMID(4) = tmp;
373 tmp = SCMID(1);
374 SCMID(1) = SCMID(3);
375 SCMID(3) = SCMID(5);
376 SCMID(5) = tmp;
378 --count;
381 stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width);
382 stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
384 dst = SCDST(4);
386 stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width);
388 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
389 scale2x_mmx_emms();
390 #endif
394 * Apply the Scale4x effect on a bitmap.
395 * The destination bitmap is filled with the scaled version of the source bitmap.
396 * The source bitmap isn't modified.
397 * The destination bitmap must be manually allocated before calling the function,
398 * note that the resulting size is exactly 4x4 times the size of the source bitmap.
399 * \note This function operates like ::scale4x_buf() but the intermediate buffer is
400 * automatically allocated in the stack.
401 * \param void_dst Pointer at the first pixel of the destination bitmap.
402 * \param dst_slice Size in bytes of a destination bitmap row.
403 * \param void_src Pointer at the first pixel of the source bitmap.
404 * \param src_slice Size in bytes of a source bitmap row.
405 * \param pixel Bytes per pixel of the source and destination bitmap.
406 * \param width Horizontal size in pixels of the source bitmap.
407 * \param height Vertical size in pixels of the source bitmap.
409 static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
411 unsigned mid_slice;
412 void* mid;
414 mid_slice = 2 * pixel * width; /* required space for 1 row buffer */
416 mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */
418 #if HAVE_ALLOCA
419 mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */
421 assert(mid != 0); /* alloca should never fails */
422 #else
423 mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */
425 if (!mid)
426 return;
427 #endif
429 scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);
431 #if !HAVE_ALLOCA
432 free(mid);
433 #endif
437 * Check if the scale implementation is applicable at the given arguments.
438 * \param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4.
439 * \param pixel Bytes per pixel of the source and destination bitmap.
440 * \param width Horizontal size in pixels of the source bitmap.
441 * \param height Vertical size in pixels of the source bitmap.
442 * \return
443 * - -1 on precondition violated.
444 * - 0 on success.
446 int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height)
448 if (pixel != 1 && pixel != 2 && pixel != 4)
449 return -1;
451 switch (scale) {
452 case 202 :
453 case 203 :
454 case 204 :
455 case 2 :
456 case 303 :
457 case 3 :
458 if (height < 2)
459 return -1;
460 break;
461 case 404 :
462 case 4 :
463 if (height < 4)
464 return -1;
465 break;
466 default:
467 return -1;
470 if (width < 2)
471 return -1;
473 return 0;
477 * Apply the Scale effect on a bitmap.
478 * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().
479 * \param scale Scale factor. 2, 203 (fox 2x3), 204 (for 2x4), 3 or 4.
480 * \param void_dst Pointer at the first pixel of the destination bitmap.
481 * \param dst_slice Size in bytes of a destination bitmap row.
482 * \param void_src Pointer at the first pixel of the source bitmap.
483 * \param src_slice Size in bytes of a source bitmap row.
484 * \param pixel Bytes per pixel of the source and destination bitmap.
485 * \param width Horizontal size in pixels of the source bitmap.
486 * \param height Vertical size in pixels of the source bitmap.
488 void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
490 switch (scale) {
491 case 202 :
492 case 2 :
493 scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
494 break;
495 case 203 :
496 scale2x3(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
497 break;
498 case 204 :
499 scale2x4(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
500 break;
501 case 303 :
502 case 3 :
503 scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
504 break;
505 case 404 :
506 case 4 :
507 scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
508 break;