media/libyuv/source/row_common.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial