Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 |