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