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 a C implementation of the Scale3x effect.
23  *
24  * You can find an high level description of the effect at :
25  *
26  * http://scale2x.sourceforge.net/
27  *
28  * Alternatively at the previous license terms, you are allowed to use this
29  * code in your program with these conditions:
30  * - the program is not used in commercial activities.
31  * - the whole source code of the program is released with the binary.
32  * - derivative works of the program are allowed.
33  */
34 
35 #ifndef __SCALE3X_H
36 #define __SCALE3X_H
37 
38 #include <assert.h>
39 
40 /***************************************************************************/
41 /* Basic types */
42 
43 typedef unsigned char scale3x_Uint8;
44 typedef unsigned short scale3x_Uint16;
45 typedef unsigned scale3x_Uint32;
46 
47 /***************************************************************************/
48 /* Scale3x C implementation */
49 
scale3x_8_def_single(scale3x_Uint8 * dst,const scale3x_Uint8 * src0,const scale3x_Uint8 * src1,const scale3x_Uint8 * src2,unsigned count)50 static void scale3x_8_def_single(scale3x_Uint8* dst, const scale3x_Uint8* src0, const scale3x_Uint8* src1, const scale3x_Uint8* src2, unsigned count)
51 {
52 	assert(count >= 2);
53 
54 	/* first pixel */
55 	dst[0] = src1[0];
56 	dst[1] = src1[0];
57 	if (src1[1] == src0[0] && src2[0] != src0[0])
58 		dst[2] = src0[0];
59 	else
60 		dst[2] = src1[0];
61 	++src0;
62 	++src1;
63 	++src2;
64 	dst += 3;
65 
66 	/* central pixels */
67 	count -= 2;
68 	while (count) {
69 		if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0])
70 			dst[0] = src0[0];
71 		else
72 			dst[0] = src1[0];
73 		dst[1] = src1[0];
74 		if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0])
75 			dst[2] = src0[0];
76 		else
77 			dst[2] = src1[0];
78 
79 		++src0;
80 		++src1;
81 		++src2;
82 
83 		dst += 3;
84 		--count;
85 	}
86 
87 	/* last pixel */
88 	if (src1[-1] == src0[0] && src2[0] != src0[0])
89 		dst[0] = src0[0];
90 	else
91 		dst[0] = src1[0];
92 	dst[1] = src1[0];
93 	dst[2] = src1[0];
94 }
95 
scale3x_8_def_fill(scale3x_Uint8 * dst,const scale3x_Uint8 * src,unsigned count)96 static void scale3x_8_def_fill(scale3x_Uint8* dst, const scale3x_Uint8* src, unsigned count)
97 {
98 	while (count) {
99 		dst[0] = src[0];
100 		dst[1] = src[0];
101 		dst[2] = src[0];
102 
103 		++src;
104 		dst += 3;
105 		--count;
106 	}
107 }
108 
scale3x_16_def_single(scale3x_Uint16 * dst,const scale3x_Uint16 * src0,const scale3x_Uint16 * src1,const scale3x_Uint16 * src2,unsigned count)109 static void scale3x_16_def_single(scale3x_Uint16* dst, const scale3x_Uint16* src0, const scale3x_Uint16* src1, const scale3x_Uint16* src2, unsigned count)
110 {
111 	assert(count >= 2);
112 
113 	/* first pixel */
114 	dst[0] = src1[0];
115 	dst[1] = src1[0];
116 	if (src1[1] == src0[0] && src2[0] != src0[0])
117 		dst[2] = src0[0];
118 	else
119 		dst[2] = src1[0];
120 	++src0;
121 	++src1;
122 	++src2;
123 	dst += 3;
124 
125 	/* central pixels */
126 	count -= 2;
127 	while (count) {
128 		if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0])
129 			dst[0] = src0[0];
130 		else
131 			dst[0] = src1[0];
132 		dst[1] = src1[0];
133 		if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0])
134 			dst[2] = src0[0];
135 		else
136 			dst[2] = src1[0];
137 
138 		++src0;
139 		++src1;
140 		++src2;
141 
142 		dst += 3;
143 		--count;
144 	}
145 
146 	/* last pixel */
147 	if (src1[-1] == src0[0] && src2[0] != src0[0])
148 		dst[0] = src0[0];
149 	else
150 		dst[0] = src1[0];
151 	dst[1] = src1[0];
152 	dst[2] = src1[0];
153 }
154 
scale3x_16_def_fill(scale3x_Uint16 * dst,const scale3x_Uint16 * src,unsigned count)155 static void scale3x_16_def_fill(scale3x_Uint16* dst, const scale3x_Uint16* src, unsigned count)
156 {
157 	while (count) {
158 		dst[0] = src[0];
159 		dst[1] = src[0];
160 		dst[2] = src[0];
161 
162 		++src;
163 		dst += 3;
164 		--count;
165 	}
166 }
167 
scale3x_32_def_single(scale3x_Uint32 * dst,const scale3x_Uint32 * src0,const scale3x_Uint32 * src1,const scale3x_Uint32 * src2,unsigned count)168 static void scale3x_32_def_single(scale3x_Uint32* dst, const scale3x_Uint32* src0, const scale3x_Uint32* src1, const scale3x_Uint32* src2, unsigned count)
169 {
170 	assert(count >= 2);
171 
172 	/* first pixel */
173 	dst[0] = src1[0];
174 	dst[1] = src1[0];
175 	if (src1[1] == src0[0] && src2[0] != src0[0])
176 		dst[2] = src0[0];
177 	else
178 		dst[2] = src1[0];
179 	++src0;
180 	++src1;
181 	++src2;
182 	dst += 3;
183 
184 	/* central pixels */
185 	count -= 2;
186 	while (count) {
187 		if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0])
188 			dst[0] = src0[0];
189 		else
190 			dst[0] = src1[0];
191 		dst[1] = src1[0];
192 		if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0])
193 			dst[2] = src0[0];
194 		else
195 			dst[2] = src1[0];
196 
197 		++src0;
198 		++src1;
199 		++src2;
200 
201 		dst += 3;
202 		--count;
203 	}
204 
205 	/* last pixel */
206 	if (src1[-1] == src0[0] && src2[0] != src0[0])
207 		dst[0] = src0[0];
208 	else
209 		dst[0] = src1[0];
210 	dst[1] = src1[0];
211 	dst[2] = src1[0];
212 }
213 
scale3x_32_def_fill(scale3x_Uint32 * dst,const scale3x_Uint32 * src,unsigned count)214 static void scale3x_32_def_fill(scale3x_Uint32* dst, const scale3x_Uint32* src, unsigned count)
215 {
216 	while (count) {
217 		dst[0] = src[0];
218 		dst[1] = src[0];
219 		dst[2] = src[0];
220 
221 		++src;
222 		dst += 3;
223 		--count;
224 	}
225 }
226 
227 /**
228  * Scale by a factor of 3 a row of pixels of 8 bits.
229  * The function is implemented in C.
230  * The pixels over the left and right borders are assumed of the same color of
231  * the pixels on the border.
232  * \param src0 Pointer at the first pixel of the previous row.
233  * \param src1 Pointer at the first pixel of the current row.
234  * \param src2 Pointer at the first pixel of the next row.
235  * \param count Length in pixels of the src0, src1 and src2 rows.
236  * It must be at least 2.
237  * \param dst0 First destination row, triple length in pixels.
238  * \param dst1 Second destination row, triple length in pixels.
239  * \param dst2 Third destination row, triple length in pixels.
240  */
scale3x_8_def(scale3x_Uint8 * dst0,scale3x_Uint8 * dst1,scale3x_Uint8 * dst2,const scale3x_Uint8 * src0,const scale3x_Uint8 * src1,const scale3x_Uint8 * src2,unsigned count)241 static inline void scale3x_8_def(scale3x_Uint8* dst0, scale3x_Uint8* dst1, scale3x_Uint8* dst2, const scale3x_Uint8* src0, const scale3x_Uint8* src1, const scale3x_Uint8* src2, unsigned count)
242 {
243 	assert(count >= 2);
244 
245 	scale3x_8_def_single(dst0, src0, src1, src2, count);
246 	scale3x_8_def_fill(dst1, src1, count);
247 	scale3x_8_def_single(dst2, src2, src1, src0, count);
248 }
249 
250 /**
251  * Scale by a factor of 3 a row of pixels of 16 bits.
252  * This function operates like scale3x_8_def() but for 16 bits pixels.
253  * \param src0 Pointer at the first pixel of the previous row.
254  * \param src1 Pointer at the first pixel of the current row.
255  * \param src2 Pointer at the first pixel of the next row.
256  * \param count Length in pixels of the src0, src1 and src2 rows.
257  * It must be at least 2.
258  * \param dst0 First destination row, triple length in pixels.
259  * \param dst1 Second destination row, triple length in pixels.
260  * \param dst2 Third destination row, triple length in pixels.
261  */
scale3x_16_def(scale3x_Uint16 * dst0,scale3x_Uint16 * dst1,scale3x_Uint16 * dst2,const scale3x_Uint16 * src0,const scale3x_Uint16 * src1,const scale3x_Uint16 * src2,unsigned count)262 static inline void scale3x_16_def(scale3x_Uint16* dst0, scale3x_Uint16* dst1, scale3x_Uint16* dst2, const scale3x_Uint16* src0, const scale3x_Uint16* src1, const scale3x_Uint16* src2, unsigned count)
263 {
264 	assert(count >= 2);
265 
266 	scale3x_16_def_single(dst0, src0, src1, src2, count);
267 	scale3x_16_def_fill(dst1, src1, count);
268 	scale3x_16_def_single(dst2, src2, src1, src0, count);
269 }
270 
271 /**
272  * Scale by a factor of 3 a row of pixels of 32 bits.
273  * This function operates like scale3x_8_def() but for 32 bits pixels.
274  * \param src0 Pointer at the first pixel of the previous row.
275  * \param src1 Pointer at the first pixel of the current row.
276  * \param src2 Pointer at the first pixel of the next row.
277  * \param count Length in pixels of the src0, src1 and src2 rows.
278  * It must be at least 2.
279  * \param dst0 First destination row, triple length in pixels.
280  * \param dst1 Second destination row, triple length in pixels.
281  * \param dst2 Third destination row, triple length in pixels.
282  */
scale3x_32_def(scale3x_Uint32 * dst0,scale3x_Uint32 * dst1,scale3x_Uint32 * dst2,const scale3x_Uint32 * src0,const scale3x_Uint32 * src1,const scale3x_Uint32 * src2,unsigned count)283 static inline void scale3x_32_def(scale3x_Uint32* dst0, scale3x_Uint32* dst1, scale3x_Uint32* dst2, const scale3x_Uint32* src0, const scale3x_Uint32* src1, const scale3x_Uint32* src2, unsigned count)
284 {
285 	assert(count >= 2);
286 
287 	scale3x_32_def_single(dst0, src0, src1, src2, count);
288 	scale3x_32_def_fill(dst1, src1, count);
289 	scale3x_32_def_single(dst2, src2, src1, src0, count);
290 }
291 
292 #endif
293