1 /*
2 * This file is part of the Scale2x project.
3 *
4 * Copyright (C) 2001, 2002, 2003, 2004 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 and MMX implementation of the Scale2x 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 #include "scale3x.h"
36
37 #include <assert.h>
38
39 #if (_MSC_VER >= 1400)
40 #define restrict __restrict
41 #else
42 #define restrict
43 #endif
44
45 #ifdef _WIN32
46 #ifndef __GNUC__
47 #pragma optimize("a", on)
48 #endif
49 #endif
50
51
52 /***************************************************************************/
53 /* Scale3x C implementation */
54
55 /**
56 * Define the macro USE_SCALE_RANDOMWRITE to enable
57 * an optimized version which writes memory in random order.
58 * This version is a little faster if you write in system memory.
59 * But it's a lot slower if you write in video memory.
60 * So, enable it only if you are sure to never write directly in video memory.
61 */
62 /* #define USE_SCALE_RANDOMWRITE */
63
scale3x_8_def_whole(scale3x_uint8 * restrict dst0,scale3x_uint8 * restrict dst1,scale3x_uint8 * restrict dst2,const scale3x_uint8 * restrict src0,const scale3x_uint8 * restrict src1,const scale3x_uint8 * restrict src2,unsigned count)64 static inline void scale3x_8_def_whole(scale3x_uint8* restrict dst0, scale3x_uint8* restrict dst1, scale3x_uint8* restrict dst2, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count)
65 {
66 assert(count >= 2);
67
68 /* first pixel */
69 if (src0[0] != src2[0] && src1[0] != src1[1]) {
70 dst0[0] = src1[0];
71 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
72 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
73 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
74 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
75 dst1[1] = src1[0];
76 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
77 dst2[0] = src1[0];
78 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
79 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
80 } else {
81 dst0[0] = src1[0];
82 dst0[1] = src1[0];
83 dst0[2] = src1[0];
84 dst1[0] = src1[0];
85 dst1[1] = src1[0];
86 dst1[2] = src1[0];
87 dst2[0] = src1[0];
88 dst2[1] = src1[0];
89 dst2[2] = src1[0];
90 }
91 ++src0;
92 ++src1;
93 ++src2;
94 dst0 += 3;
95 dst1 += 3;
96 dst2 += 3;
97
98 /* central pixels */
99 count -= 2;
100 while (count) {
101 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
102 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
103 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
104 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
105 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
106 dst1[1] = src1[0];
107 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
108 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
109 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
110 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
111 } else {
112 dst0[0] = src1[0];
113 dst0[1] = src1[0];
114 dst0[2] = src1[0];
115 dst1[0] = src1[0];
116 dst1[1] = src1[0];
117 dst1[2] = src1[0];
118 dst2[0] = src1[0];
119 dst2[1] = src1[0];
120 dst2[2] = src1[0];
121 }
122
123 ++src0;
124 ++src1;
125 ++src2;
126 dst0 += 3;
127 dst1 += 3;
128 dst2 += 3;
129 --count;
130 }
131
132 /* last pixel */
133 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
134 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
135 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
136 dst0[2] = src1[0];
137 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
138 dst1[1] = src1[0];
139 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
140 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
141 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
142 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
143 dst2[2] = src1[0];
144 } else {
145 dst0[0] = src1[0];
146 dst0[1] = src1[0];
147 dst0[2] = src1[0];
148 dst1[0] = src1[0];
149 dst1[1] = src1[0];
150 dst1[2] = src1[0];
151 dst2[0] = src1[0];
152 dst2[1] = src1[0];
153 dst2[2] = src1[0];
154 }
155 }
156
scale3x_8_def_border(scale3x_uint8 * restrict dst,const scale3x_uint8 * restrict src0,const scale3x_uint8 * restrict src1,const scale3x_uint8 * restrict src2,unsigned count)157 static inline void scale3x_8_def_border(scale3x_uint8* restrict dst, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count)
158 {
159 assert(count >= 2);
160
161 /* first pixel */
162 if (src0[0] != src2[0] && src1[0] != src1[1]) {
163 dst[0] = src1[0];
164 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
165 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
166 } else {
167 dst[0] = src1[0];
168 dst[1] = src1[0];
169 dst[2] = src1[0];
170 }
171 ++src0;
172 ++src1;
173 ++src2;
174 dst += 3;
175
176 /* central pixels */
177 count -= 2;
178 while (count) {
179 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
180 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
181 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
182 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
183 } else {
184 dst[0] = src1[0];
185 dst[1] = src1[0];
186 dst[2] = src1[0];
187 }
188
189 ++src0;
190 ++src1;
191 ++src2;
192 dst += 3;
193 --count;
194 }
195
196 /* last pixel */
197 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
198 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
199 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
200 dst[2] = src1[0];
201 } else {
202 dst[0] = src1[0];
203 dst[1] = src1[0];
204 dst[2] = src1[0];
205 }
206 }
207
scale3x_8_def_center(scale3x_uint8 * restrict dst,const scale3x_uint8 * restrict src0,const scale3x_uint8 * restrict src1,const scale3x_uint8 * restrict src2,unsigned count)208 static inline void scale3x_8_def_center(scale3x_uint8* restrict dst, const scale3x_uint8* restrict src0, const scale3x_uint8* restrict src1, const scale3x_uint8* restrict src2, unsigned count)
209 {
210 assert(count >= 2);
211
212 /* first pixel */
213 if (src0[0] != src2[0] && src1[0] != src1[1]) {
214 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
215 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
216 dst[1] = src1[0];
217 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
218 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
219 } else {
220 dst[0] = src1[0];
221 dst[1] = src1[0];
222 dst[2] = src1[0];
223 }
224 ++src0;
225 ++src1;
226 ++src2;
227 dst += 3;
228
229 /* central pixels */
230 count -= 2;
231 while (count) {
232 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
233 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
234 dst[1] = src1[0];
235 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
236 } else {
237 dst[0] = src1[0];
238 dst[1] = src1[0];
239 dst[2] = src1[0];
240 }
241
242 ++src0;
243 ++src1;
244 ++src2;
245 dst += 3;
246 --count;
247 }
248
249 /* last pixel */
250 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
251 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
252 dst[1] = src1[0];
253 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
254 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
255 } else {
256 dst[0] = src1[0];
257 dst[1] = src1[0];
258 dst[2] = src1[0];
259 }
260 }
261
scale3x_16_def_whole(scale3x_uint16 * restrict dst0,scale3x_uint16 * restrict dst1,scale3x_uint16 * restrict dst2,const scale3x_uint16 * restrict src0,const scale3x_uint16 * restrict src1,const scale3x_uint16 * restrict src2,unsigned count)262 static inline void scale3x_16_def_whole(scale3x_uint16* restrict dst0, scale3x_uint16* restrict dst1, scale3x_uint16* restrict dst2, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count)
263 {
264 assert(count >= 2);
265
266 /* first pixel */
267 if (src0[0] != src2[0] && src1[0] != src1[1]) {
268 dst0[0] = src1[0];
269 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
270 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
271 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
272 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
273 dst1[1] = src1[0];
274 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
275 dst2[0] = src1[0];
276 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
277 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
278 } else {
279 dst0[0] = src1[0];
280 dst0[1] = src1[0];
281 dst0[2] = src1[0];
282 dst1[0] = src1[0];
283 dst1[1] = src1[0];
284 dst1[2] = src1[0];
285 dst2[0] = src1[0];
286 dst2[1] = src1[0];
287 dst2[2] = src1[0];
288 }
289 ++src0;
290 ++src1;
291 ++src2;
292 dst0 += 3;
293 dst1 += 3;
294 dst2 += 3;
295
296 /* central pixels */
297 count -= 2;
298 while (count) {
299 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
300 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
301 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
302 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
303 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
304 dst1[1] = src1[0];
305 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
306 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
307 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
308 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
309 } else {
310 dst0[0] = src1[0];
311 dst0[1] = src1[0];
312 dst0[2] = src1[0];
313 dst1[0] = src1[0];
314 dst1[1] = src1[0];
315 dst1[2] = src1[0];
316 dst2[0] = src1[0];
317 dst2[1] = src1[0];
318 dst2[2] = src1[0];
319 }
320
321 ++src0;
322 ++src1;
323 ++src2;
324 dst0 += 3;
325 dst1 += 3;
326 dst2 += 3;
327 --count;
328 }
329
330 /* last pixel */
331 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
332 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
333 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
334 dst0[2] = src1[0];
335 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
336 dst1[1] = src1[0];
337 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
338 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
339 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
340 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
341 dst2[2] = src1[0];
342 } else {
343 dst0[0] = src1[0];
344 dst0[1] = src1[0];
345 dst0[2] = src1[0];
346 dst1[0] = src1[0];
347 dst1[1] = src1[0];
348 dst1[2] = src1[0];
349 dst2[0] = src1[0];
350 dst2[1] = src1[0];
351 dst2[2] = src1[0];
352 }
353 }
354
scale3x_16_def_border(scale3x_uint16 * restrict dst,const scale3x_uint16 * restrict src0,const scale3x_uint16 * restrict src1,const scale3x_uint16 * restrict src2,unsigned count)355 static inline void scale3x_16_def_border(scale3x_uint16* restrict dst, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count)
356 {
357 assert(count >= 2);
358
359 /* first pixel */
360 if (src0[0] != src2[0] && src1[0] != src1[1]) {
361 dst[0] = src1[0];
362 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
363 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
364 } else {
365 dst[0] = src1[0];
366 dst[1] = src1[0];
367 dst[2] = src1[0];
368 }
369 ++src0;
370 ++src1;
371 ++src2;
372 dst += 3;
373
374 /* central pixels */
375 count -= 2;
376 while (count) {
377 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
378 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
379 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
380 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
381 } else {
382 dst[0] = src1[0];
383 dst[1] = src1[0];
384 dst[2] = src1[0];
385 }
386
387 ++src0;
388 ++src1;
389 ++src2;
390 dst += 3;
391 --count;
392 }
393
394 /* last pixel */
395 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
396 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
397 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
398 dst[2] = src1[0];
399 } else {
400 dst[0] = src1[0];
401 dst[1] = src1[0];
402 dst[2] = src1[0];
403 }
404 }
405
scale3x_16_def_center(scale3x_uint16 * restrict dst,const scale3x_uint16 * restrict src0,const scale3x_uint16 * restrict src1,const scale3x_uint16 * restrict src2,unsigned count)406 static inline void scale3x_16_def_center(scale3x_uint16* restrict dst, const scale3x_uint16* restrict src0, const scale3x_uint16* restrict src1, const scale3x_uint16* restrict src2, unsigned count)
407 {
408 assert(count >= 2);
409
410 /* first pixel */
411 if (src0[0] != src2[0] && src1[0] != src1[1]) {
412 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
413 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
414 dst[1] = src1[0];
415 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
416 } else {
417 dst[0] = src1[0];
418 dst[1] = src1[0];
419 dst[2] = src1[0];
420 }
421 ++src0;
422 ++src1;
423 ++src2;
424 dst += 3;
425
426 /* central pixels */
427 count -= 2;
428 while (count) {
429 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
430 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
431 dst[1] = src1[0];
432 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
433 } else {
434 dst[0] = src1[0];
435 dst[1] = src1[0];
436 dst[2] = src1[0];
437 }
438
439 ++src0;
440 ++src1;
441 ++src2;
442 dst += 3;
443 --count;
444 }
445
446 /* last pixel */
447 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
448 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
449 dst[1] = src1[0];
450 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
451 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
452 } else {
453 dst[0] = src1[0];
454 dst[1] = src1[0];
455 dst[2] = src1[0];
456 }
457 }
458
scale3x_32_def_whole(scale3x_uint32 * restrict dst0,scale3x_uint32 * restrict dst1,scale3x_uint32 * restrict dst2,const scale3x_uint32 * restrict src0,const scale3x_uint32 * restrict src1,const scale3x_uint32 * restrict src2,unsigned count)459 static inline void scale3x_32_def_whole(scale3x_uint32* restrict dst0, scale3x_uint32* restrict dst1, scale3x_uint32* restrict dst2, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count)
460 {
461 assert(count >= 2);
462
463 /* first pixel */
464 if (src0[0] != src2[0] && src1[0] != src1[1]) {
465 dst0[0] = src1[0];
466 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
467 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
468 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
469 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
470 dst1[1] = src1[0];
471 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
472 dst2[0] = src1[0];
473 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
474 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
475 } else {
476 dst0[0] = src1[0];
477 dst0[1] = src1[0];
478 dst0[2] = src1[0];
479 dst1[0] = src1[0];
480 dst1[1] = src1[0];
481 dst1[2] = src1[0];
482 dst2[0] = src1[0];
483 dst2[1] = src1[0];
484 dst2[2] = src1[0];
485 }
486 ++src0;
487 ++src1;
488 ++src2;
489 dst0 += 3;
490 dst1 += 3;
491 dst2 += 3;
492
493 /* central pixels */
494 count -= 2;
495 while (count) {
496 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
497 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
498 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
499 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
500 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
501 dst1[1] = src1[0];
502 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
503 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
504 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
505 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
506 } else {
507 dst0[0] = src1[0];
508 dst0[1] = src1[0];
509 dst0[2] = src1[0];
510 dst1[0] = src1[0];
511 dst1[1] = src1[0];
512 dst1[2] = src1[0];
513 dst2[0] = src1[0];
514 dst2[1] = src1[0];
515 dst2[2] = src1[0];
516 }
517
518 ++src0;
519 ++src1;
520 ++src2;
521 dst0 += 3;
522 dst1 += 3;
523 dst2 += 3;
524 --count;
525 }
526
527 /* last pixel */
528 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
529 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
530 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
531 dst0[2] = src1[0];
532 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
533 dst1[1] = src1[0];
534 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
535 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
536 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
537 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
538 dst2[2] = src1[0];
539 } else {
540 dst0[0] = src1[0];
541 dst0[1] = src1[0];
542 dst0[2] = src1[0];
543 dst1[0] = src1[0];
544 dst1[1] = src1[0];
545 dst1[2] = src1[0];
546 dst2[0] = src1[0];
547 dst2[1] = src1[0];
548 dst2[2] = src1[0];
549 }
550 }
551
scale3x_32_def_border(scale3x_uint32 * restrict dst,const scale3x_uint32 * restrict src0,const scale3x_uint32 * restrict src1,const scale3x_uint32 * restrict src2,unsigned count)552 static inline void scale3x_32_def_border(scale3x_uint32* restrict dst, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count)
553 {
554 assert(count >= 2);
555
556 /* first pixel */
557 if (src0[0] != src2[0] && src1[0] != src1[1]) {
558 dst[0] = src1[0];
559 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
560 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
561 } else {
562 dst[0] = src1[0];
563 dst[1] = src1[0];
564 dst[2] = src1[0];
565 }
566 ++src0;
567 ++src1;
568 ++src2;
569 dst += 3;
570
571 /* central pixels */
572 count -= 2;
573 while (count) {
574 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
575 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
576 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
577 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
578 } else {
579 dst[0] = src1[0];
580 dst[1] = src1[0];
581 dst[2] = src1[0];
582 }
583
584 ++src0;
585 ++src1;
586 ++src2;
587 dst += 3;
588 --count;
589 }
590
591 /* last pixel */
592 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
593 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
594 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
595 dst[2] = src1[0];
596 } else {
597 dst[0] = src1[0];
598 dst[1] = src1[0];
599 dst[2] = src1[0];
600 }
601 }
602
scale3x_32_def_center(scale3x_uint32 * restrict dst,const scale3x_uint32 * restrict src0,const scale3x_uint32 * restrict src1,const scale3x_uint32 * restrict src2,unsigned count)603 static inline void scale3x_32_def_center(scale3x_uint32* restrict dst, const scale3x_uint32* restrict src0, const scale3x_uint32* restrict src1, const scale3x_uint32* restrict src2, unsigned count)
604 {
605 assert(count >= 2);
606
607 /* first pixel */
608 if (src0[0] != src2[0] && src1[0] != src1[1]) {
609 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
610 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
611 dst[1] = src1[0];
612 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
613 } else {
614 dst[0] = src1[0];
615 dst[1] = src1[0];
616 dst[2] = src1[0];
617 }
618 ++src0;
619 ++src1;
620 ++src2;
621 dst += 3;
622
623 /* central pixels */
624 count -= 2;
625 while (count) {
626 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
627 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
628 dst[1] = src1[0];
629 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
630 } else {
631 dst[0] = src1[0];
632 dst[1] = src1[0];
633 dst[2] = src1[0];
634 }
635
636 ++src0;
637 ++src1;
638 ++src2;
639 dst += 3;
640 --count;
641 }
642
643 /* last pixel */
644 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
645 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
646 dst[1] = src1[0];
647 //TODO: One should check ?: operator carefully - both branches are equal to src1[0]
648 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
649 } else {
650 dst[0] = src1[0];
651 dst[1] = src1[0];
652 dst[2] = src1[0];
653 }
654 }
655
656 /**
657 * Scale by a factor of 3 a row of pixels of 8 bits.
658 * The function is implemented in C.
659 * The pixels over the left and right borders are assumed of the same color of
660 * the pixels on the border.
661 * \param src0 Pointer at the first pixel of the previous row.
662 * \param src1 Pointer at the first pixel of the current row.
663 * \param src2 Pointer at the first pixel of the next row.
664 * \param count Length in pixels of the src0, src1 and src2 rows.
665 * It must be at least 2.
666 * \param dst0 First destination row, triple length in pixels.
667 * \param dst1 Second destination row, triple length in pixels.
668 * \param dst2 Third destination row, triple length in pixels.
669 */
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)670 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)
671 {
672 #ifdef USE_SCALE_RANDOMWRITE
673 scale3x_8_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
674 #else
675 scale3x_8_def_border(dst0, src0, src1, src2, count);
676 scale3x_8_def_center(dst1, src0, src1, src2, count);
677 scale3x_8_def_border(dst2, src2, src1, src0, count);
678 #endif
679 }
680
681 /**
682 * Scale by a factor of 3 a row of pixels of 16 bits.
683 * This function operates like scale3x_8_def() but for 16 bits pixels.
684 * \param src0 Pointer at the first pixel of the previous row.
685 * \param src1 Pointer at the first pixel of the current row.
686 * \param src2 Pointer at the first pixel of the next row.
687 * \param count Length in pixels of the src0, src1 and src2 rows.
688 * It must be at least 2.
689 * \param dst0 First destination row, triple length in pixels.
690 * \param dst1 Second destination row, triple length in pixels.
691 * \param dst2 Third destination row, triple length in pixels.
692 */
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)693 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)
694 {
695 #ifdef USE_SCALE_RANDOMWRITE
696 scale3x_16_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
697 #else
698 scale3x_16_def_border(dst0, src0, src1, src2, count);
699 scale3x_16_def_center(dst1, src0, src1, src2, count);
700 scale3x_16_def_border(dst2, src2, src1, src0, count);
701 #endif
702 }
703
704 /**
705 * Scale by a factor of 3 a row of pixels of 32 bits.
706 * This function operates like scale3x_8_def() but for 32 bits pixels.
707 * \param src0 Pointer at the first pixel of the previous row.
708 * \param src1 Pointer at the first pixel of the current row.
709 * \param src2 Pointer at the first pixel of the next row.
710 * \param count Length in pixels of the src0, src1 and src2 rows.
711 * It must be at least 2.
712 * \param dst0 First destination row, triple length in pixels.
713 * \param dst1 Second destination row, triple length in pixels.
714 * \param dst2 Third destination row, triple length in pixels.
715 */
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)716 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)
717 {
718 #ifdef USE_SCALE_RANDOMWRITE
719 scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
720 #else
721 scale3x_32_def_border(dst0, src0, src1, src2, count);
722 scale3x_32_def_center(dst1, src0, src1, src2, count);
723 scale3x_32_def_border(dst2, src2, src1, src0, count);
724 #endif
725 }
726
727