|
1 /* |
|
2 * Copyright 2011 The LibYuv Project Authors. All rights reserved. |
|
3 * |
|
4 * Use of this source code is governed by a BSD-style license |
|
5 * that can be found in the LICENSE file in the root of the source |
|
6 * tree. An additional intellectual property rights grant can be found |
|
7 * in the file PATENTS. All contributing project authors may |
|
8 * be found in the AUTHORS file in the root of the source tree. |
|
9 */ |
|
10 |
|
11 #include "libyuv/row.h" |
|
12 |
|
13 #include <string.h> // For memcpy and memset. |
|
14 |
|
15 #include "libyuv/basic_types.h" |
|
16 |
|
17 #ifdef __cplusplus |
|
18 namespace libyuv { |
|
19 extern "C" { |
|
20 #endif |
|
21 |
|
22 // llvm x86 is poor at ternary operator, so use branchless min/max. |
|
23 |
|
24 #define USE_BRANCHLESS 1 |
|
25 #if USE_BRANCHLESS |
|
26 static __inline int32 clamp0(int32 v) { |
|
27 return ((-(v) >> 31) & (v)); |
|
28 } |
|
29 |
|
30 static __inline int32 clamp255(int32 v) { |
|
31 return (((255 - (v)) >> 31) | (v)) & 255; |
|
32 } |
|
33 |
|
34 static __inline uint32 Clamp(int32 val) { |
|
35 int v = clamp0(val); |
|
36 return (uint32)(clamp255(v)); |
|
37 } |
|
38 |
|
39 static __inline uint32 Abs(int32 v) { |
|
40 int m = v >> 31; |
|
41 return (v + m) ^ m; |
|
42 } |
|
43 #else // USE_BRANCHLESS |
|
44 static __inline int32 clamp0(int32 v) { |
|
45 return (v < 0) ? 0 : v; |
|
46 } |
|
47 |
|
48 static __inline int32 clamp255(int32 v) { |
|
49 return (v > 255) ? 255 : v; |
|
50 } |
|
51 |
|
52 static __inline uint32 Clamp(int32 val) { |
|
53 int v = clamp0(val); |
|
54 return (uint32)(clamp255(v)); |
|
55 } |
|
56 |
|
57 static __inline uint32 Abs(int32 v) { |
|
58 return (v < 0) ? -v : v; |
|
59 } |
|
60 #endif // USE_BRANCHLESS |
|
61 |
|
62 #ifdef LIBYUV_LITTLE_ENDIAN |
|
63 #define WRITEWORD(p, v) *(uint32*)(p) = v |
|
64 #else |
|
65 static inline void WRITEWORD(uint8* p, uint32 v) { |
|
66 p[0] = (uint8)(v & 255); |
|
67 p[1] = (uint8)((v >> 8) & 255); |
|
68 p[2] = (uint8)((v >> 16) & 255); |
|
69 p[3] = (uint8)((v >> 24) & 255); |
|
70 } |
|
71 #endif |
|
72 |
|
73 void RGB24ToARGBRow_C(const uint8* src_rgb24, uint8* dst_argb, int width) { |
|
74 int x; |
|
75 for (x = 0; x < width; ++x) { |
|
76 uint8 b = src_rgb24[0]; |
|
77 uint8 g = src_rgb24[1]; |
|
78 uint8 r = src_rgb24[2]; |
|
79 dst_argb[0] = b; |
|
80 dst_argb[1] = g; |
|
81 dst_argb[2] = r; |
|
82 dst_argb[3] = 255u; |
|
83 dst_argb += 4; |
|
84 src_rgb24 += 3; |
|
85 } |
|
86 } |
|
87 |
|
88 void RAWToARGBRow_C(const uint8* src_raw, uint8* dst_argb, int width) { |
|
89 int x; |
|
90 for (x = 0; x < width; ++x) { |
|
91 uint8 r = src_raw[0]; |
|
92 uint8 g = src_raw[1]; |
|
93 uint8 b = src_raw[2]; |
|
94 dst_argb[0] = b; |
|
95 dst_argb[1] = g; |
|
96 dst_argb[2] = r; |
|
97 dst_argb[3] = 255u; |
|
98 dst_argb += 4; |
|
99 src_raw += 3; |
|
100 } |
|
101 } |
|
102 |
|
103 void RGB565ToARGBRow_C(const uint8* src_rgb565, uint8* dst_argb, int width) { |
|
104 int x; |
|
105 for (x = 0; x < width; ++x) { |
|
106 uint8 b = src_rgb565[0] & 0x1f; |
|
107 uint8 g = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3); |
|
108 uint8 r = src_rgb565[1] >> 3; |
|
109 dst_argb[0] = (b << 3) | (b >> 2); |
|
110 dst_argb[1] = (g << 2) | (g >> 4); |
|
111 dst_argb[2] = (r << 3) | (r >> 2); |
|
112 dst_argb[3] = 255u; |
|
113 dst_argb += 4; |
|
114 src_rgb565 += 2; |
|
115 } |
|
116 } |
|
117 |
|
118 void ARGB1555ToARGBRow_C(const uint8* src_argb1555, uint8* dst_argb, |
|
119 int width) { |
|
120 int x; |
|
121 for (x = 0; x < width; ++x) { |
|
122 uint8 b = src_argb1555[0] & 0x1f; |
|
123 uint8 g = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3); |
|
124 uint8 r = (src_argb1555[1] & 0x7c) >> 2; |
|
125 uint8 a = src_argb1555[1] >> 7; |
|
126 dst_argb[0] = (b << 3) | (b >> 2); |
|
127 dst_argb[1] = (g << 3) | (g >> 2); |
|
128 dst_argb[2] = (r << 3) | (r >> 2); |
|
129 dst_argb[3] = -a; |
|
130 dst_argb += 4; |
|
131 src_argb1555 += 2; |
|
132 } |
|
133 } |
|
134 |
|
135 void ARGB4444ToARGBRow_C(const uint8* src_argb4444, uint8* dst_argb, |
|
136 int width) { |
|
137 int x; |
|
138 for (x = 0; x < width; ++x) { |
|
139 uint8 b = src_argb4444[0] & 0x0f; |
|
140 uint8 g = src_argb4444[0] >> 4; |
|
141 uint8 r = src_argb4444[1] & 0x0f; |
|
142 uint8 a = src_argb4444[1] >> 4; |
|
143 dst_argb[0] = (b << 4) | b; |
|
144 dst_argb[1] = (g << 4) | g; |
|
145 dst_argb[2] = (r << 4) | r; |
|
146 dst_argb[3] = (a << 4) | a; |
|
147 dst_argb += 4; |
|
148 src_argb4444 += 2; |
|
149 } |
|
150 } |
|
151 |
|
152 void ARGBToRGB24Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { |
|
153 int x; |
|
154 for (x = 0; x < width; ++x) { |
|
155 uint8 b = src_argb[0]; |
|
156 uint8 g = src_argb[1]; |
|
157 uint8 r = src_argb[2]; |
|
158 dst_rgb[0] = b; |
|
159 dst_rgb[1] = g; |
|
160 dst_rgb[2] = r; |
|
161 dst_rgb += 3; |
|
162 src_argb += 4; |
|
163 } |
|
164 } |
|
165 |
|
166 void ARGBToRAWRow_C(const uint8* src_argb, uint8* dst_rgb, int width) { |
|
167 int x; |
|
168 for (x = 0; x < width; ++x) { |
|
169 uint8 b = src_argb[0]; |
|
170 uint8 g = src_argb[1]; |
|
171 uint8 r = src_argb[2]; |
|
172 dst_rgb[0] = r; |
|
173 dst_rgb[1] = g; |
|
174 dst_rgb[2] = b; |
|
175 dst_rgb += 3; |
|
176 src_argb += 4; |
|
177 } |
|
178 } |
|
179 |
|
180 void ARGBToRGB565Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { |
|
181 int x; |
|
182 for (x = 0; x < width - 1; x += 2) { |
|
183 uint8 b0 = src_argb[0] >> 3; |
|
184 uint8 g0 = src_argb[1] >> 2; |
|
185 uint8 r0 = src_argb[2] >> 3; |
|
186 uint8 b1 = src_argb[4] >> 3; |
|
187 uint8 g1 = src_argb[5] >> 2; |
|
188 uint8 r1 = src_argb[6] >> 3; |
|
189 WRITEWORD(dst_rgb, b0 | (g0 << 5) | (r0 << 11) | |
|
190 (b1 << 16) | (g1 << 21) | (r1 << 27)); |
|
191 dst_rgb += 4; |
|
192 src_argb += 8; |
|
193 } |
|
194 if (width & 1) { |
|
195 uint8 b0 = src_argb[0] >> 3; |
|
196 uint8 g0 = src_argb[1] >> 2; |
|
197 uint8 r0 = src_argb[2] >> 3; |
|
198 *(uint16*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 11); |
|
199 } |
|
200 } |
|
201 |
|
202 void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { |
|
203 int x; |
|
204 for (x = 0; x < width - 1; x += 2) { |
|
205 uint8 b0 = src_argb[0] >> 3; |
|
206 uint8 g0 = src_argb[1] >> 3; |
|
207 uint8 r0 = src_argb[2] >> 3; |
|
208 uint8 a0 = src_argb[3] >> 7; |
|
209 uint8 b1 = src_argb[4] >> 3; |
|
210 uint8 g1 = src_argb[5] >> 3; |
|
211 uint8 r1 = src_argb[6] >> 3; |
|
212 uint8 a1 = src_argb[7] >> 7; |
|
213 *(uint32*)(dst_rgb) = |
|
214 b0 | (g0 << 5) | (r0 << 10) | (a0 << 15) | |
|
215 (b1 << 16) | (g1 << 21) | (r1 << 26) | (a1 << 31); |
|
216 dst_rgb += 4; |
|
217 src_argb += 8; |
|
218 } |
|
219 if (width & 1) { |
|
220 uint8 b0 = src_argb[0] >> 3; |
|
221 uint8 g0 = src_argb[1] >> 3; |
|
222 uint8 r0 = src_argb[2] >> 3; |
|
223 uint8 a0 = src_argb[3] >> 7; |
|
224 *(uint16*)(dst_rgb) = |
|
225 b0 | (g0 << 5) | (r0 << 10) | (a0 << 15); |
|
226 } |
|
227 } |
|
228 |
|
229 void ARGBToARGB4444Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { |
|
230 int x; |
|
231 for (x = 0; x < width - 1; x += 2) { |
|
232 uint8 b0 = src_argb[0] >> 4; |
|
233 uint8 g0 = src_argb[1] >> 4; |
|
234 uint8 r0 = src_argb[2] >> 4; |
|
235 uint8 a0 = src_argb[3] >> 4; |
|
236 uint8 b1 = src_argb[4] >> 4; |
|
237 uint8 g1 = src_argb[5] >> 4; |
|
238 uint8 r1 = src_argb[6] >> 4; |
|
239 uint8 a1 = src_argb[7] >> 4; |
|
240 *(uint32*)(dst_rgb) = |
|
241 b0 | (g0 << 4) | (r0 << 8) | (a0 << 12) | |
|
242 (b1 << 16) | (g1 << 20) | (r1 << 24) | (a1 << 28); |
|
243 dst_rgb += 4; |
|
244 src_argb += 8; |
|
245 } |
|
246 if (width & 1) { |
|
247 uint8 b0 = src_argb[0] >> 4; |
|
248 uint8 g0 = src_argb[1] >> 4; |
|
249 uint8 r0 = src_argb[2] >> 4; |
|
250 uint8 a0 = src_argb[3] >> 4; |
|
251 *(uint16*)(dst_rgb) = |
|
252 b0 | (g0 << 4) | (r0 << 8) | (a0 << 12); |
|
253 } |
|
254 } |
|
255 |
|
256 static __inline int RGBToY(uint8 r, uint8 g, uint8 b) { |
|
257 return (66 * r + 129 * g + 25 * b + 0x1080) >> 8; |
|
258 } |
|
259 |
|
260 static __inline int RGBToU(uint8 r, uint8 g, uint8 b) { |
|
261 return (112 * b - 74 * g - 38 * r + 0x8080) >> 8; |
|
262 } |
|
263 static __inline int RGBToV(uint8 r, uint8 g, uint8 b) { |
|
264 return (112 * r - 94 * g - 18 * b + 0x8080) >> 8; |
|
265 } |
|
266 |
|
267 #define MAKEROWY(NAME, R, G, B, BPP) \ |
|
268 void NAME ## ToYRow_C(const uint8* src_argb0, uint8* dst_y, int width) { \ |
|
269 int x; \ |
|
270 for (x = 0; x < width; ++x) { \ |
|
271 dst_y[0] = RGBToY(src_argb0[R], src_argb0[G], src_argb0[B]); \ |
|
272 src_argb0 += BPP; \ |
|
273 dst_y += 1; \ |
|
274 } \ |
|
275 } \ |
|
276 void NAME ## ToUVRow_C(const uint8* src_rgb0, int src_stride_rgb, \ |
|
277 uint8* dst_u, uint8* dst_v, int width) { \ |
|
278 const uint8* src_rgb1 = src_rgb0 + src_stride_rgb; \ |
|
279 int x; \ |
|
280 for (x = 0; x < width - 1; x += 2) { \ |
|
281 uint8 ab = (src_rgb0[B] + src_rgb0[B + BPP] + \ |
|
282 src_rgb1[B] + src_rgb1[B + BPP]) >> 2; \ |
|
283 uint8 ag = (src_rgb0[G] + src_rgb0[G + BPP] + \ |
|
284 src_rgb1[G] + src_rgb1[G + BPP]) >> 2; \ |
|
285 uint8 ar = (src_rgb0[R] + src_rgb0[R + BPP] + \ |
|
286 src_rgb1[R] + src_rgb1[R + BPP]) >> 2; \ |
|
287 dst_u[0] = RGBToU(ar, ag, ab); \ |
|
288 dst_v[0] = RGBToV(ar, ag, ab); \ |
|
289 src_rgb0 += BPP * 2; \ |
|
290 src_rgb1 += BPP * 2; \ |
|
291 dst_u += 1; \ |
|
292 dst_v += 1; \ |
|
293 } \ |
|
294 if (width & 1) { \ |
|
295 uint8 ab = (src_rgb0[B] + src_rgb1[B]) >> 1; \ |
|
296 uint8 ag = (src_rgb0[G] + src_rgb1[G]) >> 1; \ |
|
297 uint8 ar = (src_rgb0[R] + src_rgb1[R]) >> 1; \ |
|
298 dst_u[0] = RGBToU(ar, ag, ab); \ |
|
299 dst_v[0] = RGBToV(ar, ag, ab); \ |
|
300 } \ |
|
301 } |
|
302 |
|
303 MAKEROWY(ARGB, 2, 1, 0, 4) |
|
304 MAKEROWY(BGRA, 1, 2, 3, 4) |
|
305 MAKEROWY(ABGR, 0, 1, 2, 4) |
|
306 MAKEROWY(RGBA, 3, 2, 1, 4) |
|
307 MAKEROWY(RGB24, 2, 1, 0, 3) |
|
308 MAKEROWY(RAW, 0, 1, 2, 3) |
|
309 #undef MAKEROWY |
|
310 |
|
311 // JPeg uses a variation on BT.601-1 full range |
|
312 // y = 0.29900 * r + 0.58700 * g + 0.11400 * b |
|
313 // u = -0.16874 * r - 0.33126 * g + 0.50000 * b + center |
|
314 // v = 0.50000 * r - 0.41869 * g - 0.08131 * b + center |
|
315 // BT.601 Mpeg range uses: |
|
316 // b 0.1016 * 255 = 25.908 = 25 |
|
317 // g 0.5078 * 255 = 129.489 = 129 |
|
318 // r 0.2578 * 255 = 65.739 = 66 |
|
319 // JPeg 8 bit Y (not used): |
|
320 // b 0.11400 * 256 = 29.184 = 29 |
|
321 // g 0.58700 * 256 = 150.272 = 150 |
|
322 // r 0.29900 * 256 = 76.544 = 77 |
|
323 // JPeg 7 bit Y: |
|
324 // b 0.11400 * 128 = 14.592 = 15 |
|
325 // g 0.58700 * 128 = 75.136 = 75 |
|
326 // r 0.29900 * 128 = 38.272 = 38 |
|
327 // JPeg 8 bit U: |
|
328 // b 0.50000 * 255 = 127.5 = 127 |
|
329 // g -0.33126 * 255 = -84.4713 = -84 |
|
330 // r -0.16874 * 255 = -43.0287 = -43 |
|
331 // JPeg 8 bit V: |
|
332 // b -0.08131 * 255 = -20.73405 = -20 |
|
333 // g -0.41869 * 255 = -106.76595 = -107 |
|
334 // r 0.50000 * 255 = 127.5 = 127 |
|
335 |
|
336 static __inline int RGBToYJ(uint8 r, uint8 g, uint8 b) { |
|
337 return (38 * r + 75 * g + 15 * b + 64) >> 7; |
|
338 } |
|
339 |
|
340 static __inline int RGBToUJ(uint8 r, uint8 g, uint8 b) { |
|
341 return (127 * b - 84 * g - 43 * r + 0x8080) >> 8; |
|
342 } |
|
343 static __inline int RGBToVJ(uint8 r, uint8 g, uint8 b) { |
|
344 return (127 * r - 107 * g - 20 * b + 0x8080) >> 8; |
|
345 } |
|
346 |
|
347 #define AVGB(a, b) (((a) + (b) + 1) >> 1) |
|
348 |
|
349 #define MAKEROWYJ(NAME, R, G, B, BPP) \ |
|
350 void NAME ## ToYJRow_C(const uint8* src_argb0, uint8* dst_y, int width) { \ |
|
351 int x; \ |
|
352 for (x = 0; x < width; ++x) { \ |
|
353 dst_y[0] = RGBToYJ(src_argb0[R], src_argb0[G], src_argb0[B]); \ |
|
354 src_argb0 += BPP; \ |
|
355 dst_y += 1; \ |
|
356 } \ |
|
357 } \ |
|
358 void NAME ## ToUVJRow_C(const uint8* src_rgb0, int src_stride_rgb, \ |
|
359 uint8* dst_u, uint8* dst_v, int width) { \ |
|
360 const uint8* src_rgb1 = src_rgb0 + src_stride_rgb; \ |
|
361 int x; \ |
|
362 for (x = 0; x < width - 1; x += 2) { \ |
|
363 uint8 ab = AVGB(AVGB(src_rgb0[B], src_rgb1[B]), \ |
|
364 AVGB(src_rgb0[B + BPP], src_rgb1[B + BPP])); \ |
|
365 uint8 ag = AVGB(AVGB(src_rgb0[G], src_rgb1[G]), \ |
|
366 AVGB(src_rgb0[G + BPP], src_rgb1[G + BPP])); \ |
|
367 uint8 ar = AVGB(AVGB(src_rgb0[R], src_rgb1[R]), \ |
|
368 AVGB(src_rgb0[R + BPP], src_rgb1[R + BPP])); \ |
|
369 dst_u[0] = RGBToUJ(ar, ag, ab); \ |
|
370 dst_v[0] = RGBToVJ(ar, ag, ab); \ |
|
371 src_rgb0 += BPP * 2; \ |
|
372 src_rgb1 += BPP * 2; \ |
|
373 dst_u += 1; \ |
|
374 dst_v += 1; \ |
|
375 } \ |
|
376 if (width & 1) { \ |
|
377 uint8 ab = AVGB(src_rgb0[B], src_rgb1[B]); \ |
|
378 uint8 ag = AVGB(src_rgb0[G], src_rgb1[G]); \ |
|
379 uint8 ar = AVGB(src_rgb0[R], src_rgb1[R]); \ |
|
380 dst_u[0] = RGBToUJ(ar, ag, ab); \ |
|
381 dst_v[0] = RGBToVJ(ar, ag, ab); \ |
|
382 } \ |
|
383 } |
|
384 |
|
385 MAKEROWYJ(ARGB, 2, 1, 0, 4) |
|
386 #undef MAKEROWYJ |
|
387 |
|
388 void RGB565ToYRow_C(const uint8* src_rgb565, uint8* dst_y, int width) { |
|
389 int x; |
|
390 for (x = 0; x < width; ++x) { |
|
391 uint8 b = src_rgb565[0] & 0x1f; |
|
392 uint8 g = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3); |
|
393 uint8 r = src_rgb565[1] >> 3; |
|
394 b = (b << 3) | (b >> 2); |
|
395 g = (g << 2) | (g >> 4); |
|
396 r = (r << 3) | (r >> 2); |
|
397 dst_y[0] = RGBToY(r, g, b); |
|
398 src_rgb565 += 2; |
|
399 dst_y += 1; |
|
400 } |
|
401 } |
|
402 |
|
403 void ARGB1555ToYRow_C(const uint8* src_argb1555, uint8* dst_y, int width) { |
|
404 int x; |
|
405 for (x = 0; x < width; ++x) { |
|
406 uint8 b = src_argb1555[0] & 0x1f; |
|
407 uint8 g = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3); |
|
408 uint8 r = (src_argb1555[1] & 0x7c) >> 2; |
|
409 b = (b << 3) | (b >> 2); |
|
410 g = (g << 3) | (g >> 2); |
|
411 r = (r << 3) | (r >> 2); |
|
412 dst_y[0] = RGBToY(r, g, b); |
|
413 src_argb1555 += 2; |
|
414 dst_y += 1; |
|
415 } |
|
416 } |
|
417 |
|
418 void ARGB4444ToYRow_C(const uint8* src_argb4444, uint8* dst_y, int width) { |
|
419 int x; |
|
420 for (x = 0; x < width; ++x) { |
|
421 uint8 b = src_argb4444[0] & 0x0f; |
|
422 uint8 g = src_argb4444[0] >> 4; |
|
423 uint8 r = src_argb4444[1] & 0x0f; |
|
424 b = (b << 4) | b; |
|
425 g = (g << 4) | g; |
|
426 r = (r << 4) | r; |
|
427 dst_y[0] = RGBToY(r, g, b); |
|
428 src_argb4444 += 2; |
|
429 dst_y += 1; |
|
430 } |
|
431 } |
|
432 |
|
433 void RGB565ToUVRow_C(const uint8* src_rgb565, int src_stride_rgb565, |
|
434 uint8* dst_u, uint8* dst_v, int width) { |
|
435 const uint8* next_rgb565 = src_rgb565 + src_stride_rgb565; |
|
436 int x; |
|
437 for (x = 0; x < width - 1; x += 2) { |
|
438 uint8 b0 = src_rgb565[0] & 0x1f; |
|
439 uint8 g0 = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3); |
|
440 uint8 r0 = src_rgb565[1] >> 3; |
|
441 uint8 b1 = src_rgb565[2] & 0x1f; |
|
442 uint8 g1 = (src_rgb565[2] >> 5) | ((src_rgb565[3] & 0x07) << 3); |
|
443 uint8 r1 = src_rgb565[3] >> 3; |
|
444 uint8 b2 = next_rgb565[0] & 0x1f; |
|
445 uint8 g2 = (next_rgb565[0] >> 5) | ((next_rgb565[1] & 0x07) << 3); |
|
446 uint8 r2 = next_rgb565[1] >> 3; |
|
447 uint8 b3 = next_rgb565[2] & 0x1f; |
|
448 uint8 g3 = (next_rgb565[2] >> 5) | ((next_rgb565[3] & 0x07) << 3); |
|
449 uint8 r3 = next_rgb565[3] >> 3; |
|
450 uint8 b = (b0 + b1 + b2 + b3); // 565 * 4 = 787. |
|
451 uint8 g = (g0 + g1 + g2 + g3); |
|
452 uint8 r = (r0 + r1 + r2 + r3); |
|
453 b = (b << 1) | (b >> 6); // 787 -> 888. |
|
454 r = (r << 1) | (r >> 6); |
|
455 dst_u[0] = RGBToU(r, g, b); |
|
456 dst_v[0] = RGBToV(r, g, b); |
|
457 src_rgb565 += 4; |
|
458 next_rgb565 += 4; |
|
459 dst_u += 1; |
|
460 dst_v += 1; |
|
461 } |
|
462 if (width & 1) { |
|
463 uint8 b0 = src_rgb565[0] & 0x1f; |
|
464 uint8 g0 = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3); |
|
465 uint8 r0 = src_rgb565[1] >> 3; |
|
466 uint8 b2 = next_rgb565[0] & 0x1f; |
|
467 uint8 g2 = (next_rgb565[0] >> 5) | ((next_rgb565[1] & 0x07) << 3); |
|
468 uint8 r2 = next_rgb565[1] >> 3; |
|
469 uint8 b = (b0 + b2); // 565 * 2 = 676. |
|
470 uint8 g = (g0 + g2); |
|
471 uint8 r = (r0 + r2); |
|
472 b = (b << 2) | (b >> 4); // 676 -> 888 |
|
473 g = (g << 1) | (g >> 6); |
|
474 r = (r << 2) | (r >> 4); |
|
475 dst_u[0] = RGBToU(r, g, b); |
|
476 dst_v[0] = RGBToV(r, g, b); |
|
477 } |
|
478 } |
|
479 |
|
480 void ARGB1555ToUVRow_C(const uint8* src_argb1555, int src_stride_argb1555, |
|
481 uint8* dst_u, uint8* dst_v, int width) { |
|
482 const uint8* next_argb1555 = src_argb1555 + src_stride_argb1555; |
|
483 int x; |
|
484 for (x = 0; x < width - 1; x += 2) { |
|
485 uint8 b0 = src_argb1555[0] & 0x1f; |
|
486 uint8 g0 = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3); |
|
487 uint8 r0 = (src_argb1555[1] & 0x7c) >> 2; |
|
488 uint8 b1 = src_argb1555[2] & 0x1f; |
|
489 uint8 g1 = (src_argb1555[2] >> 5) | ((src_argb1555[3] & 0x03) << 3); |
|
490 uint8 r1 = (src_argb1555[3] & 0x7c) >> 2; |
|
491 uint8 b2 = next_argb1555[0] & 0x1f; |
|
492 uint8 g2 = (next_argb1555[0] >> 5) | ((next_argb1555[1] & 0x03) << 3); |
|
493 uint8 r2 = (next_argb1555[1] & 0x7c) >> 2; |
|
494 uint8 b3 = next_argb1555[2] & 0x1f; |
|
495 uint8 g3 = (next_argb1555[2] >> 5) | ((next_argb1555[3] & 0x03) << 3); |
|
496 uint8 r3 = (next_argb1555[3] & 0x7c) >> 2; |
|
497 uint8 b = (b0 + b1 + b2 + b3); // 555 * 4 = 777. |
|
498 uint8 g = (g0 + g1 + g2 + g3); |
|
499 uint8 r = (r0 + r1 + r2 + r3); |
|
500 b = (b << 1) | (b >> 6); // 777 -> 888. |
|
501 g = (g << 1) | (g >> 6); |
|
502 r = (r << 1) | (r >> 6); |
|
503 dst_u[0] = RGBToU(r, g, b); |
|
504 dst_v[0] = RGBToV(r, g, b); |
|
505 src_argb1555 += 4; |
|
506 next_argb1555 += 4; |
|
507 dst_u += 1; |
|
508 dst_v += 1; |
|
509 } |
|
510 if (width & 1) { |
|
511 uint8 b0 = src_argb1555[0] & 0x1f; |
|
512 uint8 g0 = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3); |
|
513 uint8 r0 = (src_argb1555[1] & 0x7c) >> 2; |
|
514 uint8 b2 = next_argb1555[0] & 0x1f; |
|
515 uint8 g2 = (next_argb1555[0] >> 5) | ((next_argb1555[1] & 0x03) << 3); |
|
516 uint8 r2 = next_argb1555[1] >> 3; |
|
517 uint8 b = (b0 + b2); // 555 * 2 = 666. |
|
518 uint8 g = (g0 + g2); |
|
519 uint8 r = (r0 + r2); |
|
520 b = (b << 2) | (b >> 4); // 666 -> 888. |
|
521 g = (g << 2) | (g >> 4); |
|
522 r = (r << 2) | (r >> 4); |
|
523 dst_u[0] = RGBToU(r, g, b); |
|
524 dst_v[0] = RGBToV(r, g, b); |
|
525 } |
|
526 } |
|
527 |
|
528 void ARGB4444ToUVRow_C(const uint8* src_argb4444, int src_stride_argb4444, |
|
529 uint8* dst_u, uint8* dst_v, int width) { |
|
530 const uint8* next_argb4444 = src_argb4444 + src_stride_argb4444; |
|
531 int x; |
|
532 for (x = 0; x < width - 1; x += 2) { |
|
533 uint8 b0 = src_argb4444[0] & 0x0f; |
|
534 uint8 g0 = src_argb4444[0] >> 4; |
|
535 uint8 r0 = src_argb4444[1] & 0x0f; |
|
536 uint8 b1 = src_argb4444[2] & 0x0f; |
|
537 uint8 g1 = src_argb4444[2] >> 4; |
|
538 uint8 r1 = src_argb4444[3] & 0x0f; |
|
539 uint8 b2 = next_argb4444[0] & 0x0f; |
|
540 uint8 g2 = next_argb4444[0] >> 4; |
|
541 uint8 r2 = next_argb4444[1] & 0x0f; |
|
542 uint8 b3 = next_argb4444[2] & 0x0f; |
|
543 uint8 g3 = next_argb4444[2] >> 4; |
|
544 uint8 r3 = next_argb4444[3] & 0x0f; |
|
545 uint8 b = (b0 + b1 + b2 + b3); // 444 * 4 = 666. |
|
546 uint8 g = (g0 + g1 + g2 + g3); |
|
547 uint8 r = (r0 + r1 + r2 + r3); |
|
548 b = (b << 2) | (b >> 4); // 666 -> 888. |
|
549 g = (g << 2) | (g >> 4); |
|
550 r = (r << 2) | (r >> 4); |
|
551 dst_u[0] = RGBToU(r, g, b); |
|
552 dst_v[0] = RGBToV(r, g, b); |
|
553 src_argb4444 += 4; |
|
554 next_argb4444 += 4; |
|
555 dst_u += 1; |
|
556 dst_v += 1; |
|
557 } |
|
558 if (width & 1) { |
|
559 uint8 b0 = src_argb4444[0] & 0x0f; |
|
560 uint8 g0 = src_argb4444[0] >> 4; |
|
561 uint8 r0 = src_argb4444[1] & 0x0f; |
|
562 uint8 b2 = next_argb4444[0] & 0x0f; |
|
563 uint8 g2 = next_argb4444[0] >> 4; |
|
564 uint8 r2 = next_argb4444[1] & 0x0f; |
|
565 uint8 b = (b0 + b2); // 444 * 2 = 555. |
|
566 uint8 g = (g0 + g2); |
|
567 uint8 r = (r0 + r2); |
|
568 b = (b << 3) | (b >> 2); // 555 -> 888. |
|
569 g = (g << 3) | (g >> 2); |
|
570 r = (r << 3) | (r >> 2); |
|
571 dst_u[0] = RGBToU(r, g, b); |
|
572 dst_v[0] = RGBToV(r, g, b); |
|
573 } |
|
574 } |
|
575 |
|
576 void ARGBToUV444Row_C(const uint8* src_argb, |
|
577 uint8* dst_u, uint8* dst_v, int width) { |
|
578 int x; |
|
579 for (x = 0; x < width; ++x) { |
|
580 uint8 ab = src_argb[0]; |
|
581 uint8 ag = src_argb[1]; |
|
582 uint8 ar = src_argb[2]; |
|
583 dst_u[0] = RGBToU(ar, ag, ab); |
|
584 dst_v[0] = RGBToV(ar, ag, ab); |
|
585 src_argb += 4; |
|
586 dst_u += 1; |
|
587 dst_v += 1; |
|
588 } |
|
589 } |
|
590 |
|
591 void ARGBToUV422Row_C(const uint8* src_argb, |
|
592 uint8* dst_u, uint8* dst_v, int width) { |
|
593 int x; |
|
594 for (x = 0; x < width - 1; x += 2) { |
|
595 uint8 ab = (src_argb[0] + src_argb[4]) >> 1; |
|
596 uint8 ag = (src_argb[1] + src_argb[5]) >> 1; |
|
597 uint8 ar = (src_argb[2] + src_argb[6]) >> 1; |
|
598 dst_u[0] = RGBToU(ar, ag, ab); |
|
599 dst_v[0] = RGBToV(ar, ag, ab); |
|
600 src_argb += 8; |
|
601 dst_u += 1; |
|
602 dst_v += 1; |
|
603 } |
|
604 if (width & 1) { |
|
605 uint8 ab = src_argb[0]; |
|
606 uint8 ag = src_argb[1]; |
|
607 uint8 ar = src_argb[2]; |
|
608 dst_u[0] = RGBToU(ar, ag, ab); |
|
609 dst_v[0] = RGBToV(ar, ag, ab); |
|
610 } |
|
611 } |
|
612 |
|
613 void ARGBToUV411Row_C(const uint8* src_argb, |
|
614 uint8* dst_u, uint8* dst_v, int width) { |
|
615 int x; |
|
616 for (x = 0; x < width - 3; x += 4) { |
|
617 uint8 ab = (src_argb[0] + src_argb[4] + src_argb[8] + src_argb[12]) >> 2; |
|
618 uint8 ag = (src_argb[1] + src_argb[5] + src_argb[9] + src_argb[13]) >> 2; |
|
619 uint8 ar = (src_argb[2] + src_argb[6] + src_argb[10] + src_argb[14]) >> 2; |
|
620 dst_u[0] = RGBToU(ar, ag, ab); |
|
621 dst_v[0] = RGBToV(ar, ag, ab); |
|
622 src_argb += 16; |
|
623 dst_u += 1; |
|
624 dst_v += 1; |
|
625 } |
|
626 if ((width & 3) == 3) { |
|
627 uint8 ab = (src_argb[0] + src_argb[4] + src_argb[8]) / 3; |
|
628 uint8 ag = (src_argb[1] + src_argb[5] + src_argb[9]) / 3; |
|
629 uint8 ar = (src_argb[2] + src_argb[6] + src_argb[10]) / 3; |
|
630 dst_u[0] = RGBToU(ar, ag, ab); |
|
631 dst_v[0] = RGBToV(ar, ag, ab); |
|
632 } else if ((width & 3) == 2) { |
|
633 uint8 ab = (src_argb[0] + src_argb[4]) >> 1; |
|
634 uint8 ag = (src_argb[1] + src_argb[5]) >> 1; |
|
635 uint8 ar = (src_argb[2] + src_argb[6]) >> 1; |
|
636 dst_u[0] = RGBToU(ar, ag, ab); |
|
637 dst_v[0] = RGBToV(ar, ag, ab); |
|
638 } else if ((width & 3) == 1) { |
|
639 uint8 ab = src_argb[0]; |
|
640 uint8 ag = src_argb[1]; |
|
641 uint8 ar = src_argb[2]; |
|
642 dst_u[0] = RGBToU(ar, ag, ab); |
|
643 dst_v[0] = RGBToV(ar, ag, ab); |
|
644 } |
|
645 } |
|
646 |
|
647 void ARGBGrayRow_C(const uint8* src_argb, uint8* dst_argb, int width) { |
|
648 int x; |
|
649 for (x = 0; x < width; ++x) { |
|
650 uint8 y = RGBToYJ(src_argb[2], src_argb[1], src_argb[0]); |
|
651 dst_argb[2] = dst_argb[1] = dst_argb[0] = y; |
|
652 dst_argb[3] = src_argb[3]; |
|
653 dst_argb += 4; |
|
654 src_argb += 4; |
|
655 } |
|
656 } |
|
657 |
|
658 // Convert a row of image to Sepia tone. |
|
659 void ARGBSepiaRow_C(uint8* dst_argb, int width) { |
|
660 int x; |
|
661 for (x = 0; x < width; ++x) { |
|
662 int b = dst_argb[0]; |
|
663 int g = dst_argb[1]; |
|
664 int r = dst_argb[2]; |
|
665 int sb = (b * 17 + g * 68 + r * 35) >> 7; |
|
666 int sg = (b * 22 + g * 88 + r * 45) >> 7; |
|
667 int sr = (b * 24 + g * 98 + r * 50) >> 7; |
|
668 // b does not over flow. a is preserved from original. |
|
669 dst_argb[0] = sb; |
|
670 dst_argb[1] = clamp255(sg); |
|
671 dst_argb[2] = clamp255(sr); |
|
672 dst_argb += 4; |
|
673 } |
|
674 } |
|
675 |
|
676 // Apply color matrix to a row of image. Matrix is signed. |
|
677 // TODO(fbarchard): Consider adding rounding (+32). |
|
678 void ARGBColorMatrixRow_C(const uint8* src_argb, uint8* dst_argb, |
|
679 const int8* matrix_argb, int width) { |
|
680 int x; |
|
681 for (x = 0; x < width; ++x) { |
|
682 int b = src_argb[0]; |
|
683 int g = src_argb[1]; |
|
684 int r = src_argb[2]; |
|
685 int a = src_argb[3]; |
|
686 int sb = (b * matrix_argb[0] + g * matrix_argb[1] + |
|
687 r * matrix_argb[2] + a * matrix_argb[3]) >> 6; |
|
688 int sg = (b * matrix_argb[4] + g * matrix_argb[5] + |
|
689 r * matrix_argb[6] + a * matrix_argb[7]) >> 6; |
|
690 int sr = (b * matrix_argb[8] + g * matrix_argb[9] + |
|
691 r * matrix_argb[10] + a * matrix_argb[11]) >> 6; |
|
692 int sa = (b * matrix_argb[12] + g * matrix_argb[13] + |
|
693 r * matrix_argb[14] + a * matrix_argb[15]) >> 6; |
|
694 dst_argb[0] = Clamp(sb); |
|
695 dst_argb[1] = Clamp(sg); |
|
696 dst_argb[2] = Clamp(sr); |
|
697 dst_argb[3] = Clamp(sa); |
|
698 src_argb += 4; |
|
699 dst_argb += 4; |
|
700 } |
|
701 } |
|
702 |
|
703 // Apply color table to a row of image. |
|
704 void ARGBColorTableRow_C(uint8* dst_argb, const uint8* table_argb, int width) { |
|
705 int x; |
|
706 for (x = 0; x < width; ++x) { |
|
707 int b = dst_argb[0]; |
|
708 int g = dst_argb[1]; |
|
709 int r = dst_argb[2]; |
|
710 int a = dst_argb[3]; |
|
711 dst_argb[0] = table_argb[b * 4 + 0]; |
|
712 dst_argb[1] = table_argb[g * 4 + 1]; |
|
713 dst_argb[2] = table_argb[r * 4 + 2]; |
|
714 dst_argb[3] = table_argb[a * 4 + 3]; |
|
715 dst_argb += 4; |
|
716 } |
|
717 } |
|
718 |
|
719 // Apply color table to a row of image. |
|
720 void RGBColorTableRow_C(uint8* dst_argb, const uint8* table_argb, int width) { |
|
721 int x; |
|
722 for (x = 0; x < width; ++x) { |
|
723 int b = dst_argb[0]; |
|
724 int g = dst_argb[1]; |
|
725 int r = dst_argb[2]; |
|
726 dst_argb[0] = table_argb[b * 4 + 0]; |
|
727 dst_argb[1] = table_argb[g * 4 + 1]; |
|
728 dst_argb[2] = table_argb[r * 4 + 2]; |
|
729 dst_argb += 4; |
|
730 } |
|
731 } |
|
732 |
|
733 void ARGBQuantizeRow_C(uint8* dst_argb, int scale, int interval_size, |
|
734 int interval_offset, int width) { |
|
735 int x; |
|
736 for (x = 0; x < width; ++x) { |
|
737 int b = dst_argb[0]; |
|
738 int g = dst_argb[1]; |
|
739 int r = dst_argb[2]; |
|
740 dst_argb[0] = (b * scale >> 16) * interval_size + interval_offset; |
|
741 dst_argb[1] = (g * scale >> 16) * interval_size + interval_offset; |
|
742 dst_argb[2] = (r * scale >> 16) * interval_size + interval_offset; |
|
743 dst_argb += 4; |
|
744 } |
|
745 } |
|
746 |
|
747 #define REPEAT8(v) (v) | ((v) << 8) |
|
748 #define SHADE(f, v) v * f >> 24 |
|
749 |
|
750 void ARGBShadeRow_C(const uint8* src_argb, uint8* dst_argb, int width, |
|
751 uint32 value) { |
|
752 const uint32 b_scale = REPEAT8(value & 0xff); |
|
753 const uint32 g_scale = REPEAT8((value >> 8) & 0xff); |
|
754 const uint32 r_scale = REPEAT8((value >> 16) & 0xff); |
|
755 const uint32 a_scale = REPEAT8(value >> 24); |
|
756 |
|
757 int i; |
|
758 for (i = 0; i < width; ++i) { |
|
759 const uint32 b = REPEAT8(src_argb[0]); |
|
760 const uint32 g = REPEAT8(src_argb[1]); |
|
761 const uint32 r = REPEAT8(src_argb[2]); |
|
762 const uint32 a = REPEAT8(src_argb[3]); |
|
763 dst_argb[0] = SHADE(b, b_scale); |
|
764 dst_argb[1] = SHADE(g, g_scale); |
|
765 dst_argb[2] = SHADE(r, r_scale); |
|
766 dst_argb[3] = SHADE(a, a_scale); |
|
767 src_argb += 4; |
|
768 dst_argb += 4; |
|
769 } |
|
770 } |
|
771 #undef REPEAT8 |
|
772 #undef SHADE |
|
773 |
|
774 #define REPEAT8(v) (v) | ((v) << 8) |
|
775 #define SHADE(f, v) v * f >> 16 |
|
776 |
|
777 void ARGBMultiplyRow_C(const uint8* src_argb0, const uint8* src_argb1, |
|
778 uint8* dst_argb, int width) { |
|
779 int i; |
|
780 for (i = 0; i < width; ++i) { |
|
781 const uint32 b = REPEAT8(src_argb0[0]); |
|
782 const uint32 g = REPEAT8(src_argb0[1]); |
|
783 const uint32 r = REPEAT8(src_argb0[2]); |
|
784 const uint32 a = REPEAT8(src_argb0[3]); |
|
785 const uint32 b_scale = src_argb1[0]; |
|
786 const uint32 g_scale = src_argb1[1]; |
|
787 const uint32 r_scale = src_argb1[2]; |
|
788 const uint32 a_scale = src_argb1[3]; |
|
789 dst_argb[0] = SHADE(b, b_scale); |
|
790 dst_argb[1] = SHADE(g, g_scale); |
|
791 dst_argb[2] = SHADE(r, r_scale); |
|
792 dst_argb[3] = SHADE(a, a_scale); |
|
793 src_argb0 += 4; |
|
794 src_argb1 += 4; |
|
795 dst_argb += 4; |
|
796 } |
|
797 } |
|
798 #undef REPEAT8 |
|
799 #undef SHADE |
|
800 |
|
801 #define SHADE(f, v) clamp255(v + f) |
|
802 |
|
803 void ARGBAddRow_C(const uint8* src_argb0, const uint8* src_argb1, |
|
804 uint8* dst_argb, int width) { |
|
805 int i; |
|
806 for (i = 0; i < width; ++i) { |
|
807 const int b = src_argb0[0]; |
|
808 const int g = src_argb0[1]; |
|
809 const int r = src_argb0[2]; |
|
810 const int a = src_argb0[3]; |
|
811 const int b_add = src_argb1[0]; |
|
812 const int g_add = src_argb1[1]; |
|
813 const int r_add = src_argb1[2]; |
|
814 const int a_add = src_argb1[3]; |
|
815 dst_argb[0] = SHADE(b, b_add); |
|
816 dst_argb[1] = SHADE(g, g_add); |
|
817 dst_argb[2] = SHADE(r, r_add); |
|
818 dst_argb[3] = SHADE(a, a_add); |
|
819 src_argb0 += 4; |
|
820 src_argb1 += 4; |
|
821 dst_argb += 4; |
|
822 } |
|
823 } |
|
824 #undef SHADE |
|
825 |
|
826 #define SHADE(f, v) clamp0(f - v) |
|
827 |
|
828 void ARGBSubtractRow_C(const uint8* src_argb0, const uint8* src_argb1, |
|
829 uint8* dst_argb, int width) { |
|
830 int i; |
|
831 for (i = 0; i < width; ++i) { |
|
832 const int b = src_argb0[0]; |
|
833 const int g = src_argb0[1]; |
|
834 const int r = src_argb0[2]; |
|
835 const int a = src_argb0[3]; |
|
836 const int b_sub = src_argb1[0]; |
|
837 const int g_sub = src_argb1[1]; |
|
838 const int r_sub = src_argb1[2]; |
|
839 const int a_sub = src_argb1[3]; |
|
840 dst_argb[0] = SHADE(b, b_sub); |
|
841 dst_argb[1] = SHADE(g, g_sub); |
|
842 dst_argb[2] = SHADE(r, r_sub); |
|
843 dst_argb[3] = SHADE(a, a_sub); |
|
844 src_argb0 += 4; |
|
845 src_argb1 += 4; |
|
846 dst_argb += 4; |
|
847 } |
|
848 } |
|
849 #undef SHADE |
|
850 |
|
851 // Sobel functions which mimics SSSE3. |
|
852 void SobelXRow_C(const uint8* src_y0, const uint8* src_y1, const uint8* src_y2, |
|
853 uint8* dst_sobelx, int width) { |
|
854 int i; |
|
855 for (i = 0; i < width; ++i) { |
|
856 int a = src_y0[i]; |
|
857 int b = src_y1[i]; |
|
858 int c = src_y2[i]; |
|
859 int a_sub = src_y0[i + 2]; |
|
860 int b_sub = src_y1[i + 2]; |
|
861 int c_sub = src_y2[i + 2]; |
|
862 int a_diff = a - a_sub; |
|
863 int b_diff = b - b_sub; |
|
864 int c_diff = c - c_sub; |
|
865 int sobel = Abs(a_diff + b_diff * 2 + c_diff); |
|
866 dst_sobelx[i] = (uint8)(clamp255(sobel)); |
|
867 } |
|
868 } |
|
869 |
|
870 void SobelYRow_C(const uint8* src_y0, const uint8* src_y1, |
|
871 uint8* dst_sobely, int width) { |
|
872 int i; |
|
873 for (i = 0; i < width; ++i) { |
|
874 int a = src_y0[i + 0]; |
|
875 int b = src_y0[i + 1]; |
|
876 int c = src_y0[i + 2]; |
|
877 int a_sub = src_y1[i + 0]; |
|
878 int b_sub = src_y1[i + 1]; |
|
879 int c_sub = src_y1[i + 2]; |
|
880 int a_diff = a - a_sub; |
|
881 int b_diff = b - b_sub; |
|
882 int c_diff = c - c_sub; |
|
883 int sobel = Abs(a_diff + b_diff * 2 + c_diff); |
|
884 dst_sobely[i] = (uint8)(clamp255(sobel)); |
|
885 } |
|
886 } |
|
887 |
|
888 void SobelRow_C(const uint8* src_sobelx, const uint8* src_sobely, |
|
889 uint8* dst_argb, int width) { |
|
890 int i; |
|
891 for (i = 0; i < width; ++i) { |
|
892 int r = src_sobelx[i]; |
|
893 int b = src_sobely[i]; |
|
894 int s = clamp255(r + b); |
|
895 dst_argb[0] = (uint8)(s); |
|
896 dst_argb[1] = (uint8)(s); |
|
897 dst_argb[2] = (uint8)(s); |
|
898 dst_argb[3] = (uint8)(255u); |
|
899 dst_argb += 4; |
|
900 } |
|
901 } |
|
902 |
|
903 void SobelToPlaneRow_C(const uint8* src_sobelx, const uint8* src_sobely, |
|
904 uint8* dst_y, int width) { |
|
905 int i; |
|
906 for (i = 0; i < width; ++i) { |
|
907 int r = src_sobelx[i]; |
|
908 int b = src_sobely[i]; |
|
909 int s = clamp255(r + b); |
|
910 dst_y[i] = (uint8)(s); |
|
911 } |
|
912 } |
|
913 |
|
914 void SobelXYRow_C(const uint8* src_sobelx, const uint8* src_sobely, |
|
915 uint8* dst_argb, int width) { |
|
916 int i; |
|
917 for (i = 0; i < width; ++i) { |
|
918 int r = src_sobelx[i]; |
|
919 int b = src_sobely[i]; |
|
920 int g = clamp255(r + b); |
|
921 dst_argb[0] = (uint8)(b); |
|
922 dst_argb[1] = (uint8)(g); |
|
923 dst_argb[2] = (uint8)(r); |
|
924 dst_argb[3] = (uint8)(255u); |
|
925 dst_argb += 4; |
|
926 } |
|
927 } |
|
928 |
|
929 void I400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width) { |
|
930 // Copy a Y to RGB. |
|
931 int x; |
|
932 for (x = 0; x < width; ++x) { |
|
933 uint8 y = src_y[0]; |
|
934 dst_argb[2] = dst_argb[1] = dst_argb[0] = y; |
|
935 dst_argb[3] = 255u; |
|
936 dst_argb += 4; |
|
937 ++src_y; |
|
938 } |
|
939 } |
|
940 |
|
941 // C reference code that mimics the YUV assembly. |
|
942 |
|
943 #define YG 74 /* (int8)(1.164 * 64 + 0.5) */ |
|
944 |
|
945 #define UB 127 /* min(63,(int8)(2.018 * 64)) */ |
|
946 #define UG -25 /* (int8)(-0.391 * 64 - 0.5) */ |
|
947 #define UR 0 |
|
948 |
|
949 #define VB 0 |
|
950 #define VG -52 /* (int8)(-0.813 * 64 - 0.5) */ |
|
951 #define VR 102 /* (int8)(1.596 * 64 + 0.5) */ |
|
952 |
|
953 // Bias |
|
954 #define BB UB * 128 + VB * 128 |
|
955 #define BG UG * 128 + VG * 128 |
|
956 #define BR UR * 128 + VR * 128 |
|
957 |
|
958 static __inline void YuvPixel(uint8 y, uint8 u, uint8 v, |
|
959 uint8* b, uint8* g, uint8* r) { |
|
960 int32 y1 = ((int32)(y) - 16) * YG; |
|
961 *b = Clamp((int32)((u * UB + v * VB) - (BB) + y1) >> 6); |
|
962 *g = Clamp((int32)((u * UG + v * VG) - (BG) + y1) >> 6); |
|
963 *r = Clamp((int32)((u * UR + v * VR) - (BR) + y1) >> 6); |
|
964 } |
|
965 |
|
966 #if !defined(LIBYUV_DISABLE_NEON) && \ |
|
967 (defined(__ARM_NEON__) || defined(LIBYUV_NEON)) |
|
968 // C mimic assembly. |
|
969 // TODO(fbarchard): Remove subsampling from Neon. |
|
970 void I444ToARGBRow_C(const uint8* src_y, |
|
971 const uint8* src_u, |
|
972 const uint8* src_v, |
|
973 uint8* rgb_buf, |
|
974 int width) { |
|
975 int x; |
|
976 for (x = 0; x < width - 1; x += 2) { |
|
977 uint8 u = (src_u[0] + src_u[1] + 1) >> 1; |
|
978 uint8 v = (src_v[0] + src_v[1] + 1) >> 1; |
|
979 YuvPixel(src_y[0], u, v, rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
980 rgb_buf[3] = 255; |
|
981 YuvPixel(src_y[1], u, v, rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
982 rgb_buf[7] = 255; |
|
983 src_y += 2; |
|
984 src_u += 2; |
|
985 src_v += 2; |
|
986 rgb_buf += 8; // Advance 2 pixels. |
|
987 } |
|
988 if (width & 1) { |
|
989 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
990 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
991 } |
|
992 } |
|
993 #else |
|
994 void I444ToARGBRow_C(const uint8* src_y, |
|
995 const uint8* src_u, |
|
996 const uint8* src_v, |
|
997 uint8* rgb_buf, |
|
998 int width) { |
|
999 int x; |
|
1000 for (x = 0; x < width; ++x) { |
|
1001 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1002 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1003 rgb_buf[3] = 255; |
|
1004 src_y += 1; |
|
1005 src_u += 1; |
|
1006 src_v += 1; |
|
1007 rgb_buf += 4; // Advance 1 pixel. |
|
1008 } |
|
1009 } |
|
1010 #endif |
|
1011 // Also used for 420 |
|
1012 void I422ToARGBRow_C(const uint8* src_y, |
|
1013 const uint8* src_u, |
|
1014 const uint8* src_v, |
|
1015 uint8* rgb_buf, |
|
1016 int width) { |
|
1017 int x; |
|
1018 for (x = 0; x < width - 1; x += 2) { |
|
1019 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1020 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1021 rgb_buf[3] = 255; |
|
1022 YuvPixel(src_y[1], src_u[0], src_v[0], |
|
1023 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
1024 rgb_buf[7] = 255; |
|
1025 src_y += 2; |
|
1026 src_u += 1; |
|
1027 src_v += 1; |
|
1028 rgb_buf += 8; // Advance 2 pixels. |
|
1029 } |
|
1030 if (width & 1) { |
|
1031 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1032 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1033 rgb_buf[3] = 255; |
|
1034 } |
|
1035 } |
|
1036 |
|
1037 void I422ToRGB24Row_C(const uint8* src_y, |
|
1038 const uint8* src_u, |
|
1039 const uint8* src_v, |
|
1040 uint8* rgb_buf, |
|
1041 int width) { |
|
1042 int x; |
|
1043 for (x = 0; x < width - 1; x += 2) { |
|
1044 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1045 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1046 YuvPixel(src_y[1], src_u[0], src_v[0], |
|
1047 rgb_buf + 3, rgb_buf + 4, rgb_buf + 5); |
|
1048 src_y += 2; |
|
1049 src_u += 1; |
|
1050 src_v += 1; |
|
1051 rgb_buf += 6; // Advance 2 pixels. |
|
1052 } |
|
1053 if (width & 1) { |
|
1054 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1055 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1056 } |
|
1057 } |
|
1058 |
|
1059 void I422ToRAWRow_C(const uint8* src_y, |
|
1060 const uint8* src_u, |
|
1061 const uint8* src_v, |
|
1062 uint8* rgb_buf, |
|
1063 int width) { |
|
1064 int x; |
|
1065 for (x = 0; x < width - 1; x += 2) { |
|
1066 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1067 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0); |
|
1068 YuvPixel(src_y[1], src_u[0], src_v[0], |
|
1069 rgb_buf + 5, rgb_buf + 4, rgb_buf + 3); |
|
1070 src_y += 2; |
|
1071 src_u += 1; |
|
1072 src_v += 1; |
|
1073 rgb_buf += 6; // Advance 2 pixels. |
|
1074 } |
|
1075 if (width & 1) { |
|
1076 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1077 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0); |
|
1078 } |
|
1079 } |
|
1080 |
|
1081 void I422ToARGB4444Row_C(const uint8* src_y, |
|
1082 const uint8* src_u, |
|
1083 const uint8* src_v, |
|
1084 uint8* dst_argb4444, |
|
1085 int width) { |
|
1086 uint8 b0; |
|
1087 uint8 g0; |
|
1088 uint8 r0; |
|
1089 uint8 b1; |
|
1090 uint8 g1; |
|
1091 uint8 r1; |
|
1092 int x; |
|
1093 for (x = 0; x < width - 1; x += 2) { |
|
1094 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); |
|
1095 YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1); |
|
1096 b0 = b0 >> 4; |
|
1097 g0 = g0 >> 4; |
|
1098 r0 = r0 >> 4; |
|
1099 b1 = b1 >> 4; |
|
1100 g1 = g1 >> 4; |
|
1101 r1 = r1 >> 4; |
|
1102 *(uint32*)(dst_argb4444) = b0 | (g0 << 4) | (r0 << 8) | |
|
1103 (b1 << 16) | (g1 << 20) | (r1 << 24) | 0xf000f000; |
|
1104 src_y += 2; |
|
1105 src_u += 1; |
|
1106 src_v += 1; |
|
1107 dst_argb4444 += 4; // Advance 2 pixels. |
|
1108 } |
|
1109 if (width & 1) { |
|
1110 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); |
|
1111 b0 = b0 >> 4; |
|
1112 g0 = g0 >> 4; |
|
1113 r0 = r0 >> 4; |
|
1114 *(uint16*)(dst_argb4444) = b0 | (g0 << 4) | (r0 << 8) | |
|
1115 0xf000; |
|
1116 } |
|
1117 } |
|
1118 |
|
1119 void I422ToARGB1555Row_C(const uint8* src_y, |
|
1120 const uint8* src_u, |
|
1121 const uint8* src_v, |
|
1122 uint8* dst_argb1555, |
|
1123 int width) { |
|
1124 uint8 b0; |
|
1125 uint8 g0; |
|
1126 uint8 r0; |
|
1127 uint8 b1; |
|
1128 uint8 g1; |
|
1129 uint8 r1; |
|
1130 int x; |
|
1131 for (x = 0; x < width - 1; x += 2) { |
|
1132 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); |
|
1133 YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1); |
|
1134 b0 = b0 >> 3; |
|
1135 g0 = g0 >> 3; |
|
1136 r0 = r0 >> 3; |
|
1137 b1 = b1 >> 3; |
|
1138 g1 = g1 >> 3; |
|
1139 r1 = r1 >> 3; |
|
1140 *(uint32*)(dst_argb1555) = b0 | (g0 << 5) | (r0 << 10) | |
|
1141 (b1 << 16) | (g1 << 21) | (r1 << 26) | 0x80008000; |
|
1142 src_y += 2; |
|
1143 src_u += 1; |
|
1144 src_v += 1; |
|
1145 dst_argb1555 += 4; // Advance 2 pixels. |
|
1146 } |
|
1147 if (width & 1) { |
|
1148 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); |
|
1149 b0 = b0 >> 3; |
|
1150 g0 = g0 >> 3; |
|
1151 r0 = r0 >> 3; |
|
1152 *(uint16*)(dst_argb1555) = b0 | (g0 << 5) | (r0 << 10) | |
|
1153 0x8000; |
|
1154 } |
|
1155 } |
|
1156 |
|
1157 void I422ToRGB565Row_C(const uint8* src_y, |
|
1158 const uint8* src_u, |
|
1159 const uint8* src_v, |
|
1160 uint8* dst_rgb565, |
|
1161 int width) { |
|
1162 uint8 b0; |
|
1163 uint8 g0; |
|
1164 uint8 r0; |
|
1165 uint8 b1; |
|
1166 uint8 g1; |
|
1167 uint8 r1; |
|
1168 int x; |
|
1169 for (x = 0; x < width - 1; x += 2) { |
|
1170 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); |
|
1171 YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1); |
|
1172 b0 = b0 >> 3; |
|
1173 g0 = g0 >> 2; |
|
1174 r0 = r0 >> 3; |
|
1175 b1 = b1 >> 3; |
|
1176 g1 = g1 >> 2; |
|
1177 r1 = r1 >> 3; |
|
1178 *(uint32*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) | |
|
1179 (b1 << 16) | (g1 << 21) | (r1 << 27); |
|
1180 src_y += 2; |
|
1181 src_u += 1; |
|
1182 src_v += 1; |
|
1183 dst_rgb565 += 4; // Advance 2 pixels. |
|
1184 } |
|
1185 if (width & 1) { |
|
1186 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0); |
|
1187 b0 = b0 >> 3; |
|
1188 g0 = g0 >> 2; |
|
1189 r0 = r0 >> 3; |
|
1190 *(uint16*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11); |
|
1191 } |
|
1192 } |
|
1193 |
|
1194 void I411ToARGBRow_C(const uint8* src_y, |
|
1195 const uint8* src_u, |
|
1196 const uint8* src_v, |
|
1197 uint8* rgb_buf, |
|
1198 int width) { |
|
1199 int x; |
|
1200 for (x = 0; x < width - 3; x += 4) { |
|
1201 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1202 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1203 rgb_buf[3] = 255; |
|
1204 YuvPixel(src_y[1], src_u[0], src_v[0], |
|
1205 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
1206 rgb_buf[7] = 255; |
|
1207 YuvPixel(src_y[2], src_u[0], src_v[0], |
|
1208 rgb_buf + 8, rgb_buf + 9, rgb_buf + 10); |
|
1209 rgb_buf[11] = 255; |
|
1210 YuvPixel(src_y[3], src_u[0], src_v[0], |
|
1211 rgb_buf + 12, rgb_buf + 13, rgb_buf + 14); |
|
1212 rgb_buf[15] = 255; |
|
1213 src_y += 4; |
|
1214 src_u += 1; |
|
1215 src_v += 1; |
|
1216 rgb_buf += 16; // Advance 4 pixels. |
|
1217 } |
|
1218 if (width & 2) { |
|
1219 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1220 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1221 rgb_buf[3] = 255; |
|
1222 YuvPixel(src_y[1], src_u[0], src_v[0], |
|
1223 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
1224 rgb_buf[7] = 255; |
|
1225 src_y += 2; |
|
1226 rgb_buf += 8; // Advance 2 pixels. |
|
1227 } |
|
1228 if (width & 1) { |
|
1229 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1230 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1231 rgb_buf[3] = 255; |
|
1232 } |
|
1233 } |
|
1234 |
|
1235 void NV12ToARGBRow_C(const uint8* src_y, |
|
1236 const uint8* usrc_v, |
|
1237 uint8* rgb_buf, |
|
1238 int width) { |
|
1239 int x; |
|
1240 for (x = 0; x < width - 1; x += 2) { |
|
1241 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], |
|
1242 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1243 rgb_buf[3] = 255; |
|
1244 YuvPixel(src_y[1], usrc_v[0], usrc_v[1], |
|
1245 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
1246 rgb_buf[7] = 255; |
|
1247 src_y += 2; |
|
1248 usrc_v += 2; |
|
1249 rgb_buf += 8; // Advance 2 pixels. |
|
1250 } |
|
1251 if (width & 1) { |
|
1252 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], |
|
1253 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1254 rgb_buf[3] = 255; |
|
1255 } |
|
1256 } |
|
1257 |
|
1258 void NV21ToARGBRow_C(const uint8* src_y, |
|
1259 const uint8* src_vu, |
|
1260 uint8* rgb_buf, |
|
1261 int width) { |
|
1262 int x; |
|
1263 for (x = 0; x < width - 1; x += 2) { |
|
1264 YuvPixel(src_y[0], src_vu[1], src_vu[0], |
|
1265 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1266 rgb_buf[3] = 255; |
|
1267 |
|
1268 YuvPixel(src_y[1], src_vu[1], src_vu[0], |
|
1269 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
1270 rgb_buf[7] = 255; |
|
1271 |
|
1272 src_y += 2; |
|
1273 src_vu += 2; |
|
1274 rgb_buf += 8; // Advance 2 pixels. |
|
1275 } |
|
1276 if (width & 1) { |
|
1277 YuvPixel(src_y[0], src_vu[1], src_vu[0], |
|
1278 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1279 rgb_buf[3] = 255; |
|
1280 } |
|
1281 } |
|
1282 |
|
1283 void NV12ToRGB565Row_C(const uint8* src_y, |
|
1284 const uint8* usrc_v, |
|
1285 uint8* dst_rgb565, |
|
1286 int width) { |
|
1287 uint8 b0; |
|
1288 uint8 g0; |
|
1289 uint8 r0; |
|
1290 uint8 b1; |
|
1291 uint8 g1; |
|
1292 uint8 r1; |
|
1293 int x; |
|
1294 for (x = 0; x < width - 1; x += 2) { |
|
1295 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], &b0, &g0, &r0); |
|
1296 YuvPixel(src_y[1], usrc_v[0], usrc_v[1], &b1, &g1, &r1); |
|
1297 b0 = b0 >> 3; |
|
1298 g0 = g0 >> 2; |
|
1299 r0 = r0 >> 3; |
|
1300 b1 = b1 >> 3; |
|
1301 g1 = g1 >> 2; |
|
1302 r1 = r1 >> 3; |
|
1303 *(uint32*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) | |
|
1304 (b1 << 16) | (g1 << 21) | (r1 << 27); |
|
1305 src_y += 2; |
|
1306 usrc_v += 2; |
|
1307 dst_rgb565 += 4; // Advance 2 pixels. |
|
1308 } |
|
1309 if (width & 1) { |
|
1310 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], &b0, &g0, &r0); |
|
1311 b0 = b0 >> 3; |
|
1312 g0 = g0 >> 2; |
|
1313 r0 = r0 >> 3; |
|
1314 *(uint16*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11); |
|
1315 } |
|
1316 } |
|
1317 |
|
1318 void NV21ToRGB565Row_C(const uint8* src_y, |
|
1319 const uint8* vsrc_u, |
|
1320 uint8* dst_rgb565, |
|
1321 int width) { |
|
1322 uint8 b0; |
|
1323 uint8 g0; |
|
1324 uint8 r0; |
|
1325 uint8 b1; |
|
1326 uint8 g1; |
|
1327 uint8 r1; |
|
1328 int x; |
|
1329 for (x = 0; x < width - 1; x += 2) { |
|
1330 YuvPixel(src_y[0], vsrc_u[1], vsrc_u[0], &b0, &g0, &r0); |
|
1331 YuvPixel(src_y[1], vsrc_u[1], vsrc_u[0], &b1, &g1, &r1); |
|
1332 b0 = b0 >> 3; |
|
1333 g0 = g0 >> 2; |
|
1334 r0 = r0 >> 3; |
|
1335 b1 = b1 >> 3; |
|
1336 g1 = g1 >> 2; |
|
1337 r1 = r1 >> 3; |
|
1338 *(uint32*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) | |
|
1339 (b1 << 16) | (g1 << 21) | (r1 << 27); |
|
1340 src_y += 2; |
|
1341 vsrc_u += 2; |
|
1342 dst_rgb565 += 4; // Advance 2 pixels. |
|
1343 } |
|
1344 if (width & 1) { |
|
1345 YuvPixel(src_y[0], vsrc_u[1], vsrc_u[0], &b0, &g0, &r0); |
|
1346 b0 = b0 >> 3; |
|
1347 g0 = g0 >> 2; |
|
1348 r0 = r0 >> 3; |
|
1349 *(uint16*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11); |
|
1350 } |
|
1351 } |
|
1352 |
|
1353 void YUY2ToARGBRow_C(const uint8* src_yuy2, |
|
1354 uint8* rgb_buf, |
|
1355 int width) { |
|
1356 int x; |
|
1357 for (x = 0; x < width - 1; x += 2) { |
|
1358 YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3], |
|
1359 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1360 rgb_buf[3] = 255; |
|
1361 YuvPixel(src_yuy2[2], src_yuy2[1], src_yuy2[3], |
|
1362 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
1363 rgb_buf[7] = 255; |
|
1364 src_yuy2 += 4; |
|
1365 rgb_buf += 8; // Advance 2 pixels. |
|
1366 } |
|
1367 if (width & 1) { |
|
1368 YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3], |
|
1369 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1370 rgb_buf[3] = 255; |
|
1371 } |
|
1372 } |
|
1373 |
|
1374 void UYVYToARGBRow_C(const uint8* src_uyvy, |
|
1375 uint8* rgb_buf, |
|
1376 int width) { |
|
1377 int x; |
|
1378 for (x = 0; x < width - 1; x += 2) { |
|
1379 YuvPixel(src_uyvy[1], src_uyvy[0], src_uyvy[2], |
|
1380 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1381 rgb_buf[3] = 255; |
|
1382 YuvPixel(src_uyvy[3], src_uyvy[0], src_uyvy[2], |
|
1383 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
1384 rgb_buf[7] = 255; |
|
1385 src_uyvy += 4; |
|
1386 rgb_buf += 8; // Advance 2 pixels. |
|
1387 } |
|
1388 if (width & 1) { |
|
1389 YuvPixel(src_uyvy[1], src_uyvy[0], src_uyvy[2], |
|
1390 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1391 rgb_buf[3] = 255; |
|
1392 } |
|
1393 } |
|
1394 |
|
1395 void I422ToBGRARow_C(const uint8* src_y, |
|
1396 const uint8* src_u, |
|
1397 const uint8* src_v, |
|
1398 uint8* rgb_buf, |
|
1399 int width) { |
|
1400 int x; |
|
1401 for (x = 0; x < width - 1; x += 2) { |
|
1402 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1403 rgb_buf + 3, rgb_buf + 2, rgb_buf + 1); |
|
1404 rgb_buf[0] = 255; |
|
1405 YuvPixel(src_y[1], src_u[0], src_v[0], |
|
1406 rgb_buf + 7, rgb_buf + 6, rgb_buf + 5); |
|
1407 rgb_buf[4] = 255; |
|
1408 src_y += 2; |
|
1409 src_u += 1; |
|
1410 src_v += 1; |
|
1411 rgb_buf += 8; // Advance 2 pixels. |
|
1412 } |
|
1413 if (width & 1) { |
|
1414 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1415 rgb_buf + 3, rgb_buf + 2, rgb_buf + 1); |
|
1416 rgb_buf[0] = 255; |
|
1417 } |
|
1418 } |
|
1419 |
|
1420 void I422ToABGRRow_C(const uint8* src_y, |
|
1421 const uint8* src_u, |
|
1422 const uint8* src_v, |
|
1423 uint8* rgb_buf, |
|
1424 int width) { |
|
1425 int x; |
|
1426 for (x = 0; x < width - 1; x += 2) { |
|
1427 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1428 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0); |
|
1429 rgb_buf[3] = 255; |
|
1430 YuvPixel(src_y[1], src_u[0], src_v[0], |
|
1431 rgb_buf + 6, rgb_buf + 5, rgb_buf + 4); |
|
1432 rgb_buf[7] = 255; |
|
1433 src_y += 2; |
|
1434 src_u += 1; |
|
1435 src_v += 1; |
|
1436 rgb_buf += 8; // Advance 2 pixels. |
|
1437 } |
|
1438 if (width & 1) { |
|
1439 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1440 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0); |
|
1441 rgb_buf[3] = 255; |
|
1442 } |
|
1443 } |
|
1444 |
|
1445 void I422ToRGBARow_C(const uint8* src_y, |
|
1446 const uint8* src_u, |
|
1447 const uint8* src_v, |
|
1448 uint8* rgb_buf, |
|
1449 int width) { |
|
1450 int x; |
|
1451 for (x = 0; x < width - 1; x += 2) { |
|
1452 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1453 rgb_buf + 1, rgb_buf + 2, rgb_buf + 3); |
|
1454 rgb_buf[0] = 255; |
|
1455 YuvPixel(src_y[1], src_u[0], src_v[0], |
|
1456 rgb_buf + 5, rgb_buf + 6, rgb_buf + 7); |
|
1457 rgb_buf[4] = 255; |
|
1458 src_y += 2; |
|
1459 src_u += 1; |
|
1460 src_v += 1; |
|
1461 rgb_buf += 8; // Advance 2 pixels. |
|
1462 } |
|
1463 if (width & 1) { |
|
1464 YuvPixel(src_y[0], src_u[0], src_v[0], |
|
1465 rgb_buf + 1, rgb_buf + 2, rgb_buf + 3); |
|
1466 rgb_buf[0] = 255; |
|
1467 } |
|
1468 } |
|
1469 |
|
1470 void YToARGBRow_C(const uint8* src_y, uint8* rgb_buf, int width) { |
|
1471 int x; |
|
1472 for (x = 0; x < width - 1; x += 2) { |
|
1473 YuvPixel(src_y[0], 128, 128, |
|
1474 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1475 rgb_buf[3] = 255; |
|
1476 YuvPixel(src_y[1], 128, 128, |
|
1477 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
|
1478 rgb_buf[7] = 255; |
|
1479 src_y += 2; |
|
1480 rgb_buf += 8; // Advance 2 pixels. |
|
1481 } |
|
1482 if (width & 1) { |
|
1483 YuvPixel(src_y[0], 128, 128, |
|
1484 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
|
1485 rgb_buf[3] = 255; |
|
1486 } |
|
1487 } |
|
1488 |
|
1489 void MirrorRow_C(const uint8* src, uint8* dst, int width) { |
|
1490 int x; |
|
1491 src += width - 1; |
|
1492 for (x = 0; x < width - 1; x += 2) { |
|
1493 dst[x] = src[0]; |
|
1494 dst[x + 1] = src[-1]; |
|
1495 src -= 2; |
|
1496 } |
|
1497 if (width & 1) { |
|
1498 dst[width - 1] = src[0]; |
|
1499 } |
|
1500 } |
|
1501 |
|
1502 void MirrorUVRow_C(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width) { |
|
1503 int x; |
|
1504 src_uv += (width - 1) << 1; |
|
1505 for (x = 0; x < width - 1; x += 2) { |
|
1506 dst_u[x] = src_uv[0]; |
|
1507 dst_u[x + 1] = src_uv[-2]; |
|
1508 dst_v[x] = src_uv[1]; |
|
1509 dst_v[x + 1] = src_uv[-2 + 1]; |
|
1510 src_uv -= 4; |
|
1511 } |
|
1512 if (width & 1) { |
|
1513 dst_u[width - 1] = src_uv[0]; |
|
1514 dst_v[width - 1] = src_uv[1]; |
|
1515 } |
|
1516 } |
|
1517 |
|
1518 void ARGBMirrorRow_C(const uint8* src, uint8* dst, int width) { |
|
1519 int x; |
|
1520 const uint32* src32 = (const uint32*)(src); |
|
1521 uint32* dst32 = (uint32*)(dst); |
|
1522 src32 += width - 1; |
|
1523 for (x = 0; x < width - 1; x += 2) { |
|
1524 dst32[x] = src32[0]; |
|
1525 dst32[x + 1] = src32[-1]; |
|
1526 src32 -= 2; |
|
1527 } |
|
1528 if (width & 1) { |
|
1529 dst32[width - 1] = src32[0]; |
|
1530 } |
|
1531 } |
|
1532 |
|
1533 void SplitUVRow_C(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width) { |
|
1534 int x; |
|
1535 for (x = 0; x < width - 1; x += 2) { |
|
1536 dst_u[x] = src_uv[0]; |
|
1537 dst_u[x + 1] = src_uv[2]; |
|
1538 dst_v[x] = src_uv[1]; |
|
1539 dst_v[x + 1] = src_uv[3]; |
|
1540 src_uv += 4; |
|
1541 } |
|
1542 if (width & 1) { |
|
1543 dst_u[width - 1] = src_uv[0]; |
|
1544 dst_v[width - 1] = src_uv[1]; |
|
1545 } |
|
1546 } |
|
1547 |
|
1548 void MergeUVRow_C(const uint8* src_u, const uint8* src_v, uint8* dst_uv, |
|
1549 int width) { |
|
1550 int x; |
|
1551 for (x = 0; x < width - 1; x += 2) { |
|
1552 dst_uv[0] = src_u[x]; |
|
1553 dst_uv[1] = src_v[x]; |
|
1554 dst_uv[2] = src_u[x + 1]; |
|
1555 dst_uv[3] = src_v[x + 1]; |
|
1556 dst_uv += 4; |
|
1557 } |
|
1558 if (width & 1) { |
|
1559 dst_uv[0] = src_u[width - 1]; |
|
1560 dst_uv[1] = src_v[width - 1]; |
|
1561 } |
|
1562 } |
|
1563 |
|
1564 void CopyRow_C(const uint8* src, uint8* dst, int count) { |
|
1565 memcpy(dst, src, count); |
|
1566 } |
|
1567 |
|
1568 void SetRow_C(uint8* dst, uint32 v8, int count) { |
|
1569 #ifdef _MSC_VER |
|
1570 // VC will generate rep stosb. |
|
1571 int x; |
|
1572 for (x = 0; x < count; ++x) { |
|
1573 dst[x] = v8; |
|
1574 } |
|
1575 #else |
|
1576 memset(dst, v8, count); |
|
1577 #endif |
|
1578 } |
|
1579 |
|
1580 void ARGBSetRows_C(uint8* dst, uint32 v32, int width, |
|
1581 int dst_stride, int height) { |
|
1582 int y; |
|
1583 for (y = 0; y < height; ++y) { |
|
1584 uint32* d = (uint32*)(dst); |
|
1585 int x; |
|
1586 for (x = 0; x < width; ++x) { |
|
1587 d[x] = v32; |
|
1588 } |
|
1589 dst += dst_stride; |
|
1590 } |
|
1591 } |
|
1592 |
|
1593 // Filter 2 rows of YUY2 UV's (422) into U and V (420). |
|
1594 void YUY2ToUVRow_C(const uint8* src_yuy2, int src_stride_yuy2, |
|
1595 uint8* dst_u, uint8* dst_v, int width) { |
|
1596 // Output a row of UV values, filtering 2 rows of YUY2. |
|
1597 int x; |
|
1598 for (x = 0; x < width; x += 2) { |
|
1599 dst_u[0] = (src_yuy2[1] + src_yuy2[src_stride_yuy2 + 1] + 1) >> 1; |
|
1600 dst_v[0] = (src_yuy2[3] + src_yuy2[src_stride_yuy2 + 3] + 1) >> 1; |
|
1601 src_yuy2 += 4; |
|
1602 dst_u += 1; |
|
1603 dst_v += 1; |
|
1604 } |
|
1605 } |
|
1606 |
|
1607 // Copy row of YUY2 UV's (422) into U and V (422). |
|
1608 void YUY2ToUV422Row_C(const uint8* src_yuy2, |
|
1609 uint8* dst_u, uint8* dst_v, int width) { |
|
1610 // Output a row of UV values. |
|
1611 int x; |
|
1612 for (x = 0; x < width; x += 2) { |
|
1613 dst_u[0] = src_yuy2[1]; |
|
1614 dst_v[0] = src_yuy2[3]; |
|
1615 src_yuy2 += 4; |
|
1616 dst_u += 1; |
|
1617 dst_v += 1; |
|
1618 } |
|
1619 } |
|
1620 |
|
1621 // Copy row of YUY2 Y's (422) into Y (420/422). |
|
1622 void YUY2ToYRow_C(const uint8* src_yuy2, uint8* dst_y, int width) { |
|
1623 // Output a row of Y values. |
|
1624 int x; |
|
1625 for (x = 0; x < width - 1; x += 2) { |
|
1626 dst_y[x] = src_yuy2[0]; |
|
1627 dst_y[x + 1] = src_yuy2[2]; |
|
1628 src_yuy2 += 4; |
|
1629 } |
|
1630 if (width & 1) { |
|
1631 dst_y[width - 1] = src_yuy2[0]; |
|
1632 } |
|
1633 } |
|
1634 |
|
1635 // Filter 2 rows of UYVY UV's (422) into U and V (420). |
|
1636 void UYVYToUVRow_C(const uint8* src_uyvy, int src_stride_uyvy, |
|
1637 uint8* dst_u, uint8* dst_v, int width) { |
|
1638 // Output a row of UV values. |
|
1639 int x; |
|
1640 for (x = 0; x < width; x += 2) { |
|
1641 dst_u[0] = (src_uyvy[0] + src_uyvy[src_stride_uyvy + 0] + 1) >> 1; |
|
1642 dst_v[0] = (src_uyvy[2] + src_uyvy[src_stride_uyvy + 2] + 1) >> 1; |
|
1643 src_uyvy += 4; |
|
1644 dst_u += 1; |
|
1645 dst_v += 1; |
|
1646 } |
|
1647 } |
|
1648 |
|
1649 // Copy row of UYVY UV's (422) into U and V (422). |
|
1650 void UYVYToUV422Row_C(const uint8* src_uyvy, |
|
1651 uint8* dst_u, uint8* dst_v, int width) { |
|
1652 // Output a row of UV values. |
|
1653 int x; |
|
1654 for (x = 0; x < width; x += 2) { |
|
1655 dst_u[0] = src_uyvy[0]; |
|
1656 dst_v[0] = src_uyvy[2]; |
|
1657 src_uyvy += 4; |
|
1658 dst_u += 1; |
|
1659 dst_v += 1; |
|
1660 } |
|
1661 } |
|
1662 |
|
1663 // Copy row of UYVY Y's (422) into Y (420/422). |
|
1664 void UYVYToYRow_C(const uint8* src_uyvy, uint8* dst_y, int width) { |
|
1665 // Output a row of Y values. |
|
1666 int x; |
|
1667 for (x = 0; x < width - 1; x += 2) { |
|
1668 dst_y[x] = src_uyvy[1]; |
|
1669 dst_y[x + 1] = src_uyvy[3]; |
|
1670 src_uyvy += 4; |
|
1671 } |
|
1672 if (width & 1) { |
|
1673 dst_y[width - 1] = src_uyvy[1]; |
|
1674 } |
|
1675 } |
|
1676 |
|
1677 #define BLEND(f, b, a) (((256 - a) * b) >> 8) + f |
|
1678 |
|
1679 // Blend src_argb0 over src_argb1 and store to dst_argb. |
|
1680 // dst_argb may be src_argb0 or src_argb1. |
|
1681 // This code mimics the SSSE3 version for better testability. |
|
1682 void ARGBBlendRow_C(const uint8* src_argb0, const uint8* src_argb1, |
|
1683 uint8* dst_argb, int width) { |
|
1684 int x; |
|
1685 for (x = 0; x < width - 1; x += 2) { |
|
1686 uint32 fb = src_argb0[0]; |
|
1687 uint32 fg = src_argb0[1]; |
|
1688 uint32 fr = src_argb0[2]; |
|
1689 uint32 a = src_argb0[3]; |
|
1690 uint32 bb = src_argb1[0]; |
|
1691 uint32 bg = src_argb1[1]; |
|
1692 uint32 br = src_argb1[2]; |
|
1693 dst_argb[0] = BLEND(fb, bb, a); |
|
1694 dst_argb[1] = BLEND(fg, bg, a); |
|
1695 dst_argb[2] = BLEND(fr, br, a); |
|
1696 dst_argb[3] = 255u; |
|
1697 |
|
1698 fb = src_argb0[4 + 0]; |
|
1699 fg = src_argb0[4 + 1]; |
|
1700 fr = src_argb0[4 + 2]; |
|
1701 a = src_argb0[4 + 3]; |
|
1702 bb = src_argb1[4 + 0]; |
|
1703 bg = src_argb1[4 + 1]; |
|
1704 br = src_argb1[4 + 2]; |
|
1705 dst_argb[4 + 0] = BLEND(fb, bb, a); |
|
1706 dst_argb[4 + 1] = BLEND(fg, bg, a); |
|
1707 dst_argb[4 + 2] = BLEND(fr, br, a); |
|
1708 dst_argb[4 + 3] = 255u; |
|
1709 src_argb0 += 8; |
|
1710 src_argb1 += 8; |
|
1711 dst_argb += 8; |
|
1712 } |
|
1713 |
|
1714 if (width & 1) { |
|
1715 uint32 fb = src_argb0[0]; |
|
1716 uint32 fg = src_argb0[1]; |
|
1717 uint32 fr = src_argb0[2]; |
|
1718 uint32 a = src_argb0[3]; |
|
1719 uint32 bb = src_argb1[0]; |
|
1720 uint32 bg = src_argb1[1]; |
|
1721 uint32 br = src_argb1[2]; |
|
1722 dst_argb[0] = BLEND(fb, bb, a); |
|
1723 dst_argb[1] = BLEND(fg, bg, a); |
|
1724 dst_argb[2] = BLEND(fr, br, a); |
|
1725 dst_argb[3] = 255u; |
|
1726 } |
|
1727 } |
|
1728 #undef BLEND |
|
1729 #define ATTENUATE(f, a) (a | (a << 8)) * (f | (f << 8)) >> 24 |
|
1730 |
|
1731 // Multiply source RGB by alpha and store to destination. |
|
1732 // This code mimics the SSSE3 version for better testability. |
|
1733 void ARGBAttenuateRow_C(const uint8* src_argb, uint8* dst_argb, int width) { |
|
1734 int i; |
|
1735 for (i = 0; i < width - 1; i += 2) { |
|
1736 uint32 b = src_argb[0]; |
|
1737 uint32 g = src_argb[1]; |
|
1738 uint32 r = src_argb[2]; |
|
1739 uint32 a = src_argb[3]; |
|
1740 dst_argb[0] = ATTENUATE(b, a); |
|
1741 dst_argb[1] = ATTENUATE(g, a); |
|
1742 dst_argb[2] = ATTENUATE(r, a); |
|
1743 dst_argb[3] = a; |
|
1744 b = src_argb[4]; |
|
1745 g = src_argb[5]; |
|
1746 r = src_argb[6]; |
|
1747 a = src_argb[7]; |
|
1748 dst_argb[4] = ATTENUATE(b, a); |
|
1749 dst_argb[5] = ATTENUATE(g, a); |
|
1750 dst_argb[6] = ATTENUATE(r, a); |
|
1751 dst_argb[7] = a; |
|
1752 src_argb += 8; |
|
1753 dst_argb += 8; |
|
1754 } |
|
1755 |
|
1756 if (width & 1) { |
|
1757 const uint32 b = src_argb[0]; |
|
1758 const uint32 g = src_argb[1]; |
|
1759 const uint32 r = src_argb[2]; |
|
1760 const uint32 a = src_argb[3]; |
|
1761 dst_argb[0] = ATTENUATE(b, a); |
|
1762 dst_argb[1] = ATTENUATE(g, a); |
|
1763 dst_argb[2] = ATTENUATE(r, a); |
|
1764 dst_argb[3] = a; |
|
1765 } |
|
1766 } |
|
1767 #undef ATTENUATE |
|
1768 |
|
1769 // Divide source RGB by alpha and store to destination. |
|
1770 // b = (b * 255 + (a / 2)) / a; |
|
1771 // g = (g * 255 + (a / 2)) / a; |
|
1772 // r = (r * 255 + (a / 2)) / a; |
|
1773 // Reciprocal method is off by 1 on some values. ie 125 |
|
1774 // 8.8 fixed point inverse table with 1.0 in upper short and 1 / a in lower. |
|
1775 #define T(a) 0x01000000 + (0x10000 / a) |
|
1776 const uint32 fixed_invtbl8[256] = { |
|
1777 0x01000000, 0x0100ffff, T(0x02), T(0x03), T(0x04), T(0x05), T(0x06), T(0x07), |
|
1778 T(0x08), T(0x09), T(0x0a), T(0x0b), T(0x0c), T(0x0d), T(0x0e), T(0x0f), |
|
1779 T(0x10), T(0x11), T(0x12), T(0x13), T(0x14), T(0x15), T(0x16), T(0x17), |
|
1780 T(0x18), T(0x19), T(0x1a), T(0x1b), T(0x1c), T(0x1d), T(0x1e), T(0x1f), |
|
1781 T(0x20), T(0x21), T(0x22), T(0x23), T(0x24), T(0x25), T(0x26), T(0x27), |
|
1782 T(0x28), T(0x29), T(0x2a), T(0x2b), T(0x2c), T(0x2d), T(0x2e), T(0x2f), |
|
1783 T(0x30), T(0x31), T(0x32), T(0x33), T(0x34), T(0x35), T(0x36), T(0x37), |
|
1784 T(0x38), T(0x39), T(0x3a), T(0x3b), T(0x3c), T(0x3d), T(0x3e), T(0x3f), |
|
1785 T(0x40), T(0x41), T(0x42), T(0x43), T(0x44), T(0x45), T(0x46), T(0x47), |
|
1786 T(0x48), T(0x49), T(0x4a), T(0x4b), T(0x4c), T(0x4d), T(0x4e), T(0x4f), |
|
1787 T(0x50), T(0x51), T(0x52), T(0x53), T(0x54), T(0x55), T(0x56), T(0x57), |
|
1788 T(0x58), T(0x59), T(0x5a), T(0x5b), T(0x5c), T(0x5d), T(0x5e), T(0x5f), |
|
1789 T(0x60), T(0x61), T(0x62), T(0x63), T(0x64), T(0x65), T(0x66), T(0x67), |
|
1790 T(0x68), T(0x69), T(0x6a), T(0x6b), T(0x6c), T(0x6d), T(0x6e), T(0x6f), |
|
1791 T(0x70), T(0x71), T(0x72), T(0x73), T(0x74), T(0x75), T(0x76), T(0x77), |
|
1792 T(0x78), T(0x79), T(0x7a), T(0x7b), T(0x7c), T(0x7d), T(0x7e), T(0x7f), |
|
1793 T(0x80), T(0x81), T(0x82), T(0x83), T(0x84), T(0x85), T(0x86), T(0x87), |
|
1794 T(0x88), T(0x89), T(0x8a), T(0x8b), T(0x8c), T(0x8d), T(0x8e), T(0x8f), |
|
1795 T(0x90), T(0x91), T(0x92), T(0x93), T(0x94), T(0x95), T(0x96), T(0x97), |
|
1796 T(0x98), T(0x99), T(0x9a), T(0x9b), T(0x9c), T(0x9d), T(0x9e), T(0x9f), |
|
1797 T(0xa0), T(0xa1), T(0xa2), T(0xa3), T(0xa4), T(0xa5), T(0xa6), T(0xa7), |
|
1798 T(0xa8), T(0xa9), T(0xaa), T(0xab), T(0xac), T(0xad), T(0xae), T(0xaf), |
|
1799 T(0xb0), T(0xb1), T(0xb2), T(0xb3), T(0xb4), T(0xb5), T(0xb6), T(0xb7), |
|
1800 T(0xb8), T(0xb9), T(0xba), T(0xbb), T(0xbc), T(0xbd), T(0xbe), T(0xbf), |
|
1801 T(0xc0), T(0xc1), T(0xc2), T(0xc3), T(0xc4), T(0xc5), T(0xc6), T(0xc7), |
|
1802 T(0xc8), T(0xc9), T(0xca), T(0xcb), T(0xcc), T(0xcd), T(0xce), T(0xcf), |
|
1803 T(0xd0), T(0xd1), T(0xd2), T(0xd3), T(0xd4), T(0xd5), T(0xd6), T(0xd7), |
|
1804 T(0xd8), T(0xd9), T(0xda), T(0xdb), T(0xdc), T(0xdd), T(0xde), T(0xdf), |
|
1805 T(0xe0), T(0xe1), T(0xe2), T(0xe3), T(0xe4), T(0xe5), T(0xe6), T(0xe7), |
|
1806 T(0xe8), T(0xe9), T(0xea), T(0xeb), T(0xec), T(0xed), T(0xee), T(0xef), |
|
1807 T(0xf0), T(0xf1), T(0xf2), T(0xf3), T(0xf4), T(0xf5), T(0xf6), T(0xf7), |
|
1808 T(0xf8), T(0xf9), T(0xfa), T(0xfb), T(0xfc), T(0xfd), T(0xfe), 0x01000100 }; |
|
1809 #undef T |
|
1810 |
|
1811 void ARGBUnattenuateRow_C(const uint8* src_argb, uint8* dst_argb, int width) { |
|
1812 int i; |
|
1813 for (i = 0; i < width; ++i) { |
|
1814 uint32 b = src_argb[0]; |
|
1815 uint32 g = src_argb[1]; |
|
1816 uint32 r = src_argb[2]; |
|
1817 const uint32 a = src_argb[3]; |
|
1818 const uint32 ia = fixed_invtbl8[a] & 0xffff; // 8.8 fixed point |
|
1819 b = (b * ia) >> 8; |
|
1820 g = (g * ia) >> 8; |
|
1821 r = (r * ia) >> 8; |
|
1822 // Clamping should not be necessary but is free in assembly. |
|
1823 dst_argb[0] = clamp255(b); |
|
1824 dst_argb[1] = clamp255(g); |
|
1825 dst_argb[2] = clamp255(r); |
|
1826 dst_argb[3] = a; |
|
1827 src_argb += 4; |
|
1828 dst_argb += 4; |
|
1829 } |
|
1830 } |
|
1831 |
|
1832 void ComputeCumulativeSumRow_C(const uint8* row, int32* cumsum, |
|
1833 const int32* previous_cumsum, int width) { |
|
1834 int32 row_sum[4] = {0, 0, 0, 0}; |
|
1835 int x; |
|
1836 for (x = 0; x < width; ++x) { |
|
1837 row_sum[0] += row[x * 4 + 0]; |
|
1838 row_sum[1] += row[x * 4 + 1]; |
|
1839 row_sum[2] += row[x * 4 + 2]; |
|
1840 row_sum[3] += row[x * 4 + 3]; |
|
1841 cumsum[x * 4 + 0] = row_sum[0] + previous_cumsum[x * 4 + 0]; |
|
1842 cumsum[x * 4 + 1] = row_sum[1] + previous_cumsum[x * 4 + 1]; |
|
1843 cumsum[x * 4 + 2] = row_sum[2] + previous_cumsum[x * 4 + 2]; |
|
1844 cumsum[x * 4 + 3] = row_sum[3] + previous_cumsum[x * 4 + 3]; |
|
1845 } |
|
1846 } |
|
1847 |
|
1848 void CumulativeSumToAverageRow_C(const int32* tl, const int32* bl, |
|
1849 int w, int area, uint8* dst, int count) { |
|
1850 float ooa = 1.0f / area; |
|
1851 int i; |
|
1852 for (i = 0; i < count; ++i) { |
|
1853 dst[0] = (uint8)((bl[w + 0] + tl[0] - bl[0] - tl[w + 0]) * ooa); |
|
1854 dst[1] = (uint8)((bl[w + 1] + tl[1] - bl[1] - tl[w + 1]) * ooa); |
|
1855 dst[2] = (uint8)((bl[w + 2] + tl[2] - bl[2] - tl[w + 2]) * ooa); |
|
1856 dst[3] = (uint8)((bl[w + 3] + tl[3] - bl[3] - tl[w + 3]) * ooa); |
|
1857 dst += 4; |
|
1858 tl += 4; |
|
1859 bl += 4; |
|
1860 } |
|
1861 } |
|
1862 |
|
1863 // Copy pixels from rotated source to destination row with a slope. |
|
1864 LIBYUV_API |
|
1865 void ARGBAffineRow_C(const uint8* src_argb, int src_argb_stride, |
|
1866 uint8* dst_argb, const float* uv_dudv, int width) { |
|
1867 int i; |
|
1868 // Render a row of pixels from source into a buffer. |
|
1869 float uv[2]; |
|
1870 uv[0] = uv_dudv[0]; |
|
1871 uv[1] = uv_dudv[1]; |
|
1872 for (i = 0; i < width; ++i) { |
|
1873 int x = (int)(uv[0]); |
|
1874 int y = (int)(uv[1]); |
|
1875 *(uint32*)(dst_argb) = |
|
1876 *(const uint32*)(src_argb + y * src_argb_stride + |
|
1877 x * 4); |
|
1878 dst_argb += 4; |
|
1879 uv[0] += uv_dudv[2]; |
|
1880 uv[1] += uv_dudv[3]; |
|
1881 } |
|
1882 } |
|
1883 |
|
1884 // Blend 2 rows into 1 for conversions such as I422ToI420. |
|
1885 void HalfRow_C(const uint8* src_uv, int src_uv_stride, |
|
1886 uint8* dst_uv, int pix) { |
|
1887 int x; |
|
1888 for (x = 0; x < pix; ++x) { |
|
1889 dst_uv[x] = (src_uv[x] + src_uv[src_uv_stride + x] + 1) >> 1; |
|
1890 } |
|
1891 } |
|
1892 |
|
1893 // C version 2x2 -> 2x1. |
|
1894 void InterpolateRow_C(uint8* dst_ptr, const uint8* src_ptr, |
|
1895 ptrdiff_t src_stride, |
|
1896 int width, int source_y_fraction) { |
|
1897 int y1_fraction = source_y_fraction; |
|
1898 int y0_fraction = 256 - y1_fraction; |
|
1899 const uint8* src_ptr1 = src_ptr + src_stride; |
|
1900 int x; |
|
1901 if (source_y_fraction == 0) { |
|
1902 memcpy(dst_ptr, src_ptr, width); |
|
1903 return; |
|
1904 } |
|
1905 if (source_y_fraction == 128) { |
|
1906 HalfRow_C(src_ptr, (int)(src_stride), dst_ptr, width); |
|
1907 return; |
|
1908 } |
|
1909 for (x = 0; x < width - 1; x += 2) { |
|
1910 dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8; |
|
1911 dst_ptr[1] = (src_ptr[1] * y0_fraction + src_ptr1[1] * y1_fraction) >> 8; |
|
1912 src_ptr += 2; |
|
1913 src_ptr1 += 2; |
|
1914 dst_ptr += 2; |
|
1915 } |
|
1916 if (width & 1) { |
|
1917 dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8; |
|
1918 } |
|
1919 } |
|
1920 |
|
1921 // Select 2 channels from ARGB on alternating pixels. e.g. BGBGBGBG |
|
1922 void ARGBToBayerRow_C(const uint8* src_argb, |
|
1923 uint8* dst_bayer, uint32 selector, int pix) { |
|
1924 int index0 = selector & 0xff; |
|
1925 int index1 = (selector >> 8) & 0xff; |
|
1926 // Copy a row of Bayer. |
|
1927 int x; |
|
1928 for (x = 0; x < pix - 1; x += 2) { |
|
1929 dst_bayer[0] = src_argb[index0]; |
|
1930 dst_bayer[1] = src_argb[index1]; |
|
1931 src_argb += 8; |
|
1932 dst_bayer += 2; |
|
1933 } |
|
1934 if (pix & 1) { |
|
1935 dst_bayer[0] = src_argb[index0]; |
|
1936 } |
|
1937 } |
|
1938 |
|
1939 // Select G channel from ARGB. e.g. GGGGGGGG |
|
1940 void ARGBToBayerGGRow_C(const uint8* src_argb, |
|
1941 uint8* dst_bayer, uint32 selector, int pix) { |
|
1942 // Copy a row of G. |
|
1943 int x; |
|
1944 for (x = 0; x < pix - 1; x += 2) { |
|
1945 dst_bayer[0] = src_argb[1]; |
|
1946 dst_bayer[1] = src_argb[5]; |
|
1947 src_argb += 8; |
|
1948 dst_bayer += 2; |
|
1949 } |
|
1950 if (pix & 1) { |
|
1951 dst_bayer[0] = src_argb[1]; |
|
1952 } |
|
1953 } |
|
1954 |
|
1955 // Use first 4 shuffler values to reorder ARGB channels. |
|
1956 void ARGBShuffleRow_C(const uint8* src_argb, uint8* dst_argb, |
|
1957 const uint8* shuffler, int pix) { |
|
1958 int index0 = shuffler[0]; |
|
1959 int index1 = shuffler[1]; |
|
1960 int index2 = shuffler[2]; |
|
1961 int index3 = shuffler[3]; |
|
1962 // Shuffle a row of ARGB. |
|
1963 int x; |
|
1964 for (x = 0; x < pix; ++x) { |
|
1965 // To support in-place conversion. |
|
1966 uint8 b = src_argb[index0]; |
|
1967 uint8 g = src_argb[index1]; |
|
1968 uint8 r = src_argb[index2]; |
|
1969 uint8 a = src_argb[index3]; |
|
1970 dst_argb[0] = b; |
|
1971 dst_argb[1] = g; |
|
1972 dst_argb[2] = r; |
|
1973 dst_argb[3] = a; |
|
1974 src_argb += 4; |
|
1975 dst_argb += 4; |
|
1976 } |
|
1977 } |
|
1978 |
|
1979 void I422ToYUY2Row_C(const uint8* src_y, |
|
1980 const uint8* src_u, |
|
1981 const uint8* src_v, |
|
1982 uint8* dst_frame, int width) { |
|
1983 int x; |
|
1984 for (x = 0; x < width - 1; x += 2) { |
|
1985 dst_frame[0] = src_y[0]; |
|
1986 dst_frame[1] = src_u[0]; |
|
1987 dst_frame[2] = src_y[1]; |
|
1988 dst_frame[3] = src_v[0]; |
|
1989 dst_frame += 4; |
|
1990 src_y += 2; |
|
1991 src_u += 1; |
|
1992 src_v += 1; |
|
1993 } |
|
1994 if (width & 1) { |
|
1995 dst_frame[0] = src_y[0]; |
|
1996 dst_frame[1] = src_u[0]; |
|
1997 dst_frame[2] = src_y[0]; // duplicate last y |
|
1998 dst_frame[3] = src_v[0]; |
|
1999 } |
|
2000 } |
|
2001 |
|
2002 void I422ToUYVYRow_C(const uint8* src_y, |
|
2003 const uint8* src_u, |
|
2004 const uint8* src_v, |
|
2005 uint8* dst_frame, int width) { |
|
2006 int x; |
|
2007 for (x = 0; x < width - 1; x += 2) { |
|
2008 dst_frame[0] = src_u[0]; |
|
2009 dst_frame[1] = src_y[0]; |
|
2010 dst_frame[2] = src_v[0]; |
|
2011 dst_frame[3] = src_y[1]; |
|
2012 dst_frame += 4; |
|
2013 src_y += 2; |
|
2014 src_u += 1; |
|
2015 src_v += 1; |
|
2016 } |
|
2017 if (width & 1) { |
|
2018 dst_frame[0] = src_u[0]; |
|
2019 dst_frame[1] = src_y[0]; |
|
2020 dst_frame[2] = src_v[0]; |
|
2021 dst_frame[3] = src_y[0]; // duplicate last y |
|
2022 } |
|
2023 } |
|
2024 |
|
2025 #if !defined(LIBYUV_DISABLE_X86) && defined(HAS_I422TOARGBROW_SSSE3) |
|
2026 // row_win.cc has asm version, but GCC uses 2 step wrapper. |
|
2027 #if defined(__x86_64__) || defined(__i386__) |
|
2028 void I422ToRGB565Row_SSSE3(const uint8* src_y, |
|
2029 const uint8* src_u, |
|
2030 const uint8* src_v, |
|
2031 uint8* rgb_buf, |
|
2032 int width) { |
|
2033 // Allocate a row of ARGB. |
|
2034 align_buffer_64(row, width * 4); |
|
2035 I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width); |
|
2036 ARGBToRGB565Row_SSE2(row, rgb_buf, width); |
|
2037 free_aligned_buffer_64(row); |
|
2038 } |
|
2039 #endif // defined(__x86_64__) || defined(__i386__) |
|
2040 |
|
2041 #if defined(_M_IX86) || defined(__x86_64__) || defined(__i386__) |
|
2042 void I422ToARGB1555Row_SSSE3(const uint8* src_y, |
|
2043 const uint8* src_u, |
|
2044 const uint8* src_v, |
|
2045 uint8* rgb_buf, |
|
2046 int width) { |
|
2047 // Allocate a row of ARGB. |
|
2048 align_buffer_64(row, width * 4); |
|
2049 I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width); |
|
2050 ARGBToARGB1555Row_SSE2(row, rgb_buf, width); |
|
2051 free_aligned_buffer_64(row); |
|
2052 } |
|
2053 |
|
2054 void I422ToARGB4444Row_SSSE3(const uint8* src_y, |
|
2055 const uint8* src_u, |
|
2056 const uint8* src_v, |
|
2057 uint8* rgb_buf, |
|
2058 int width) { |
|
2059 // Allocate a row of ARGB. |
|
2060 align_buffer_64(row, width * 4); |
|
2061 I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width); |
|
2062 ARGBToARGB4444Row_SSE2(row, rgb_buf, width); |
|
2063 free_aligned_buffer_64(row); |
|
2064 } |
|
2065 |
|
2066 void NV12ToRGB565Row_SSSE3(const uint8* src_y, |
|
2067 const uint8* src_uv, |
|
2068 uint8* dst_rgb565, |
|
2069 int width) { |
|
2070 // Allocate a row of ARGB. |
|
2071 align_buffer_64(row, width * 4); |
|
2072 NV12ToARGBRow_SSSE3(src_y, src_uv, row, width); |
|
2073 ARGBToRGB565Row_SSE2(row, dst_rgb565, width); |
|
2074 free_aligned_buffer_64(row); |
|
2075 } |
|
2076 |
|
2077 void NV21ToRGB565Row_SSSE3(const uint8* src_y, |
|
2078 const uint8* src_vu, |
|
2079 uint8* dst_rgb565, |
|
2080 int width) { |
|
2081 // Allocate a row of ARGB. |
|
2082 align_buffer_64(row, width * 4); |
|
2083 NV21ToARGBRow_SSSE3(src_y, src_vu, row, width); |
|
2084 ARGBToRGB565Row_SSE2(row, dst_rgb565, width); |
|
2085 free_aligned_buffer_64(row); |
|
2086 } |
|
2087 |
|
2088 void YUY2ToARGBRow_SSSE3(const uint8* src_yuy2, |
|
2089 uint8* dst_argb, |
|
2090 int width) { |
|
2091 // Allocate a rows of yuv. |
|
2092 align_buffer_64(row_y, ((width + 63) & ~63) * 2); |
|
2093 uint8* row_u = row_y + ((width + 63) & ~63); |
|
2094 uint8* row_v = row_u + ((width + 63) & ~63) / 2; |
|
2095 YUY2ToUV422Row_SSE2(src_yuy2, row_u, row_v, width); |
|
2096 YUY2ToYRow_SSE2(src_yuy2, row_y, width); |
|
2097 I422ToARGBRow_SSSE3(row_y, row_u, row_v, dst_argb, width); |
|
2098 free_aligned_buffer_64(row_y); |
|
2099 } |
|
2100 |
|
2101 void YUY2ToARGBRow_Unaligned_SSSE3(const uint8* src_yuy2, |
|
2102 uint8* dst_argb, |
|
2103 int width) { |
|
2104 // Allocate a rows of yuv. |
|
2105 align_buffer_64(row_y, ((width + 63) & ~63) * 2); |
|
2106 uint8* row_u = row_y + ((width + 63) & ~63); |
|
2107 uint8* row_v = row_u + ((width + 63) & ~63) / 2; |
|
2108 YUY2ToUV422Row_Unaligned_SSE2(src_yuy2, row_u, row_v, width); |
|
2109 YUY2ToYRow_Unaligned_SSE2(src_yuy2, row_y, width); |
|
2110 I422ToARGBRow_Unaligned_SSSE3(row_y, row_u, row_v, dst_argb, width); |
|
2111 free_aligned_buffer_64(row_y); |
|
2112 } |
|
2113 |
|
2114 void UYVYToARGBRow_SSSE3(const uint8* src_uyvy, |
|
2115 uint8* dst_argb, |
|
2116 int width) { |
|
2117 // Allocate a rows of yuv. |
|
2118 align_buffer_64(row_y, ((width + 63) & ~63) * 2); |
|
2119 uint8* row_u = row_y + ((width + 63) & ~63); |
|
2120 uint8* row_v = row_u + ((width + 63) & ~63) / 2; |
|
2121 UYVYToUV422Row_SSE2(src_uyvy, row_u, row_v, width); |
|
2122 UYVYToYRow_SSE2(src_uyvy, row_y, width); |
|
2123 I422ToARGBRow_SSSE3(row_y, row_u, row_v, dst_argb, width); |
|
2124 free_aligned_buffer_64(row_y); |
|
2125 } |
|
2126 |
|
2127 void UYVYToARGBRow_Unaligned_SSSE3(const uint8* src_uyvy, |
|
2128 uint8* dst_argb, |
|
2129 int width) { |
|
2130 // Allocate a rows of yuv. |
|
2131 align_buffer_64(row_y, ((width + 63) & ~63) * 2); |
|
2132 uint8* row_u = row_y + ((width + 63) & ~63); |
|
2133 uint8* row_v = row_u + ((width + 63) & ~63) / 2; |
|
2134 UYVYToUV422Row_Unaligned_SSE2(src_uyvy, row_u, row_v, width); |
|
2135 UYVYToYRow_Unaligned_SSE2(src_uyvy, row_y, width); |
|
2136 I422ToARGBRow_Unaligned_SSSE3(row_y, row_u, row_v, dst_argb, width); |
|
2137 free_aligned_buffer_64(row_y); |
|
2138 } |
|
2139 |
|
2140 #endif // defined(_M_IX86) || defined(__x86_64__) || defined(__i386__) |
|
2141 #endif // !defined(LIBYUV_DISABLE_X86) |
|
2142 |
|
2143 void ARGBPolynomialRow_C(const uint8* src_argb, |
|
2144 uint8* dst_argb, const float* poly, |
|
2145 int width) { |
|
2146 int i; |
|
2147 for (i = 0; i < width; ++i) { |
|
2148 float b = (float)(src_argb[0]); |
|
2149 float g = (float)(src_argb[1]); |
|
2150 float r = (float)(src_argb[2]); |
|
2151 float a = (float)(src_argb[3]); |
|
2152 float b2 = b * b; |
|
2153 float g2 = g * g; |
|
2154 float r2 = r * r; |
|
2155 float a2 = a * a; |
|
2156 float db = poly[0] + poly[4] * b; |
|
2157 float dg = poly[1] + poly[5] * g; |
|
2158 float dr = poly[2] + poly[6] * r; |
|
2159 float da = poly[3] + poly[7] * a; |
|
2160 float b3 = b2 * b; |
|
2161 float g3 = g2 * g; |
|
2162 float r3 = r2 * r; |
|
2163 float a3 = a2 * a; |
|
2164 db += poly[8] * b2; |
|
2165 dg += poly[9] * g2; |
|
2166 dr += poly[10] * r2; |
|
2167 da += poly[11] * a2; |
|
2168 db += poly[12] * b3; |
|
2169 dg += poly[13] * g3; |
|
2170 dr += poly[14] * r3; |
|
2171 da += poly[15] * a3; |
|
2172 |
|
2173 dst_argb[0] = Clamp((int32)(db)); |
|
2174 dst_argb[1] = Clamp((int32)(dg)); |
|
2175 dst_argb[2] = Clamp((int32)(dr)); |
|
2176 dst_argb[3] = Clamp((int32)(da)); |
|
2177 src_argb += 4; |
|
2178 dst_argb += 4; |
|
2179 } |
|
2180 } |
|
2181 |
|
2182 void ARGBLumaColorTableRow_C(const uint8* src_argb, uint8* dst_argb, int width, |
|
2183 const uint8* luma, uint32 lumacoeff) { |
|
2184 uint32 bc = lumacoeff & 0xff; |
|
2185 uint32 gc = (lumacoeff >> 8) & 0xff; |
|
2186 uint32 rc = (lumacoeff >> 16) & 0xff; |
|
2187 |
|
2188 int i; |
|
2189 for (i = 0; i < width - 1; i += 2) { |
|
2190 // Luminance in rows, color values in columns. |
|
2191 const uint8* luma0 = ((src_argb[0] * bc + src_argb[1] * gc + |
|
2192 src_argb[2] * rc) & 0x7F00u) + luma; |
|
2193 const uint8* luma1; |
|
2194 dst_argb[0] = luma0[src_argb[0]]; |
|
2195 dst_argb[1] = luma0[src_argb[1]]; |
|
2196 dst_argb[2] = luma0[src_argb[2]]; |
|
2197 dst_argb[3] = src_argb[3]; |
|
2198 luma1 = ((src_argb[4] * bc + src_argb[5] * gc + |
|
2199 src_argb[6] * rc) & 0x7F00u) + luma; |
|
2200 dst_argb[4] = luma1[src_argb[4]]; |
|
2201 dst_argb[5] = luma1[src_argb[5]]; |
|
2202 dst_argb[6] = luma1[src_argb[6]]; |
|
2203 dst_argb[7] = src_argb[7]; |
|
2204 src_argb += 8; |
|
2205 dst_argb += 8; |
|
2206 } |
|
2207 if (width & 1) { |
|
2208 // Luminance in rows, color values in columns. |
|
2209 const uint8* luma0 = ((src_argb[0] * bc + src_argb[1] * gc + |
|
2210 src_argb[2] * rc) & 0x7F00u) + luma; |
|
2211 dst_argb[0] = luma0[src_argb[0]]; |
|
2212 dst_argb[1] = luma0[src_argb[1]]; |
|
2213 dst_argb[2] = luma0[src_argb[2]]; |
|
2214 dst_argb[3] = src_argb[3]; |
|
2215 } |
|
2216 } |
|
2217 |
|
2218 void ARGBCopyAlphaRow_C(const uint8* src, uint8* dst, int width) { |
|
2219 int i; |
|
2220 for (i = 0; i < width - 1; i += 2) { |
|
2221 dst[3] = src[3]; |
|
2222 dst[7] = src[7]; |
|
2223 dst += 8; |
|
2224 src += 8; |
|
2225 } |
|
2226 if (width & 1) { |
|
2227 dst[3] = src[3]; |
|
2228 } |
|
2229 } |
|
2230 |
|
2231 void ARGBCopyYToAlphaRow_C(const uint8* src, uint8* dst, int width) { |
|
2232 int i; |
|
2233 for (i = 0; i < width - 1; i += 2) { |
|
2234 dst[3] = src[0]; |
|
2235 dst[7] = src[1]; |
|
2236 dst += 8; |
|
2237 src += 2; |
|
2238 } |
|
2239 if (width & 1) { |
|
2240 dst[3] = src[0]; |
|
2241 } |
|
2242 } |
|
2243 |
|
2244 #ifdef __cplusplus |
|
2245 } // extern "C" |
|
2246 } // namespace libyuv |
|
2247 #endif |