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