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 "common/scummsys.h"
36
37 #include "graphics/scaler/scale3x.h"
38
39 /***************************************************************************/
40 /* Scale3x C implementation */
41
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)42 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) {
43 /* central pixels */
44 while (count) {
45 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
46 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
47 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
48 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
49 } else {
50 dst[0] = src1[0];
51 dst[1] = src1[0];
52 dst[2] = src1[0];
53 }
54
55 ++src0;
56 ++src1;
57 ++src2;
58 dst += 3;
59 --count;
60 }
61 }
62
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)63 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) {
64 /* central pixels */
65 while (count) {
66 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
67 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
68 dst[1] = src1[0];
69 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
70 } else {
71 dst[0] = src1[0];
72 dst[1] = src1[0];
73 dst[2] = src1[0];
74 }
75
76 ++src0;
77 ++src1;
78 ++src2;
79 dst += 3;
80 --count;
81 }
82 }
83
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)84 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) {
85 /* central pixels */
86 while (count) {
87 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
88 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
89 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
90 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
91 } else {
92 dst[0] = src1[0];
93 dst[1] = src1[0];
94 dst[2] = src1[0];
95 }
96
97 ++src0;
98 ++src1;
99 ++src2;
100 dst += 3;
101 --count;
102 }
103 }
104
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)105 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) {
106 /* central pixels */
107 while (count) {
108 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
109 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
110 dst[1] = src1[0];
111 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
112 } else {
113 dst[0] = src1[0];
114 dst[1] = src1[0];
115 dst[2] = src1[0];
116 }
117
118 ++src0;
119 ++src1;
120 ++src2;
121 dst += 3;
122 --count;
123 }
124 }
125
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)126 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) {
127 /* central pixels */
128 while (count) {
129 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
130 dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
131 dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
132 dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
133 } else {
134 dst[0] = src1[0];
135 dst[1] = src1[0];
136 dst[2] = src1[0];
137 }
138
139 ++src0;
140 ++src1;
141 ++src2;
142 dst += 3;
143 --count;
144 }
145 }
146
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)147 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) {
148 /* central pixels */
149 while (count) {
150 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
151 dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
152 dst[1] = src1[0];
153 dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
154 } else {
155 dst[0] = src1[0];
156 dst[1] = src1[0];
157 dst[2] = src1[0];
158 }
159
160 ++src0;
161 ++src1;
162 ++src2;
163 dst += 3;
164 --count;
165 }
166 }
167
168 /**
169 * Scale by a factor of 3 a row of pixels of 8 bits.
170 * The function is implemented in C.
171 * The pixels over the left and right borders are assumed of the same color of
172 * the pixels on the border.
173 * @param src0 Pointer at the first pixel of the previous row.
174 * @param src1 Pointer at the first pixel of the current row.
175 * @param src2 Pointer at the first pixel of the next row.
176 * @param count Length in pixels of the src0, src1 and src2 rows.
177 * It must be at least 2.
178 * @param dst0 First destination row, triple length in pixels.
179 * @param dst1 Second destination row, triple length in pixels.
180 * @param dst2 Third destination row, triple length in pixels.
181 */
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)182 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) {
183 scale3x_8_def_border(dst0, src0, src1, src2, count);
184 scale3x_8_def_center(dst1, src0, src1, src2, count);
185 scale3x_8_def_border(dst2, src2, src1, src0, count);
186 }
187
188 /**
189 * Scale by a factor of 3 a row of pixels of 16 bits.
190 * This function operates like scale3x_8_def() but for 16 bits pixels.
191 * @param src0 Pointer at the first pixel of the previous row.
192 * @param src1 Pointer at the first pixel of the current row.
193 * @param src2 Pointer at the first pixel of the next row.
194 * @param count Length in pixels of the src0, src1 and src2 rows.
195 * It must be at least 2.
196 * @param dst0 First destination row, triple length in pixels.
197 * @param dst1 Second destination row, triple length in pixels.
198 * @param dst2 Third destination row, triple length in pixels.
199 */
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)200 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) {
201 scale3x_16_def_border(dst0, src0, src1, src2, count);
202 scale3x_16_def_center(dst1, src0, src1, src2, count);
203 scale3x_16_def_border(dst2, src2, src1, src0, count);
204 }
205
206 /**
207 * Scale by a factor of 3 a row of pixels of 32 bits.
208 * This function operates like scale3x_8_def() but for 32 bits pixels.
209 * @param src0 Pointer at the first pixel of the previous row.
210 * @param src1 Pointer at the first pixel of the current row.
211 * @param src2 Pointer at the first pixel of the next row.
212 * @param count Length in pixels of the src0, src1 and src2 rows.
213 * It must be at least 2.
214 * @param dst0 First destination row, triple length in pixels.
215 * @param dst1 Second destination row, triple length in pixels.
216 * @param dst2 Third destination row, triple length in pixels.
217 */
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)218 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) {
219 scale3x_32_def_border(dst0, src0, src1, src2, count);
220 scale3x_32_def_center(dst1, src0, src1, src2, count);
221 scale3x_32_def_border(dst2, src2, src1, src0, count);
222 }
223