|
|
1.1 root 1: /*
2: * This file is part of the Scale2x project.
3: *
4: * Copyright (C) 2001-2003 Andrea Mazzoleni
5: *
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.
10: *
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.
15: *
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.
19: */
20:
21: /*
22: * This file contains an example implementation of the Scale effect
23: * applyed to a generic bitmap.
24: *
25: * You can find an high level description of the effect at :
26: *
27: * http://scale2x.sourceforge.net/
28: *
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.
34: */
35:
36: #if HAVE_CONFIG_H
37: #include <config.h>
38: #endif
39:
40: #include "scale2x.h"
41: #include "scale3x.h"
42:
43: #if HAVE_ALLOCA_H
44: #include <alloca.h>
45: #endif
46:
47: #include <assert.h>
48: #include <stdlib.h>
49:
50: /**
51: * Apply the Scale2x effect on a group of rows. Used internally.
52: */
53: static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
54: {
55: switch (pixel) {
56: #if defined(__GNUC__) && defined(__i386__)
57: case 1 : scale2x_8_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
58: case 2 : scale2x_16_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
59: case 4 : scale2x_32_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
60: #else
61: case 1 : scale2x_8_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
62: case 2 : scale2x_16_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
63: case 4 : scale2x_32_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
64: #endif
65: }
66: }
67:
68: /**
69: * Apply the Scale3x effect on a group of rows. Used internally.
70: */
71: 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)
72: {
73: switch (pixel) {
74: case 1 : scale3x_8_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
75: case 2 : scale3x_16_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
76: case 4 : scale3x_32_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
77: }
78: }
79:
80: /**
81: * Apply the Scale4x effect on a group of rows. Used internally.
82: */
83: 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)
84: {
85: stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);
86: stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);
87: }
88:
89: #define SCDST(i) (dst+(i)*dst_slice)
90: #define SCSRC(i) (src+(i)*src_slice)
91: #define SCMID(i) (mid[(i)])
92:
93: /**
94: * Apply the Scale2x effect on a bitmap.
95: * The destination bitmap is filled with the scaled version of the source bitmap.
96: * The source bitmap isn't modified.
97: * The destination bitmap must be manually allocated before calling the function,
98: * note that the resulting size is exactly 2x2 times the size of the source bitmap.
99: * \param void_dst Pointer at the first pixel of the destination bitmap.
100: * \param dst_slice Size in bytes of a destination bitmap row.
101: * \param void_src Pointer at the first pixel of the source bitmap.
102: * \param src_slice Size in bytes of a source bitmap row.
103: * \param pixel Bytes per pixel of the source and destination bitmap.
104: * \param width Horizontal size in pixels of the source bitmap.
105: * \param height Vertical size in pixels of the source bitmap.
106: */
107: static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
108: {
109: unsigned char* dst = (unsigned char*)void_dst;
110: const unsigned char* src = (unsigned char*)void_src;
111: unsigned count;
112:
113: assert(height >= 2);
114:
115: count = height;
116:
117: stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
118:
119: dst = SCDST(2);
120:
121: count -= 2;
122: while (count) {
123: stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
124:
125: dst = SCDST(2);
126: src = SCSRC(1);
127:
128: --count;
129: }
130:
131: stage_scale2x(SCDST(0), SCDST(1), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width);
132:
133: #if defined(__GNUC__) && defined(__i386__)
134: scale2x_mmx_emms();
135: #endif
136: }
137:
138: /**
139: * Apply the Scale32x effect on a bitmap.
140: * The destination bitmap is filled with the scaled version of the source bitmap.
141: * The source bitmap isn't modified.
142: * The destination bitmap must be manually allocated before calling the function,
143: * note that the resulting size is exactly 3x3 times the size of the source bitmap.
144: * \param void_dst Pointer at the first pixel of the destination bitmap.
145: * \param dst_slice Size in bytes of a destination bitmap row.
146: * \param void_src Pointer at the first pixel of the source bitmap.
147: * \param src_slice Size in bytes of a source bitmap row.
148: * \param pixel Bytes per pixel of the source and destination bitmap.
149: * \param width Horizontal size in pixels of the source bitmap.
150: * \param height Vertical size in pixels of the source bitmap.
151: */
152: static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
153: {
154: unsigned char* dst = (unsigned char*)void_dst;
155: const unsigned char* src = (unsigned char*)void_src;
156: unsigned count;
157:
158: assert(height >= 2);
159:
160: count = height;
161:
162: stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
163:
164: dst = SCDST(3);
165:
166: count -= 2;
167: while (count) {
168: stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
169:
170: dst = SCDST(3);
171: src = SCSRC(1);
172:
173: --count;
174: }
175:
176: stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width);
177: }
178:
179: /**
180: * Apply the Scale4x effect on a bitmap.
181: * The destination bitmap is filled with the scaled version of the source bitmap.
182: * The source bitmap isn't modified.
183: * The destination bitmap must be manually allocated before calling the function,
184: * note that the resulting size is exactly 4x4 times the size of the source bitmap.
185: * \note This function requires also a small buffer bitmap used internally to store
186: * intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,
187: * and a vertical size of 6 rows. The memory of this buffer must not be allocated
188: * in video memory because it's also read and not only written. Generally
189: * a heap (malloc) or a stack (alloca) buffer is the best choices.
190: * \param void_dst Pointer at the first pixel of the destination bitmap.
191: * \param dst_slice Size in bytes of a destination bitmap row.
192: * \param void_mid Pointer at the first pixel of the buffer bitmap.
193: * \param mid_slice Size in bytes of a buffer bitmap row.
194: * \param void_src Pointer at the first pixel of the source bitmap.
195: * \param src_slice Size in bytes of a source bitmap row.
196: * \param pixel Bytes per pixel of the source and destination bitmap.
197: * \param width Horizontal size in pixels of the source bitmap.
198: * \param height Vertical size in pixels of the source bitmap.
199: */
200: 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)
201: {
202: unsigned char* dst = (unsigned char*)void_dst;
203: const unsigned char* src = (unsigned char*)void_src;
204: unsigned count;
205: unsigned char* mid[6];
206:
207: assert(height >= 4);
208:
209: count = height;
210:
211: /* set the 6 buffer pointers */
212: mid[0] = (unsigned char*)void_mid;
213: mid[1] = mid[0] + mid_slice;
214: mid[2] = mid[1] + mid_slice;
215: mid[3] = mid[2] + mid_slice;
216: mid[4] = mid[3] + mid_slice;
217: mid[5] = mid[4] + mid_slice;
218:
219: stage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
220: stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
221: stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width);
222: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width);
223:
224: dst = SCDST(4);
225:
226: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width);
227:
228: dst = SCDST(4);
229:
230: count -= 4;
231: while (count) {
232: unsigned char* tmp;
233:
234: stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);
235: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
236:
237: dst = SCDST(4);
238: src = SCSRC(1);
239:
240: tmp = SCMID(0); /* shift by 2 position */
241: SCMID(0) = SCMID(2);
242: SCMID(2) = SCMID(4);
243: SCMID(4) = tmp;
244: tmp = SCMID(1);
245: SCMID(1) = SCMID(3);
246: SCMID(3) = SCMID(5);
247: SCMID(5) = tmp;
248:
249: --count;
250: }
251:
252: stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width);
253: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
254:
255: dst = SCDST(4);
256:
257: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width);
258:
259: #if defined(__GNUC__) && defined(__i386__)
260: scale2x_mmx_emms();
261: #endif
262: }
263:
264: /**
265: * Apply the Scale4x effect on a bitmap.
266: * The destination bitmap is filled with the scaled version of the source bitmap.
267: * The source bitmap isn't modified.
268: * The destination bitmap must be manually allocated before calling the function,
269: * note that the resulting size is exactly 4x4 times the size of the source bitmap.
270: * \note This function operates like ::scale4x_buf() but the intermediate buffer is
271: * automatically allocated in the stack.
272: * \param void_dst Pointer at the first pixel of the destination bitmap.
273: * \param dst_slice Size in bytes of a destination bitmap row.
274: * \param void_src Pointer at the first pixel of the source bitmap.
275: * \param src_slice Size in bytes of a source bitmap row.
276: * \param pixel Bytes per pixel of the source and destination bitmap.
277: * \param width Horizontal size in pixels of the source bitmap.
278: * \param height Vertical size in pixels of the source bitmap.
279: */
280: static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
281: {
282: unsigned mid_slice;
283: void* mid;
284:
285: mid_slice = 2 * pixel * width; /* required space for 1 row buffer */
286:
287: mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */
288:
289: #if HAVE_ALLOCA
290: mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */
291:
292: assert(mid != 0); /* alloca should never fails */
293: #else
294: mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */
295:
296: if (!mid)
297: return;
298: #endif
299:
300: scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);
301:
302: #if !HAVE_ALLOCA
303: free(mid);
304: #endif
305: }
306:
307: /**
308: * Check if the scale implementation is applicable at the given arguments.
309: * \param scale Scale factor. 2, 3 or 4.
310: * \param src_slice Size in bytes of a source bitmap row.
311: * \param pixel Bytes per pixel of the source and destination bitmap.
312: * \param width Horizontal size in pixels of the source bitmap.
313: * \return
314: * - -1 on precondition violated.
315: * - 0 on success.
316: */
317: int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height)
318: {
319: if (scale != 2 && scale != 3 && scale != 4)
320: return -1;
321:
322: if (pixel != 1 && pixel != 2 && pixel != 4)
323: return -1;
324:
325: switch (scale) {
326: case 2 :
327: case 3 :
328: if (height < 2)
329: return -1;
330: case 4 :
331: if (height < 4)
332: return -1;
333: }
334:
335: #if defined(__GNUC__) && defined(__i386__)
336: switch (scale) {
337: case 2 :
338: case 4 :
339: if (width < (16 / pixel))
340: return -1;
341: if (width % (8 / pixel) != 0)
342: return -1;
343: case 3 :
344: if (width < 2)
345: return -1;
346: }
347: #else
348: if (width < 2)
349: return -1;
350: #endif
351:
352: return 0;
353: }
354:
355: /**
356: * Apply the Scale effect on a bitmap.
357: * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().
358: * \param scale Scale factor. 2, 3 or 4.
359: * \param void_dst Pointer at the first pixel of the destination bitmap.
360: * \param dst_slice Size in bytes of a destination bitmap row.
361: * \param void_src Pointer at the first pixel of the source bitmap.
362: * \param src_slice Size in bytes of a source bitmap row.
363: * \param pixel Bytes per pixel of the source and destination bitmap.
364: * \param width Horizontal size in pixels of the source bitmap.
365: * \param height Vertical size in pixels of the source bitmap.
366: */
367: void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
368: {
369: switch (scale) {
370: case 2 : scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break;
371: case 3 : scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break;
372: case 4 : scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break;
373: }
374: }
375:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.