Update
[debian-dgen.git] / scale2x / scale3x.c
blob4e3f5595a49feaecff9341d33a6f40e48f3afd4f
1 /*
2 * This file is part of the Scale2x project.
4 * Copyright (C) 2001, 2002, 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 a C and MMX implementation of the Scale2x effect.
24 * You can find an high level description of the effect at :
26 * http://scale2x.sourceforge.net/
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.
35 #if HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include "scale3x.h"
41 #include <assert.h>
43 /***************************************************************************/
44 /* Scale3x C implementation */
46 /**
47 * Define the macro USE_SCALE_RANDOMWRITE to enable
48 * an optimized version which writes memory in random order.
49 * This version is a little faster if you write in system memory.
50 * But it's a lot slower if you write in video memory.
51 * So, enable it only if you are sure to never write directly in video memory.
53 /* #define USE_SCALE_RANDOMWRITE */
55 #ifdef USE_SCALE_RANDOMWRITE
57 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)
59 assert(count >= 2);
61 /* first pixel */
62 if (src0[0] != src2[0] && src1[0] != src1[1]) {
63 dst0[0] = src1[0];
64 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
65 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
66 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
67 dst1[1] = src1[0];
68 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
69 dst2[0] = src1[0];
70 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
71 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
72 } else {
73 dst0[0] = src1[0];
74 dst0[1] = src1[0];
75 dst0[2] = src1[0];
76 dst1[0] = src1[0];
77 dst1[1] = src1[0];
78 dst1[2] = src1[0];
79 dst2[0] = src1[0];
80 dst2[1] = src1[0];
81 dst2[2] = src1[0];
83 ++src0;
84 ++src1;
85 ++src2;
86 dst0 += 3;
87 dst1 += 3;
88 dst2 += 3;
90 /* central pixels */
91 count -= 2;
92 while (count) {
93 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
94 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
95 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
96 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
97 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
98 dst1[1] = src1[0];
99 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
100 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
101 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
102 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
103 } else {
104 dst0[0] = src1[0];
105 dst0[1] = src1[0];
106 dst0[2] = src1[0];
107 dst1[0] = src1[0];
108 dst1[1] = src1[0];
109 dst1[2] = src1[0];
110 dst2[0] = src1[0];
111 dst2[1] = src1[0];
112 dst2[2] = src1[0];
115 ++src0;
116 ++src1;
117 ++src2;
118 dst0 += 3;
119 dst1 += 3;
120 dst2 += 3;
121 --count;
124 /* last pixel */
125 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
126 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
127 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
128 dst0[2] = src1[0];
129 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
130 dst1[1] = src1[0];
131 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
132 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
133 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
134 dst2[2] = src1[0];
135 } else {
136 dst0[0] = src1[0];
137 dst0[1] = src1[0];
138 dst0[2] = src1[0];
139 dst1[0] = src1[0];
140 dst1[1] = src1[0];
141 dst1[2] = src1[0];
142 dst2[0] = src1[0];
143 dst2[1] = src1[0];
144 dst2[2] = src1[0];
148 #else /* USE_SCALE_RANDOMWRITE */
150 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)
152 assert(count >= 2);
154 /* first pixel */
155 if (src0[0] != src2[0] && src1[0] != src1[1]) {
156 dst[0] = src1[0];
157 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
158 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
159 } else {
160 dst[0] = src1[0];
161 dst[1] = src1[0];
162 dst[2] = src1[0];
164 ++src0;
165 ++src1;
166 ++src2;
167 dst += 3;
169 /* central pixels */
170 count -= 2;
171 while (count) {
172 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
173 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
174 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
175 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
176 } else {
177 dst[0] = src1[0];
178 dst[1] = src1[0];
179 dst[2] = src1[0];
182 ++src0;
183 ++src1;
184 ++src2;
185 dst += 3;
186 --count;
189 /* last pixel */
190 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
191 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
192 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
193 dst[2] = src1[0];
194 } else {
195 dst[0] = src1[0];
196 dst[1] = src1[0];
197 dst[2] = src1[0];
201 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)
203 assert(count >= 2);
205 /* first pixel */
206 if (src0[0] != src2[0] && src1[0] != src1[1]) {
207 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
208 dst[1] = src1[0];
209 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
210 } else {
211 dst[0] = src1[0];
212 dst[1] = src1[0];
213 dst[2] = src1[0];
215 ++src0;
216 ++src1;
217 ++src2;
218 dst += 3;
220 /* central pixels */
221 count -= 2;
222 while (count) {
223 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
224 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
225 dst[1] = src1[0];
226 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
227 } else {
228 dst[0] = src1[0];
229 dst[1] = src1[0];
230 dst[2] = src1[0];
233 ++src0;
234 ++src1;
235 ++src2;
236 dst += 3;
237 --count;
240 /* last pixel */
241 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
242 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
243 dst[1] = src1[0];
244 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
245 } else {
246 dst[0] = src1[0];
247 dst[1] = src1[0];
248 dst[2] = src1[0];
252 #endif /* USE_SCALE_RANDOMWRITE */
254 #ifdef USE_SCALE_RANDOMWRITE
256 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)
258 assert(count >= 2);
260 /* first pixel */
261 if (src0[0] != src2[0] && src1[0] != src1[1]) {
262 dst0[0] = src1[0];
263 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
264 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
265 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
266 dst1[1] = src1[0];
267 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
268 dst2[0] = src1[0];
269 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
270 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
271 } else {
272 dst0[0] = src1[0];
273 dst0[1] = src1[0];
274 dst0[2] = src1[0];
275 dst1[0] = src1[0];
276 dst1[1] = src1[0];
277 dst1[2] = src1[0];
278 dst2[0] = src1[0];
279 dst2[1] = src1[0];
280 dst2[2] = src1[0];
282 ++src0;
283 ++src1;
284 ++src2;
285 dst0 += 3;
286 dst1 += 3;
287 dst2 += 3;
289 /* central pixels */
290 count -= 2;
291 while (count) {
292 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
293 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
294 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
295 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
296 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
297 dst1[1] = src1[0];
298 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
299 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
300 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
301 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
302 } else {
303 dst0[0] = src1[0];
304 dst0[1] = src1[0];
305 dst0[2] = src1[0];
306 dst1[0] = src1[0];
307 dst1[1] = src1[0];
308 dst1[2] = src1[0];
309 dst2[0] = src1[0];
310 dst2[1] = src1[0];
311 dst2[2] = src1[0];
314 ++src0;
315 ++src1;
316 ++src2;
317 dst0 += 3;
318 dst1 += 3;
319 dst2 += 3;
320 --count;
323 /* last pixel */
324 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
325 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
326 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
327 dst0[2] = src1[0];
328 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
329 dst1[1] = src1[0];
330 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
331 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
332 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
333 dst2[2] = src1[0];
334 } else {
335 dst0[0] = src1[0];
336 dst0[1] = src1[0];
337 dst0[2] = src1[0];
338 dst1[0] = src1[0];
339 dst1[1] = src1[0];
340 dst1[2] = src1[0];
341 dst2[0] = src1[0];
342 dst2[1] = src1[0];
343 dst2[2] = src1[0];
347 #else /* USE_SCALE_RANDOMWRITE */
349 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)
351 assert(count >= 2);
353 /* first pixel */
354 if (src0[0] != src2[0] && src1[0] != src1[1]) {
355 dst[0] = src1[0];
356 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
357 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
358 } else {
359 dst[0] = src1[0];
360 dst[1] = src1[0];
361 dst[2] = src1[0];
363 ++src0;
364 ++src1;
365 ++src2;
366 dst += 3;
368 /* central pixels */
369 count -= 2;
370 while (count) {
371 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
372 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
373 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
374 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
375 } else {
376 dst[0] = src1[0];
377 dst[1] = src1[0];
378 dst[2] = src1[0];
381 ++src0;
382 ++src1;
383 ++src2;
384 dst += 3;
385 --count;
388 /* last pixel */
389 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
390 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
391 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
392 dst[2] = src1[0];
393 } else {
394 dst[0] = src1[0];
395 dst[1] = src1[0];
396 dst[2] = src1[0];
400 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)
402 assert(count >= 2);
404 /* first pixel */
405 if (src0[0] != src2[0] && src1[0] != src1[1]) {
406 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
407 dst[1] = src1[0];
408 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
409 } else {
410 dst[0] = src1[0];
411 dst[1] = src1[0];
412 dst[2] = src1[0];
414 ++src0;
415 ++src1;
416 ++src2;
417 dst += 3;
419 /* central pixels */
420 count -= 2;
421 while (count) {
422 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
423 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
424 dst[1] = src1[0];
425 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
426 } else {
427 dst[0] = src1[0];
428 dst[1] = src1[0];
429 dst[2] = src1[0];
432 ++src0;
433 ++src1;
434 ++src2;
435 dst += 3;
436 --count;
439 /* last pixel */
440 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
441 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
442 dst[1] = src1[0];
443 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
444 } else {
445 dst[0] = src1[0];
446 dst[1] = src1[0];
447 dst[2] = src1[0];
451 #endif /* USE_SCALE_RANDOMWRITE */
453 #ifdef USE_SCALE_RANDOMWRITE
455 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)
457 assert(count >= 2);
459 /* first pixel */
460 if (src0[0] != src2[0] && src1[0] != src1[1]) {
461 dst0[0] = src1[0];
462 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
463 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
464 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
465 dst1[1] = src1[0];
466 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
467 dst2[0] = src1[0];
468 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
469 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
470 } else {
471 dst0[0] = src1[0];
472 dst0[1] = src1[0];
473 dst0[2] = src1[0];
474 dst1[0] = src1[0];
475 dst1[1] = src1[0];
476 dst1[2] = src1[0];
477 dst2[0] = src1[0];
478 dst2[1] = src1[0];
479 dst2[2] = src1[0];
481 ++src0;
482 ++src1;
483 ++src2;
484 dst0 += 3;
485 dst1 += 3;
486 dst2 += 3;
488 /* central pixels */
489 count -= 2;
490 while (count) {
491 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
492 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
493 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
494 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
495 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
496 dst1[1] = src1[0];
497 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
498 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
499 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
500 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
501 } else {
502 dst0[0] = src1[0];
503 dst0[1] = src1[0];
504 dst0[2] = src1[0];
505 dst1[0] = src1[0];
506 dst1[1] = src1[0];
507 dst1[2] = src1[0];
508 dst2[0] = src1[0];
509 dst2[1] = src1[0];
510 dst2[2] = src1[0];
513 ++src0;
514 ++src1;
515 ++src2;
516 dst0 += 3;
517 dst1 += 3;
518 dst2 += 3;
519 --count;
522 /* last pixel */
523 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
524 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
525 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
526 dst0[2] = src1[0];
527 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
528 dst1[1] = src1[0];
529 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
530 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
531 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
532 dst2[2] = src1[0];
533 } else {
534 dst0[0] = src1[0];
535 dst0[1] = src1[0];
536 dst0[2] = src1[0];
537 dst1[0] = src1[0];
538 dst1[1] = src1[0];
539 dst1[2] = src1[0];
540 dst2[0] = src1[0];
541 dst2[1] = src1[0];
542 dst2[2] = src1[0];
546 #else /* USE_SCALE_RANDOMWRITE */
548 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)
550 assert(count >= 2);
552 /* first pixel */
553 if (src0[0] != src2[0] && src1[0] != src1[1]) {
554 dst[0] = src1[0];
555 dst[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
556 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
557 } else {
558 dst[0] = src1[0];
559 dst[1] = src1[0];
560 dst[2] = src1[0];
562 ++src0;
563 ++src1;
564 ++src2;
565 dst += 3;
567 /* central pixels */
568 count -= 2;
569 while (count) {
570 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
571 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
572 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
573 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
574 } else {
575 dst[0] = src1[0];
576 dst[1] = src1[0];
577 dst[2] = src1[0];
580 ++src0;
581 ++src1;
582 ++src2;
583 dst += 3;
584 --count;
587 /* last pixel */
588 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
589 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
590 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
591 dst[2] = src1[0];
592 } else {
593 dst[0] = src1[0];
594 dst[1] = src1[0];
595 dst[2] = src1[0];
599 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)
601 assert(count >= 2);
603 /* first pixel */
604 if (src0[0] != src2[0] && src1[0] != src1[1]) {
605 dst[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
606 dst[1] = src1[0];
607 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
608 } else {
609 dst[0] = src1[0];
610 dst[1] = src1[0];
611 dst[2] = src1[0];
613 ++src0;
614 ++src1;
615 ++src2;
616 dst += 3;
618 /* central pixels */
619 count -= 2;
620 while (count) {
621 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
622 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
623 dst[1] = src1[0];
624 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
625 } else {
626 dst[0] = src1[0];
627 dst[1] = src1[0];
628 dst[2] = src1[0];
631 ++src0;
632 ++src1;
633 ++src2;
634 dst += 3;
635 --count;
638 /* last pixel */
639 if (src0[0] != src2[0] && src1[-1] != src1[0]) {
640 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
641 dst[1] = src1[0];
642 dst[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
643 } else {
644 dst[0] = src1[0];
645 dst[1] = src1[0];
646 dst[2] = src1[0];
650 #endif /* USE_SCALE_RANDOMWRITE */
653 * Scale by a factor of 3 a row of pixels of 8 bits.
654 * The function is implemented in C.
655 * The pixels over the left and right borders are assumed of the same color of
656 * the pixels on the border.
657 * \param src0 Pointer at the first pixel of the previous row.
658 * \param src1 Pointer at the first pixel of the current row.
659 * \param src2 Pointer at the first pixel of the next row.
660 * \param count Length in pixels of the src0, src1 and src2 rows.
661 * It must be at least 2.
662 * \param dst0 First destination row, triple length in pixels.
663 * \param dst1 Second destination row, triple length in pixels.
664 * \param dst2 Third destination row, triple length in pixels.
666 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)
668 #ifdef USE_SCALE_RANDOMWRITE
669 scale3x_8_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
670 #else
671 scale3x_8_def_border(dst0, src0, src1, src2, count);
672 scale3x_8_def_center(dst1, src0, src1, src2, count);
673 scale3x_8_def_border(dst2, src2, src1, src0, count);
674 #endif
678 * Scale by a factor of 3 a row of pixels of 16 bits.
679 * This function operates like scale3x_8_def() but for 16 bits pixels.
680 * \param src0 Pointer at the first pixel of the previous row.
681 * \param src1 Pointer at the first pixel of the current row.
682 * \param src2 Pointer at the first pixel of the next row.
683 * \param count Length in pixels of the src0, src1 and src2 rows.
684 * It must be at least 2.
685 * \param dst0 First destination row, triple length in pixels.
686 * \param dst1 Second destination row, triple length in pixels.
687 * \param dst2 Third destination row, triple length in pixels.
689 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)
691 #ifdef USE_SCALE_RANDOMWRITE
692 scale3x_16_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
693 #else
694 scale3x_16_def_border(dst0, src0, src1, src2, count);
695 scale3x_16_def_center(dst1, src0, src1, src2, count);
696 scale3x_16_def_border(dst2, src2, src1, src0, count);
697 #endif
701 * Scale by a factor of 3 a row of pixels of 32 bits.
702 * This function operates like scale3x_8_def() but for 32 bits pixels.
703 * \param src0 Pointer at the first pixel of the previous row.
704 * \param src1 Pointer at the first pixel of the current row.
705 * \param src2 Pointer at the first pixel of the next row.
706 * \param count Length in pixels of the src0, src1 and src2 rows.
707 * It must be at least 2.
708 * \param dst0 First destination row, triple length in pixels.
709 * \param dst1 Second destination row, triple length in pixels.
710 * \param dst2 Third destination row, triple length in pixels.
712 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)
714 #ifdef USE_SCALE_RANDOMWRITE
715 scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, count);
716 #else
717 scale3x_32_def_border(dst0, src0, src1, src2, count);
718 scale3x_32_def_center(dst1, src0, src1, src2, count);
719 scale3x_32_def_border(dst2, src2, src1, src0, count);
720 #endif