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.
50 #define SSDST(bits, num) (scale2x_uint##bits *)dst##num
51 #define SSSRC(bits, num) (const scale2x_uint##bits *)src##num
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
)
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;
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;
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
)
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;
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;
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
)
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;
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;
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
)
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
;
156 stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel
, width
);
162 stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel
, width
);
170 stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(1), pixel
, width
);
172 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
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
;
201 stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel
, width
);
207 stage_scale2x3(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel
, width
);
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__))
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
;
246 stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(0), SCSRC(1), pixel
, width
);
252 stage_scale2x4(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCSRC(0), SCSRC(1), SCSRC(2), pixel
, width
);
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__))
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
;
291 stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel
, width
);
297 stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel
, width
);
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
;
334 unsigned char* mid
[6];
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
);
355 stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel
, width
);
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
);
369 tmp
= SCMID(0); /* shift by 2 position */
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
);
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__))
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
)
414 mid_slice
= 2 * pixel
* width
; /* required space for 1 row buffer */
416 mid_slice
= (mid_slice
+ 0x7) & ~0x7; /* align to 8 bytes */
419 mid
= alloca(6 * mid_slice
); /* allocate space for 6 row buffers */
421 assert(mid
!= 0); /* alloca should never fails */
423 mid
= malloc(6 * mid_slice
); /* allocate space for 6 row buffers */
429 scale4x_buf(void_dst
, dst_slice
, mid
, mid_slice
, void_src
, src_slice
, pixel
, width
, height
);
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.
443 * - -1 on precondition violated.
446 int scale_precondition(unsigned scale
, unsigned pixel
, unsigned width
, unsigned height
)
448 if (pixel
!= 1 && pixel
!= 2 && pixel
!= 4)
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
)
493 scale2x(void_dst
, dst_slice
, void_src
, src_slice
, pixel
, width
, height
);
496 scale2x3(void_dst
, dst_slice
, void_src
, src_slice
, pixel
, width
, height
);
499 scale2x4(void_dst
, dst_slice
, void_src
, src_slice
, pixel
, width
, height
);
503 scale3x(void_dst
, dst_slice
, void_src
, src_slice
, pixel
, width
, height
);
507 scale4x(void_dst
, dst_slice
, void_src
, src_slice
, pixel
, width
, height
);