diff --git a/README.chromium b/README.chromium index 752bc5d4b..66046f5c7 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 621 +Version: 622 License: BSD License File: LICENSE diff --git a/include/libyuv/convert_from_argb.h b/include/libyuv/convert_from_argb.h index a7bfe481d..be3bba444 100644 --- a/include/libyuv/convert_from_argb.h +++ b/include/libyuv/convert_from_argb.h @@ -99,6 +99,14 @@ int ARGBToI420(const uint8* src_argb, int src_stride_argb, uint8* dst_v, int dst_stride_v, int width, int height); +// Convert ARGB to J420. (JPeg full range I420). +LIBYUV_API +int ARGBToJ420(const uint8* src_argb, int src_stride_argb, + uint8* dst_yj, int dst_stride_yj, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height); + // Convert ARGB To I411. LIBYUV_API int ARGBToI411(const uint8* src_argb, int src_stride_argb, @@ -107,6 +115,12 @@ int ARGBToI411(const uint8* src_argb, int src_stride_argb, uint8* dst_v, int dst_stride_v, int width, int height); +// Convert ARGB to J400. (JPeg full range). +LIBYUV_API +int ARGBToJ400(const uint8* src_argb, int src_stride_argb, + uint8* dst_yj, int dst_stride_yj, + int width, int height); + // Convert ARGB to I400. LIBYUV_API int ARGBToI400(const uint8* src_argb, int src_stride_argb, diff --git a/include/libyuv/row.h b/include/libyuv/row.h index 0d3848974..9f0b07ea3 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -55,6 +55,7 @@ extern "C" { #define HAS_ARGBTOUV444ROW_SSSE3 #define HAS_ARGBTOUVROW_SSSE3 #define HAS_ARGBTOYROW_SSSE3 +#define HAS_ARGBTOYJROW_SSSE3 #define HAS_BGRATOUVROW_SSSE3 #define HAS_BGRATOYROW_SSSE3 #define HAS_COPYROW_SSE2 @@ -203,6 +204,7 @@ extern "C" { #define HAS_ARGBTOUV444ROW_NEON #define HAS_ARGBTOUVROW_NEON #define HAS_ARGBTOYROW_NEON +#define HAS_ARGBTOYJROW_NEON #define HAS_BGRATOUVROW_NEON #define HAS_BGRATOYROW_NEON #define HAS_COPYROW_NEON @@ -398,18 +400,21 @@ void UYVYToARGBRow_NEON(const uint8* src_uyvy, void ARGBToYRow_AVX2(const uint8* src_argb, uint8* dst_y, int pix); void ARGBToYRow_Any_AVX2(const uint8* src_argb, uint8* dst_y, int pix); void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); +void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); void BGRAToYRow_SSSE3(const uint8* src_bgra, uint8* dst_y, int pix); void ABGRToYRow_SSSE3(const uint8* src_abgr, uint8* dst_y, int pix); void RGBAToYRow_SSSE3(const uint8* src_rgba, uint8* dst_y, int pix); void RGB24ToYRow_SSSE3(const uint8* src_rgb24, uint8* dst_y, int pix); void RAWToYRow_SSSE3(const uint8* src_raw, uint8* dst_y, int pix); void ARGBToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); +void ARGBToYJRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); void BGRAToYRow_Unaligned_SSSE3(const uint8* src_bgra, uint8* dst_y, int pix); void ABGRToYRow_Unaligned_SSSE3(const uint8* src_abgr, uint8* dst_y, int pix); void RGBAToYRow_Unaligned_SSSE3(const uint8* src_rgba, uint8* dst_y, int pix); void RGB24ToYRow_Unaligned_SSSE3(const uint8* src_rgb24, uint8* dst_y, int pix); void RAWToYRow_Unaligned_SSSE3(const uint8* src_raw, uint8* dst_y, int pix); void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int pix); +void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int pix); void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int pix); void ARGBToUV422Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, @@ -443,6 +448,7 @@ void RGB565ToYRow_NEON(const uint8* src_rgb565, uint8* dst_y, int pix); void ARGB1555ToYRow_NEON(const uint8* src_argb1555, uint8* dst_y, int pix); void ARGB4444ToYRow_NEON(const uint8* src_argb4444, uint8* dst_y, int pix); void ARGBToYRow_C(const uint8* src_argb, uint8* dst_y, int pix); +void ARGBToYJRow_C(const uint8* src_argb, uint8* dst_y, int pix); void BGRAToYRow_C(const uint8* src_bgra, uint8* dst_y, int pix); void ABGRToYRow_C(const uint8* src_abgr, uint8* dst_y, int pix); void RGBAToYRow_C(const uint8* src_rgba, uint8* dst_y, int pix); @@ -452,12 +458,14 @@ void RGB565ToYRow_C(const uint8* src_rgb565, uint8* dst_y, int pix); void ARGB1555ToYRow_C(const uint8* src_argb1555, uint8* dst_y, int pix); void ARGB4444ToYRow_C(const uint8* src_argb4444, uint8* dst_y, int pix); void ARGBToYRow_Any_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); +void ARGBToYJRow_Any_SSSE3(const uint8* src_argb, uint8* dst_y, int pix); void BGRAToYRow_Any_SSSE3(const uint8* src_bgra, uint8* dst_y, int pix); void ABGRToYRow_Any_SSSE3(const uint8* src_abgr, uint8* dst_y, int pix); void RGBAToYRow_Any_SSSE3(const uint8* src_rgba, uint8* dst_y, int pix); void RGB24ToYRow_Any_SSSE3(const uint8* src_rgb24, uint8* dst_y, int pix); void RAWToYRow_Any_SSSE3(const uint8* src_raw, uint8* dst_y, int pix); void ARGBToYRow_Any_NEON(const uint8* src_argb, uint8* dst_y, int pix); +void ARGBToYJRow_Any_NEON(const uint8* src_argb, uint8* dst_y, int pix); void BGRAToYRow_Any_NEON(const uint8* src_bgra, uint8* dst_y, int pix); void ABGRToYRow_Any_NEON(const uint8* src_abgr, uint8* dst_y, int pix); void RGBAToYRow_Any_NEON(const uint8* src_rgba, uint8* dst_y, int pix); diff --git a/include/libyuv/version.h b/include/libyuv/version.h index ab5216c27..2b2e4ce91 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 621 +#define LIBYUV_VERSION 622 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/convert_from_argb.cc b/source/convert_from_argb.cc index 79ed48645..57cda4c85 100644 --- a/source/convert_from_argb.cc +++ b/source/convert_from_argb.cc @@ -976,6 +976,126 @@ int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb, return 0; } +// Convert ARGB to J420. (JPeg full range I420). +LIBYUV_API +int ARGBToJ420(const uint8* src_argb, int src_stride_argb, + uint8* dst_yj, int dst_stride_yj, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height) { + if (!src_argb || + !dst_yj || !dst_u || !dst_v || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_argb = src_argb + (height - 1) * src_stride_argb; + src_stride_argb = -src_stride_argb; + } + void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, + uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; + void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) = + ARGBToYJRow_C; +#if defined(HAS_ARGBTOYJROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + ARGBToUVRow = ARGBToUVRow_Any_SSSE3; + ARGBToYJRow = ARGBToYJRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3; + ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3; + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { + ARGBToUVRow = ARGBToUVRow_SSSE3; + if (IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) { + ARGBToYJRow = ARGBToYJRow_SSSE3; + } + } + } + } +#endif +#if defined(HAS_ARGBTOYJROW_NEON) + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + ARGBToYJRow = ARGBToYJRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + ARGBToYJRow = ARGBToYJRow_NEON; + } + if (width >= 16) { + ARGBToUVRow = ARGBToUVRow_Any_NEON; + if (IS_ALIGNED(width, 16)) { + ARGBToUVRow = ARGBToUVRow_NEON; + } + } + } +#endif + + for (int y = 0; y < height - 1; y += 2) { + ARGBToUVRow(src_argb, src_stride_argb, dst_u, dst_v, width); + ARGBToYJRow(src_argb, dst_yj, width); + ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width); + src_argb += src_stride_argb * 2; + dst_yj += dst_stride_yj * 2; + dst_u += dst_stride_u; + dst_v += dst_stride_v; + } + if (height & 1) { + ARGBToUVRow(src_argb, 0, dst_u, dst_v, width); + ARGBToYJRow(src_argb, dst_yj, width); + } + return 0; +} + +// Convert ARGB to J400. +LIBYUV_API +int ARGBToJ400(const uint8* src_argb, int src_stride_argb, + uint8* dst_yj, int dst_stride_yj, + int width, int height) { + if (!src_argb || !dst_yj || width <= 0 || height == 0) { + return -1; + } + if (height < 0) { + height = -height; + src_argb = src_argb + (height - 1) * src_stride_argb; + src_stride_argb = -src_stride_argb; + } + // Coalesce contiguous rows. + if (src_stride_argb == width * 4 && + dst_stride_yj == width) { + return ARGBToI400(src_argb, 0, + dst_yj, 0, + width * height, 1); + } + void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) = + ARGBToYJRow_C; +#if defined(HAS_ARGBTOYJROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { + ARGBToYJRow = ARGBToYJRow_Any_SSSE3; + if (IS_ALIGNED(width, 16)) { + ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3; + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && + IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) { + ARGBToYJRow = ARGBToYJRow_SSSE3; + } + } + } +#endif +#if defined(HAS_ARGBTOYJROW_NEON) + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + ARGBToYJRow = ARGBToYJRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + ARGBToYJRow = ARGBToYJRow_NEON; + } + } +#endif + + for (int y = 0; y < height; ++y) { + ARGBToYJRow(src_argb, dst_yj, width); + src_argb += src_stride_argb; + dst_yj += dst_stride_yj; + } + return 0; +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/source/row_any.cc b/source/row_any.cc index bd55adaf1..3ccb2c0c7 100644 --- a/source/row_any.cc +++ b/source/row_any.cc @@ -215,8 +215,12 @@ YANY(RGBAToYRow_Any_SSSE3, RGBAToYRow_Unaligned_SSSE3, 4, 1, 16) YANY(YUY2ToYRow_Any_SSE2, YUY2ToYRow_Unaligned_SSE2, 2, 1, 16) YANY(UYVYToYRow_Any_SSE2, UYVYToYRow_Unaligned_SSE2, 2, 1, 16) #endif +#ifdef HAS_ARGBTOYJROW_SSSE3 +YANY(ARGBToYJRow_Any_SSSE3, ARGBToYJRow_Unaligned_SSSE3, 4, 1, 16) +#endif #ifdef HAS_ARGBTOYROW_NEON YANY(ARGBToYRow_Any_NEON, ARGBToYRow_NEON, 4, 1, 8) +YANY(ARGBToYJRow_Any_NEON, ARGBToYJRow_NEON, 4, 1, 8) YANY(BGRAToYRow_Any_NEON, BGRAToYRow_NEON, 4, 1, 8) YANY(ABGRToYRow_Any_NEON, ABGRToYRow_NEON, 4, 1, 8) YANY(RGBAToYRow_Any_NEON, RGBAToYRow_NEON, 4, 1, 8) diff --git a/source/row_common.cc b/source/row_common.cc index ebbcd435a..f06847000 100644 --- a/source/row_common.cc +++ b/source/row_common.cc @@ -256,6 +256,22 @@ MAKEROWY(RGB24, 2, 1, 0, 3) MAKEROWY(RAW, 0, 1, 2, 3) #undef MAKEROWY +static __inline int RGBToYJ(uint8 r, uint8 g, uint8 b) { + return (66 * r + 129 * g + 25 * b + 0x0080) >> 8; +} + +#define MAKEROWYJ(NAME, R, G, B, BPP) \ +void NAME ## ToYJRow_C(const uint8* src_argb0, uint8* dst_y, int width) { \ + for (int x = 0; x < width; ++x) { \ + dst_y[0] = RGBToYJ(src_argb0[R], src_argb0[G], src_argb0[B]); \ + src_argb0 += BPP; \ + dst_y += 1; \ + } \ +} \ + +MAKEROWYJ(ARGB, 2, 1, 0, 4) +#undef MAKEROWYJ + void RGB565ToYRow_C(const uint8* src_rgb565, uint8* dst_y, int width) { for (int x = 0; x < width; ++x) { uint8 b = src_rgb565[0] & 0x1f; diff --git a/source/row_neon.cc b/source/row_neon.cc index cc905fe6c..e8f14ec1b 100644 --- a/source/row_neon.cc +++ b/source/row_neon.cc @@ -1336,6 +1336,29 @@ void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { ); } +void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int pix) { + asm volatile ( + "vmov.u8 d24, #13 \n" // B * 0.1016 coefficient + "vmov.u8 d25, #65 \n" // G * 0.5078 coefficient + "vmov.u8 d26, #33 \n" // R * 0.2578 coefficient + ".p2align 2 \n" + "1: \n" + "vld4.8 {d0, d1, d2, d3}, [%0]! \n" // load 8 ARGB pixels. + "subs %2, %2, #8 \n" // 8 processed per loop. + "vmull.u8 q2, d0, d24 \n" // B + "vmlal.u8 q2, d1, d25 \n" // G + "vmlal.u8 q2, d2, d26 \n" // R + "vqrshrun.s16 d0, q2, #7 \n" // 16 bit to 8 bit Y + "vst1.8 {d0}, [%1]! \n" // store 8 pixels Y. + "bgt 1b \n" + : "+r"(src_argb), // %0 + "+r"(dst_y), // %1 + "+r"(pix) // %2 + : + : "cc", "memory", "q0", "q1", "q2", "q12", "q13" + ); +} + // 8x1 pixels. void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int pix) { diff --git a/source/row_posix.cc b/source/row_posix.cc index e26303e80..db2e5f5cc 100644 --- a/source/row_posix.cc +++ b/source/row_posix.cc @@ -642,6 +642,40 @@ void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { ); } +void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { + asm volatile ( + "movdqa %3,%%xmm4 \n" + ".p2align 4 \n" + "1: \n" + "movdqa (%0),%%xmm0 \n" + "movdqa 0x10(%0),%%xmm1 \n" + "movdqa 0x20(%0),%%xmm2 \n" + "movdqa 0x30(%0),%%xmm3 \n" + "pmaddubsw %%xmm4,%%xmm0 \n" + "pmaddubsw %%xmm4,%%xmm1 \n" + "pmaddubsw %%xmm4,%%xmm2 \n" + "pmaddubsw %%xmm4,%%xmm3 \n" + "lea 0x40(%0),%0 \n" + "phaddw %%xmm1,%%xmm0 \n" + "phaddw %%xmm3,%%xmm2 \n" + "psrlw $0x7,%%xmm0 \n" + "psrlw $0x7,%%xmm2 \n" + "packuswb %%xmm2,%%xmm0 \n" + "sub $0x10,%2 \n" + "movdqa %%xmm0,(%1) \n" + "lea 0x10(%1),%1 \n" + "jg 1b \n" + : "+r"(src_argb), // %0 + "+r"(dst_y), // %1 + "+r"(pix) // %2 + : "m"(kARGBToY) // %3 + : "memory", "cc" +#if defined(__SSE2__) + , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4" +#endif + ); +} + void ARGBToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { asm volatile ( "movdqa %4,%%xmm5 \n" @@ -679,6 +713,39 @@ void ARGBToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { ); } +void ARGBToYJRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { + asm volatile ( + "movdqa %3,%%xmm4 \n" + ".p2align 4 \n" + "1: \n" + "movdqu (%0),%%xmm0 \n" + "movdqu 0x10(%0),%%xmm1 \n" + "movdqu 0x20(%0),%%xmm2 \n" + "movdqu 0x30(%0),%%xmm3 \n" + "pmaddubsw %%xmm4,%%xmm0 \n" + "pmaddubsw %%xmm4,%%xmm1 \n" + "pmaddubsw %%xmm4,%%xmm2 \n" + "pmaddubsw %%xmm4,%%xmm3 \n" + "lea 0x40(%0),%0 \n" + "phaddw %%xmm1,%%xmm0 \n" + "phaddw %%xmm3,%%xmm2 \n" + "psrlw $0x7,%%xmm0 \n" + "psrlw $0x7,%%xmm2 \n" + "packuswb %%xmm2,%%xmm0 \n" + "sub $0x10,%2 \n" + "movdqu %%xmm0,(%1) \n" + "lea 0x10(%1),%1 \n" + "jg 1b \n" + : "+r"(src_argb), // %0 + "+r"(dst_y), // %1 + "+r"(pix) // %2 + : "m"(kARGBToY) // %3 + : "memory", "cc" +#if defined(__SSE2__) + , "xmm0", "xmm1", "xmm2", "xmm3", "xmm4" +#endif + ); +} // TODO(fbarchard): pass xmm constants to single block of assembly. // fpic on GCC 4.2 for OSX runs out of GPR registers. "m" effectively takes // 3 registers - ebx, ebp and eax. "m" can be passed with 3 normal registers, diff --git a/source/row_win.cc b/source/row_win.cc index b61cdcc4d..78ee99860 100644 --- a/source/row_win.cc +++ b/source/row_win.cc @@ -664,6 +664,39 @@ void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { } } +// Convert 16 ARGB pixels (64 bytes) to 16 Y values. +__declspec(naked) __declspec(align(16)) +void ARGBToYJRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { + __asm { + mov eax, [esp + 4] /* src_argb */ + mov edx, [esp + 8] /* dst_y */ + mov ecx, [esp + 12] /* pix */ + movdqa xmm4, kARGBToY + + align 16 + convertloop: + movdqa xmm0, [eax] + movdqa xmm1, [eax + 16] + movdqa xmm2, [eax + 32] + movdqa xmm3, [eax + 48] + pmaddubsw xmm0, xmm4 + pmaddubsw xmm1, xmm4 + pmaddubsw xmm2, xmm4 + pmaddubsw xmm3, xmm4 + lea eax, [eax + 64] + phaddw xmm0, xmm1 + phaddw xmm2, xmm3 + psrlw xmm0, 7 + psrlw xmm2, 7 + packuswb xmm0, xmm2 + sub ecx, 16 + movdqa [edx], xmm0 + lea edx, [edx + 16] + jg convertloop + ret + } +} + #ifdef HAS_ARGBTOYROW_AVX2 // Convert 32 ARGB pixels (128 bytes) to 32 Y values. __declspec(naked) __declspec(align(32)) @@ -737,6 +770,38 @@ void ARGBToYRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { } } +__declspec(naked) __declspec(align(16)) +void ARGBToYJRow_Unaligned_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { + __asm { + mov eax, [esp + 4] /* src_argb */ + mov edx, [esp + 8] /* dst_y */ + mov ecx, [esp + 12] /* pix */ + movdqa xmm4, kARGBToY + + align 16 + convertloop: + movdqu xmm0, [eax] + movdqu xmm1, [eax + 16] + movdqu xmm2, [eax + 32] + movdqu xmm3, [eax + 48] + pmaddubsw xmm0, xmm4 + pmaddubsw xmm1, xmm4 + pmaddubsw xmm2, xmm4 + pmaddubsw xmm3, xmm4 + lea eax, [eax + 64] + phaddw xmm0, xmm1 + phaddw xmm2, xmm3 + psrlw xmm0, 7 + psrlw xmm2, 7 + packuswb xmm0, xmm2 + sub ecx, 16 + movdqu [edx], xmm0 + lea edx, [edx + 16] + jg convertloop + ret + } +} + __declspec(naked) __declspec(align(16)) void BGRAToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix) { __asm { diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc index 161683cfa..5edcb78e0 100644 --- a/unit_test/convert_test.cc +++ b/unit_test/convert_test.cc @@ -686,6 +686,7 @@ TEST_F(libyuvTest, FMT_A##To##FMT_PLANAR##N) { \ benchmark_width_, DIFF, _Opt, +, 0) TESTATOPLANAR(ARGB, 4, I420, 2, 2, 4) +TESTATOPLANAR(ARGB, 4, J420, 2, 2, 4) TESTATOPLANAR(BGRA, 4, I420, 2, 2, 4) TESTATOPLANAR(ABGR, 4, I420, 2, 2, 4) TESTATOPLANAR(RGBA, 4, I420, 2, 2, 4) @@ -902,6 +903,7 @@ TESTATOB(ARGB, 4, 4, 1, BayerGRBG, 1, 2, 2, 0) TESTATOB(ARGB, 4, 4, 1, YUY2, 2, 4, 1, 4) TESTATOB(ARGB, 4, 4, 1, UYVY, 2, 4, 1, 4) TESTATOB(ARGB, 4, 4, 1, I400, 1, 1, 1, 2) +TESTATOB(ARGB, 4, 4, 1, J400, 1, 1, 1, 2) TESTATOB(BGRA, 4, 4, 1, ARGB, 4, 4, 1, 0) TESTATOB(ABGR, 4, 4, 1, ARGB, 4, 4, 1, 0) TESTATOB(RGBA, 4, 4, 1, ARGB, 4, 4, 1, 0)