3237 lines · 103.5 KB · C++
RawDownload
/* *  Copyright 2011 The LibYuv Project Authors. All rights reserved. * *  Use of this source code is governed by a BSD-style license *  that can be found in the LICENSE file in the root of the source *  tree. An additional intellectual property rights grant can be found *  in the file PATENTS. All contributing project authors may *  be found in the AUTHORS file in the root of the source tree. */ #include "libyuv/row.h" #include <stdio.h>#include <string.h>  // For memcpy and memset. #include "libyuv/basic_types.h" #ifdef __cplusplusnamespace libyuv {extern "C" {#endif // llvm x86 is poor at ternary operator, so use branchless min/max. #define USE_BRANCHLESS 1#if USE_BRANCHLESSstatic __inline int32_t clamp0(int32_t v) {  return ((-(v) >> 31) & (v));} static __inline int32_t clamp255(int32_t v) {  return (((255 - (v)) >> 31) | (v)) & 255;} static __inline int32_t clamp1023(int32_t v) {  return (((1023 - (v)) >> 31) | (v)) & 1023;} static __inline uint32_t Abs(int32_t v) {  int m = v >> 31;  return (v + m) ^ m;}#else   // USE_BRANCHLESSstatic __inline int32_t clamp0(int32_t v) {  return (v < 0) ? 0 : v;} static __inline int32_t clamp255(int32_t v) {  return (v > 255) ? 255 : v;} static __inline int32_t clamp1023(int32_t v) {  return (v > 1023) ? 1023 : v;} static __inline uint32_t Abs(int32_t v) {  return (v < 0) ? -v : v;}#endif  // USE_BRANCHLESSstatic __inline uint32_t Clamp(int32_t val) {  int v = clamp0(val);  return (uint32_t)(clamp255(v));} static __inline uint32_t Clamp10(int32_t val) {  int v = clamp0(val);  return (uint32_t)(clamp1023(v));} // Little Endian#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \    defined(_M_IX86) || defined(__arm__) || defined(_M_ARM) ||     \    (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)#define WRITEWORD(p, v) *(uint32_t*)(p) = v#elsestatic inline void WRITEWORD(uint8_t* p, uint32_t v) {  p[0] = (uint8_t)(v & 255);  p[1] = (uint8_t)((v >> 8) & 255);  p[2] = (uint8_t)((v >> 16) & 255);  p[3] = (uint8_t)((v >> 24) & 255);}#endif void RGB24ToARGBRow_C(const uint8_t* src_rgb24, uint8_t* dst_argb, int width) {  int x;  for (x = 0; x < width; ++x) {    uint8_t b = src_rgb24[0];    uint8_t g = src_rgb24[1];    uint8_t r = src_rgb24[2];    dst_argb[0] = b;    dst_argb[1] = g;    dst_argb[2] = r;    dst_argb[3] = 255u;    dst_argb += 4;    src_rgb24 += 3;  }} void RAWToARGBRow_C(const uint8_t* src_raw, uint8_t* dst_argb, int width) {  int x;  for (x = 0; x < width; ++x) {    uint8_t r = src_raw[0];    uint8_t g = src_raw[1];    uint8_t b = src_raw[2];    dst_argb[0] = b;    dst_argb[1] = g;    dst_argb[2] = r;    dst_argb[3] = 255u;    dst_argb += 4;    src_raw += 3;  }} void RAWToRGB24Row_C(const uint8_t* src_raw, uint8_t* dst_rgb24, int width) {  int x;  for (x = 0; x < width; ++x) {    uint8_t r = src_raw[0];    uint8_t g = src_raw[1];    uint8_t b = src_raw[2];    dst_rgb24[0] = b;    dst_rgb24[1] = g;    dst_rgb24[2] = r;    dst_rgb24 += 3;    src_raw += 3;  }} void RGB565ToARGBRow_C(const uint8_t* src_rgb565,                       uint8_t* dst_argb,                       int width) {  int x;  for (x = 0; x < width; ++x) {    uint8_t b = src_rgb565[0] & 0x1f;    uint8_t g = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3);    uint8_t r = src_rgb565[1] >> 3;    dst_argb[0] = (b << 3) | (b >> 2);    dst_argb[1] = (g << 2) | (g >> 4);    dst_argb[2] = (r << 3) | (r >> 2);    dst_argb[3] = 255u;    dst_argb += 4;    src_rgb565 += 2;  }} void ARGB1555ToARGBRow_C(const uint8_t* src_argb1555,                         uint8_t* dst_argb,                         int width) {  int x;  for (x = 0; x < width; ++x) {    uint8_t b = src_argb1555[0] & 0x1f;    uint8_t g = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3);    uint8_t r = (src_argb1555[1] & 0x7c) >> 2;    uint8_t a = src_argb1555[1] >> 7;    dst_argb[0] = (b << 3) | (b >> 2);    dst_argb[1] = (g << 3) | (g >> 2);    dst_argb[2] = (r << 3) | (r >> 2);    dst_argb[3] = -a;    dst_argb += 4;    src_argb1555 += 2;  }} void ARGB4444ToARGBRow_C(const uint8_t* src_argb4444,                         uint8_t* dst_argb,                         int width) {  int x;  for (x = 0; x < width; ++x) {    uint8_t b = src_argb4444[0] & 0x0f;    uint8_t g = src_argb4444[0] >> 4;    uint8_t r = src_argb4444[1] & 0x0f;    uint8_t a = src_argb4444[1] >> 4;    dst_argb[0] = (b << 4) | b;    dst_argb[1] = (g << 4) | g;    dst_argb[2] = (r << 4) | r;    dst_argb[3] = (a << 4) | a;    dst_argb += 4;    src_argb4444 += 2;  }} void AR30ToARGBRow_C(const uint8_t* src_ar30, uint8_t* dst_argb, int width) {  int x;  for (x = 0; x < width; ++x) {    uint32_t ar30 = *(const uint32_t*)src_ar30;    uint32_t b = (ar30 >> 2) & 0xff;    uint32_t g = (ar30 >> 12) & 0xff;    uint32_t r = (ar30 >> 22) & 0xff;    uint32_t a = (ar30 >> 30) * 0x55;  // Replicate 2 bits to 8 bits.    *(uint32_t*)(dst_argb) = b | (g << 8) | (r << 16) | (a << 24);    dst_argb += 4;    src_ar30 += 4;  }} void AR30ToABGRRow_C(const uint8_t* src_ar30, uint8_t* dst_abgr, int width) {  int x;  for (x = 0; x < width; ++x) {    uint32_t ar30 = *(const uint32_t*)src_ar30;    uint32_t b = (ar30 >> 2) & 0xff;    uint32_t g = (ar30 >> 12) & 0xff;    uint32_t r = (ar30 >> 22) & 0xff;    uint32_t a = (ar30 >> 30) * 0x55;  // Replicate 2 bits to 8 bits.    *(uint32_t*)(dst_abgr) = r | (g << 8) | (b << 16) | (a << 24);    dst_abgr += 4;    src_ar30 += 4;  }} void AR30ToAB30Row_C(const uint8_t* src_ar30, uint8_t* dst_ab30, int width) {  int x;  for (x = 0; x < width; ++x) {    uint32_t ar30 = *(const uint32_t*)src_ar30;    uint32_t b = ar30 & 0x3ff;    uint32_t ga = ar30 & 0xc00ffc00;    uint32_t r = (ar30 >> 20) & 0x3ff;    *(uint32_t*)(dst_ab30) = r | ga | (b << 20);    dst_ab30 += 4;    src_ar30 += 4;  }} void ARGBToRGB24Row_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width) {  int x;  for (x = 0; x < width; ++x) {    uint8_t b = src_argb[0];    uint8_t g = src_argb[1];    uint8_t r = src_argb[2];    dst_rgb[0] = b;    dst_rgb[1] = g;    dst_rgb[2] = r;    dst_rgb += 3;    src_argb += 4;  }} void ARGBToRAWRow_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width) {  int x;  for (x = 0; x < width; ++x) {    uint8_t b = src_argb[0];    uint8_t g = src_argb[1];    uint8_t r = src_argb[2];    dst_rgb[0] = r;    dst_rgb[1] = g;    dst_rgb[2] = b;    dst_rgb += 3;    src_argb += 4;  }} void ARGBToRGB565Row_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width) {  int x;  for (x = 0; x < width - 1; x += 2) {    uint8_t b0 = src_argb[0] >> 3;    uint8_t g0 = src_argb[1] >> 2;    uint8_t r0 = src_argb[2] >> 3;    uint8_t b1 = src_argb[4] >> 3;    uint8_t g1 = src_argb[5] >> 2;    uint8_t r1 = src_argb[6] >> 3;    WRITEWORD(dst_rgb, b0 | (g0 << 5) | (r0 << 11) | (b1 << 16) | (g1 << 21) |                           (r1 << 27));    dst_rgb += 4;    src_argb += 8;  }  if (width & 1) {    uint8_t b0 = src_argb[0] >> 3;    uint8_t g0 = src_argb[1] >> 2;    uint8_t r0 = src_argb[2] >> 3;    *(uint16_t*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 11);  }} // dither4 is a row of 4 values from 4x4 dither matrix.// The 4x4 matrix contains values to increase RGB.  When converting to// fewer bits (565) this provides an ordered dither.// The order in the 4x4 matrix in first byte is upper left.// The 4 values are passed as an int, then referenced as an array, so// endian will not affect order of the original matrix.  But the dither4// will containing the first pixel in the lower byte for little endian// or the upper byte for big endian.void ARGBToRGB565DitherRow_C(const uint8_t* src_argb,                             uint8_t* dst_rgb,                             const uint32_t dither4,                             int width) {  int x;  for (x = 0; x < width - 1; x += 2) {    int dither0 = ((const unsigned char*)(&dither4))[x & 3];    int dither1 = ((const unsigned char*)(&dither4))[(x + 1) & 3];    uint8_t b0 = clamp255(src_argb[0] + dither0) >> 3;    uint8_t g0 = clamp255(src_argb[1] + dither0) >> 2;    uint8_t r0 = clamp255(src_argb[2] + dither0) >> 3;    uint8_t b1 = clamp255(src_argb[4] + dither1) >> 3;    uint8_t g1 = clamp255(src_argb[5] + dither1) >> 2;    uint8_t r1 = clamp255(src_argb[6] + dither1) >> 3;    WRITEWORD(dst_rgb, b0 | (g0 << 5) | (r0 << 11) | (b1 << 16) | (g1 << 21) |                           (r1 << 27));    dst_rgb += 4;    src_argb += 8;  }  if (width & 1) {    int dither0 = ((const unsigned char*)(&dither4))[(width - 1) & 3];    uint8_t b0 = clamp255(src_argb[0] + dither0) >> 3;    uint8_t g0 = clamp255(src_argb[1] + dither0) >> 2;    uint8_t r0 = clamp255(src_argb[2] + dither0) >> 3;    *(uint16_t*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 11);  }} void ARGBToARGB1555Row_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width) {  int x;  for (x = 0; x < width - 1; x += 2) {    uint8_t b0 = src_argb[0] >> 3;    uint8_t g0 = src_argb[1] >> 3;    uint8_t r0 = src_argb[2] >> 3;    uint8_t a0 = src_argb[3] >> 7;    uint8_t b1 = src_argb[4] >> 3;    uint8_t g1 = src_argb[5] >> 3;    uint8_t r1 = src_argb[6] >> 3;    uint8_t a1 = src_argb[7] >> 7;    *(uint32_t*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 10) | (a0 << 15) |                            (b1 << 16) | (g1 << 21) | (r1 << 26) | (a1 << 31);    dst_rgb += 4;    src_argb += 8;  }  if (width & 1) {    uint8_t b0 = src_argb[0] >> 3;    uint8_t g0 = src_argb[1] >> 3;    uint8_t r0 = src_argb[2] >> 3;    uint8_t a0 = src_argb[3] >> 7;    *(uint16_t*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 10) | (a0 << 15);  }} void ARGBToARGB4444Row_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width) {  int x;  for (x = 0; x < width - 1; x += 2) {    uint8_t b0 = src_argb[0] >> 4;    uint8_t g0 = src_argb[1] >> 4;    uint8_t r0 = src_argb[2] >> 4;    uint8_t a0 = src_argb[3] >> 4;    uint8_t b1 = src_argb[4] >> 4;    uint8_t g1 = src_argb[5] >> 4;    uint8_t r1 = src_argb[6] >> 4;    uint8_t a1 = src_argb[7] >> 4;    *(uint32_t*)(dst_rgb) = b0 | (g0 << 4) | (r0 << 8) | (a0 << 12) |                            (b1 << 16) | (g1 << 20) | (r1 << 24) | (a1 << 28);    dst_rgb += 4;    src_argb += 8;  }  if (width & 1) {    uint8_t b0 = src_argb[0] >> 4;    uint8_t g0 = src_argb[1] >> 4;    uint8_t r0 = src_argb[2] >> 4;    uint8_t a0 = src_argb[3] >> 4;    *(uint16_t*)(dst_rgb) = b0 | (g0 << 4) | (r0 << 8) | (a0 << 12);  }} void ABGRToAR30Row_C(const uint8_t* src_abgr, uint8_t* dst_ar30, int width) {  int x;  for (x = 0; x < width; ++x) {    uint32_t b0 = (src_abgr[0] >> 6) | ((uint32_t)(src_abgr[0]) << 2);    uint32_t g0 = (src_abgr[1] >> 6) | ((uint32_t)(src_abgr[1]) << 2);    uint32_t r0 = (src_abgr[2] >> 6) | ((uint32_t)(src_abgr[2]) << 2);    uint32_t a0 = (src_abgr[3] >> 6);    *(uint32_t*)(dst_ar30) = r0 | (g0 << 10) | (b0 << 20) | (a0 << 30);    dst_ar30 += 4;    src_abgr += 4;  }} void ARGBToAR30Row_C(const uint8_t* src_argb, uint8_t* dst_ar30, int width) {  int x;  for (x = 0; x < width; ++x) {    uint32_t b0 = (src_argb[0] >> 6) | ((uint32_t)(src_argb[0]) << 2);    uint32_t g0 = (src_argb[1] >> 6) | ((uint32_t)(src_argb[1]) << 2);    uint32_t r0 = (src_argb[2] >> 6) | ((uint32_t)(src_argb[2]) << 2);    uint32_t a0 = (src_argb[3] >> 6);    *(uint32_t*)(dst_ar30) = b0 | (g0 << 10) | (r0 << 20) | (a0 << 30);    dst_ar30 += 4;    src_argb += 4;  }} static __inline int RGBToY(uint8_t r, uint8_t g, uint8_t b) {  return (66 * r + 129 * g + 25 * b + 0x1080) >> 8;} static __inline int RGBToU(uint8_t r, uint8_t g, uint8_t b) {  return (112 * b - 74 * g - 38 * r + 0x8080) >> 8;}static __inline int RGBToV(uint8_t r, uint8_t g, uint8_t b) {  return (112 * r - 94 * g - 18 * b + 0x8080) >> 8;} // ARGBToY_C and ARGBToUV_C#define MAKEROWY(NAME, R, G, B, BPP)                                         \  void NAME##ToYRow_C(const uint8_t* src_argb0, uint8_t* dst_y, int width) { \    int x;                                                                   \    for (x = 0; x < width; ++x) {                                            \      dst_y[0] = RGBToY(src_argb0[R], src_argb0[G], src_argb0[B]);           \      src_argb0 += BPP;                                                      \      dst_y += 1;                                                            \    }                                                                        \  }                                                                          \  void NAME##ToUVRow_C(const uint8_t* src_rgb0, int src_stride_rgb,          \                       uint8_t* dst_u, uint8_t* dst_v, int width) {          \    const uint8_t* src_rgb1 = src_rgb0 + src_stride_rgb;                     \    int x;                                                                   \    for (x = 0; x < width - 1; x += 2) {                                     \      uint8_t ab = (src_rgb0[B] + src_rgb0[B + BPP] + src_rgb1[B] +          \                    src_rgb1[B + BPP]) >>                                    \                   2;                                                        \      uint8_t ag = (src_rgb0[G] + src_rgb0[G + BPP] + src_rgb1[G] +          \                    src_rgb1[G + BPP]) >>                                    \                   2;                                                        \      uint8_t ar = (src_rgb0[R] + src_rgb0[R + BPP] + src_rgb1[R] +          \                    src_rgb1[R + BPP]) >>                                    \                   2;                                                        \      dst_u[0] = RGBToU(ar, ag, ab);                                         \      dst_v[0] = RGBToV(ar, ag, ab);                                         \      src_rgb0 += BPP * 2;                                                   \      src_rgb1 += BPP * 2;                                                   \      dst_u += 1;                                                            \      dst_v += 1;                                                            \    }                                                                        \    if (width & 1) {                                                         \      uint8_t ab = (src_rgb0[B] + src_rgb1[B]) >> 1;                         \      uint8_t ag = (src_rgb0[G] + src_rgb1[G]) >> 1;                         \      uint8_t ar = (src_rgb0[R] + src_rgb1[R]) >> 1;                         \      dst_u[0] = RGBToU(ar, ag, ab);                                         \      dst_v[0] = RGBToV(ar, ag, ab);                                         \    }                                                                        \  } MAKEROWY(ARGB, 2, 1, 0, 4)MAKEROWY(BGRA, 1, 2, 3, 4)MAKEROWY(ABGR, 0, 1, 2, 4)MAKEROWY(RGBA, 3, 2, 1, 4)MAKEROWY(RGB24, 2, 1, 0, 3)MAKEROWY(RAW, 0, 1, 2, 3)#undef MAKEROWY // JPeg uses a variation on BT.601-1 full range// y =  0.29900 * r + 0.58700 * g + 0.11400 * b// u = -0.16874 * r - 0.33126 * g + 0.50000 * b  + center// v =  0.50000 * r - 0.41869 * g - 0.08131 * b  + center// BT.601 Mpeg range uses:// b 0.1016 * 255 = 25.908 = 25// g 0.5078 * 255 = 129.489 = 129// r 0.2578 * 255 = 65.739 = 66// JPeg 8 bit Y (not used):// b 0.11400 * 256 = 29.184 = 29// g 0.58700 * 256 = 150.272 = 150// r 0.29900 * 256 = 76.544 = 77// JPeg 7 bit Y:// b 0.11400 * 128 = 14.592 = 15// g 0.58700 * 128 = 75.136 = 75// r 0.29900 * 128 = 38.272 = 38// JPeg 8 bit U:// b  0.50000 * 255 = 127.5 = 127// g -0.33126 * 255 = -84.4713 = -84// r -0.16874 * 255 = -43.0287 = -43// JPeg 8 bit V:// b -0.08131 * 255 = -20.73405 = -20// g -0.41869 * 255 = -106.76595 = -107// r  0.50000 * 255 = 127.5 = 127 static __inline int RGBToYJ(uint8_t r, uint8_t g, uint8_t b) {  return (38 * r + 75 * g + 15 * b + 64) >> 7;} static __inline int RGBToUJ(uint8_t r, uint8_t g, uint8_t b) {  return (127 * b - 84 * g - 43 * r + 0x8080) >> 8;}static __inline int RGBToVJ(uint8_t r, uint8_t g, uint8_t b) {  return (127 * r - 107 * g - 20 * b + 0x8080) >> 8;} #define AVGB(a, b) (((a) + (b) + 1) >> 1) // ARGBToYJ_C and ARGBToUVJ_C#define MAKEROWYJ(NAME, R, G, B, BPP)                                         \  void NAME##ToYJRow_C(const uint8_t* src_argb0, uint8_t* dst_y, int width) { \    int x;                                                                    \    for (x = 0; x < width; ++x) {                                             \      dst_y[0] = RGBToYJ(src_argb0[R], src_argb0[G], src_argb0[B]);           \      src_argb0 += BPP;                                                       \      dst_y += 1;                                                             \    }                                                                         \  }                                                                           \  void NAME##ToUVJRow_C(const uint8_t* src_rgb0, int src_stride_rgb,          \                        uint8_t* dst_u, uint8_t* dst_v, int width) {          \    const uint8_t* src_rgb1 = src_rgb0 + src_stride_rgb;                      \    int x;                                                                    \    for (x = 0; x < width - 1; x += 2) {                                      \      uint8_t ab = AVGB(AVGB(src_rgb0[B], src_rgb1[B]),                       \                        AVGB(src_rgb0[B + BPP], src_rgb1[B + BPP]));          \      uint8_t ag = AVGB(AVGB(src_rgb0[G], src_rgb1[G]),                       \                        AVGB(src_rgb0[G + BPP], src_rgb1[G + BPP]));          \      uint8_t ar = AVGB(AVGB(src_rgb0[R], src_rgb1[R]),                       \

Lines 1–500 of 3237.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t