planar_functions.cc revision ba6c59e9d7d7013b3906b6f4230b663422681848
1ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian/*
2ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *
4ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  Use of this source code is governed by a BSD-style license
5ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  that can be found in the LICENSE file in the root of the source
6ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  tree. An additional intellectual property rights grant can be found
7ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  in the file PATENTS. All contributing project authors may
8ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  be found in the AUTHORS file in the root of the source tree.
9ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian */
10ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
11ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/planar_functions.h"
12ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
13ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include <string.h>  // for memset()
14ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
15ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/cpu_id.h"
16ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef HAVE_JPEG
17ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/mjpeg_decoder.h"
18ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
19ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/row.h"
20ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
21ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef __cplusplus
22ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramaniannamespace libyuv {
23ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianextern "C" {
24ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
25ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
26ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy a plane of data
27ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
28ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid CopyPlane(const uint8* src_y, int src_stride_y,
29ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
30ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
31ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
32ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
33ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
34ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
35ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_y == width) {
36ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
37ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
38ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = dst_stride_y = 0;
39ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
40ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Nothing to do.
41ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_y == dst_y && src_stride_y == dst_stride_y) {
42ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return;
43ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
44ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_X86)
45ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) {
46ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_X86;
47ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
48ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
49ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_SSE2)
50ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) &&
51ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
52ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
53ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_SSE2;
54ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
55ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
56ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_ERMS)
57ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasERMS)) {
58ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_ERMS;
59ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
60ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
61ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_NEON)
62ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
63ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_NEON;
64ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
65ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
66ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_MIPS)
67ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS)) {
68ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_MIPS;
69ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
70ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
71ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
72ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Copy plane
73ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
74ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow(src_y, dst_y, width);
75ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
76ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
77ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
78ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
79ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
80ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
81ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid CopyPlane_16(const uint16* src_y, int src_stride_y,
82ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint16* dst_y, int dst_stride_y,
83ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int width, int height) {
84ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
85ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*CopyRow)(const uint16* src, uint16* dst, int width) = CopyRow_16_C;
86ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
87ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
88ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_y == width) {
89ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
90ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
91ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = dst_stride_y = 0;
92ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
93ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_X86)
94ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) {
95ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_X86;
96ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
97ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
98ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_SSE2)
99ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) &&
100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_SSE2;
103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_ERMS)
106ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasERMS)) {
107ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_ERMS;
108ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
109ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
110ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_NEON)
111ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_NEON;
113ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
114ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
115ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_COPYROW_16_MIPS)
116ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS)) {
117ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow = CopyRow_16_MIPS;
118ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
121ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Copy plane
122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
123ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CopyRow(src_y, dst_y, width);
124ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
125ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
126ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
127ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
128ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
129ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy I422.
130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I422Copy(const uint8* src_y, int src_stride_y,
132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             const uint8* src_u, int src_stride_u,
133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             const uint8* src_v, int src_stride_v,
134ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_y, int dst_stride_y,
135ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_u, int dst_stride_u,
136ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_v, int dst_stride_v,
137ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height) {
138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfwidth = (width + 1) >> 1;
139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
140ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_y || !dst_u || !dst_v ||
141ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
142ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u = src_u + (height - 1) * src_stride_u;
149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v = src_v + (height - 1) * src_stride_v;
150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
151ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_u = -src_stride_u;
152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_v = -src_stride_v;
153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height);
156ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height);
157ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
160ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy I444.
161ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
162ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I444Copy(const uint8* src_y, int src_stride_y,
163ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             const uint8* src_u, int src_stride_u,
164ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             const uint8* src_v, int src_stride_v,
165ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_y, int dst_stride_y,
166ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_u, int dst_stride_u,
167ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_v, int dst_stride_v,
168ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height) {
169ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_y || !dst_u || !dst_v ||
171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u = src_u + (height - 1) * src_stride_u;
179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v = src_v + (height - 1) * src_stride_v;
180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_u = -src_stride_u;
182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_v = -src_stride_v;
183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
184ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
185ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
186ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height);
187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height);
188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
191ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy I400.
192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
193ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I400ToI400(const uint8* src_y, int src_stride_y,
194ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
195ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
196ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !dst_y || width <= 0 || height == 0) {
197ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
198ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
199ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
200ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
203ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
204ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
205ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
206ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
207ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
208ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
209ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert I420 to I400.
210ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
211ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I420ToI400(const uint8* src_y, int src_stride_y,
212ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
213ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
214ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
215ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
216ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !dst_y || width <= 0 || height == 0) {
217ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
218ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
219ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
220ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
221ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
222ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
223ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
224ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
225ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
226ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Mirror a plane of data.
230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid MirrorPlane(const uint8* src_y, int src_stride_y,
231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_y, int dst_stride_y,
232ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
233ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
234ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*MirrorRow)(const uint8* src, uint8* dst, int width) = MirrorRow_C;
235ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
236ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
237ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
238ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
239ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
240ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
241ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_NEON)
242ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) {
243ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    MirrorRow = MirrorRow_NEON;
244ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
245ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
246ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_SSE2)
247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) {
248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    MirrorRow = MirrorRow_SSE2;
249ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
250ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
251ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_SSSE3)
252ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16) &&
253ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
254ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
255ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    MirrorRow = MirrorRow_SSSE3;
256ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
257ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
258ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_MIRRORROW_AVX2)
259ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 32)) {
260ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    MirrorRow = MirrorRow_AVX2;
261ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
262ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
263ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
264ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Mirror plane
265ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
266ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    MirrorRow(src_y, dst_y, width);
267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
269ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
270ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
271ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
272ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert YUY2 to I422.
273ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
274ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2,
275ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
276ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_u, int dst_stride_u,
277ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_v, int dst_stride_v,
278ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
279ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
280ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*YUY2ToUV422Row)(const uint8* src_yuy2,
281ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         uint8* dst_u, uint8* dst_v, int pix) =
282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row_C;
283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int pix) =
284ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToYRow_C;
285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
288ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_yuy2 = -src_stride_yuy2;
290ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
292ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_yuy2 == width * 2 &&
293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_y == width &&
294ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_u * 2 == width &&
295ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_v * 2 == width) {
296ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
297ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
298ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_yuy2 = dst_stride_y = dst_stride_u = dst_stride_v = 0;
299ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
300ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_YUY2TOYROW_SSE2)
301ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
302ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToUV422Row = YUY2ToUV422Row_Any_SSE2;
303ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToYRow = YUY2ToYRow_Any_SSE2;
304ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
305ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row = YUY2ToUV422Row_Unaligned_SSE2;
306ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2;
307ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) {
308ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        YUY2ToUV422Row = YUY2ToUV422Row_SSE2;
309ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
310ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          YUY2ToYRow = YUY2ToYRow_SSE2;
311ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
312ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
313ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
314ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
315ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
316ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_YUY2TOYROW_AVX2)
317ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
318ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToUV422Row = YUY2ToUV422Row_Any_AVX2;
319ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToYRow = YUY2ToYRow_Any_AVX2;
320ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
321ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row = YUY2ToUV422Row_AVX2;
322ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToYRow = YUY2ToYRow_AVX2;
323ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
324ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
325ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
326ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_YUY2TOYROW_NEON)
327ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
328ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToYRow = YUY2ToYRow_Any_NEON;
329ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (width >= 16) {
330ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row = YUY2ToUV422Row_Any_NEON;
331ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
332ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
333ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToYRow = YUY2ToYRow_NEON;
334ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      YUY2ToUV422Row = YUY2ToUV422Row_NEON;
335ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
336ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
337ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
338ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
339ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
340ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width);
341ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    YUY2ToYRow(src_yuy2, dst_y, width);
342ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_yuy2 += src_stride_yuy2;
343ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
344ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_u += dst_stride_u;
345ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_v += dst_stride_v;
346ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
347ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
348ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
349ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
350ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert UYVY to I422.
351ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
352ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy,
353ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
354ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_u, int dst_stride_u,
355ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_v, int dst_stride_v,
356ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
357ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
358ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*UYVYToUV422Row)(const uint8* src_uyvy,
359ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         uint8* dst_u, uint8* dst_v, int pix) =
360ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row_C;
361ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*UYVYToYRow)(const uint8* src_uyvy,
362ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     uint8* dst_y, int pix) = UYVYToYRow_C;
363ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
364ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
365ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
366ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
367ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_uyvy = -src_stride_uyvy;
368ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
369ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
370ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_uyvy == width * 2 &&
371ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_y == width &&
372ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_u * 2 == width &&
373ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_v * 2 == width) {
374ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
375ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
376ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_uyvy = dst_stride_y = dst_stride_u = dst_stride_v = 0;
377ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
378ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_UYVYTOYROW_SSE2)
379ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
380ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToUV422Row = UYVYToUV422Row_Any_SSE2;
381ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToYRow = UYVYToYRow_Any_SSE2;
382ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
383ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row = UYVYToUV422Row_Unaligned_SSE2;
384ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToYRow = UYVYToYRow_Unaligned_SSE2;
385ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16)) {
386ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        UYVYToUV422Row = UYVYToUV422Row_SSE2;
387ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
388ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          UYVYToYRow = UYVYToYRow_SSE2;
389ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
390ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
391ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
392ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
393ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
394ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_UYVYTOYROW_AVX2)
395ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
396ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToUV422Row = UYVYToUV422Row_Any_AVX2;
397ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToYRow = UYVYToYRow_Any_AVX2;
398ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 32)) {
399ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row = UYVYToUV422Row_AVX2;
400ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToYRow = UYVYToYRow_AVX2;
401ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
402ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
403ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
404ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_UYVYTOYROW_NEON)
405ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
406ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToYRow = UYVYToYRow_Any_NEON;
407ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (width >= 16) {
408ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row = UYVYToUV422Row_Any_NEON;
409ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
410ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
411ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToYRow = UYVYToYRow_NEON;
412ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      UYVYToUV422Row = UYVYToUV422Row_NEON;
413ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
414ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
415ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
416ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
417ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
418ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToUV422Row(src_uyvy, dst_u, dst_v, width);
419ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    UYVYToYRow(src_uyvy, dst_y, width);
420ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_uyvy += src_stride_uyvy;
421ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
422ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_u += dst_stride_u;
423ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_v += dst_stride_v;
424ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
425ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
426ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
427ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
428ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Mirror I400 with optional flipping
429ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
430ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I400Mirror(const uint8* src_y, int src_stride_y,
431ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
432ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
433ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !dst_y ||
434ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
435ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
436ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
437ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
438ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
439ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
440ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
441ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
442ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
443ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
444ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MirrorPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
445ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
446ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
447ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
448ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Mirror I420 with optional flipping
449ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
450ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I420Mirror(const uint8* src_y, int src_stride_y,
451ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
452ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
453ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_y, int dst_stride_y,
454ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_u, int dst_stride_u,
455ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_v, int dst_stride_v,
456ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
457ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfwidth = (width + 1) >> 1;
458ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfheight = (height + 1) >> 1;
459ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v || !dst_y || !dst_u || !dst_v ||
460ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
461ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
462ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
463ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
464ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
465ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
466ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    halfheight = (height + 1) >> 1;
467ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
468ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u = src_u + (halfheight - 1) * src_stride_u;
469ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v = src_v + (halfheight - 1) * src_stride_v;
470ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
471ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_u = -src_stride_u;
472ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_v = -src_stride_v;
473ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
474ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
475ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_y) {
476ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    MirrorPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
477ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
478ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MirrorPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);
479ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MirrorPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);
480ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
481ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
482ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
483ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// ARGB mirror.
484ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
485ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBMirror(const uint8* src_argb, int src_stride_argb,
486ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_argb, int dst_stride_argb,
487ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
488ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
489ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBMirrorRow)(const uint8* src, uint8* dst, int width) =
490ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBMirrorRow_C;
491ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
492ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
493ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
494ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
495ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
496ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
497ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
498ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
499ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
500ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
501ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMIRRORROW_SSSE3)
502ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4) &&
503ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
504ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
505ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMirrorRow = ARGBMirrorRow_SSSE3;
506ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
507ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
508ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMIRRORROW_AVX2)
509ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 8)) {
510ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMirrorRow = ARGBMirrorRow_AVX2;
511ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
512ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
513ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMIRRORROW_NEON)
514ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 4)) {
515ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMirrorRow = ARGBMirrorRow_NEON;
516ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
517ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
518ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
519ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Mirror plane
520ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
521ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMirrorRow(src_argb, dst_argb, width);
522ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
523ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
524ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
525ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
526ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
527ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
528ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Get a blender that optimized for the CPU, alignment and pixel count.
529ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// As there are 6 blenders to choose from, the caller should try to use
530ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// the same blend function for all pixels if possible.
531ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
532ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianARGBBlendRow GetARGBBlend() {
533ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1,
534ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       uint8* dst_argb, int width) = ARGBBlendRow_C;
535ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBBLENDROW_SSSE3)
536ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3)) {
537ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBBlendRow = ARGBBlendRow_SSSE3;
538ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return ARGBBlendRow;
539ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
540ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
541ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBBLENDROW_SSE2)
542ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
543ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBBlendRow = ARGBBlendRow_SSE2;
544ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
545ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
546ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBBLENDROW_NEON)
547ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
548ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBBlendRow = ARGBBlendRow_NEON;
549ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
550ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
551ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBBlendRow;
552ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
553ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
554ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Alpha Blend 2 ARGB images and store to destination.
555ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
556ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBBlend(const uint8* src_argb0, int src_stride_argb0,
557ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              const uint8* src_argb1, int src_stride_argb1,
558ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint8* dst_argb, int dst_stride_argb,
559ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int width, int height) {
560ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
561ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1,
562ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       uint8* dst_argb, int width) = GetARGBBlend();
563ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
564ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
565ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
566ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
567ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
568ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
569ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
570ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
571ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
572ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
573ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
574ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
575ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
576ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
577ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
578ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
579ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
580ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
581ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
582ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBBlendRow(src_argb0, src_argb1, dst_argb, width);
583ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
584ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
585ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
586ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
587ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
588ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
589ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
590ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Multiply 2 ARGB images and store to destination.
591ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
592ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBMultiply(const uint8* src_argb0, int src_stride_argb0,
593ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 const uint8* src_argb1, int src_stride_argb1,
594ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_argb, int dst_stride_argb,
595ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
596ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
597ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBMultiplyRow)(const uint8* src0, const uint8* src1, uint8* dst,
598ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int width) = ARGBMultiplyRow_C;
599ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
600ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
601ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
602ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
603ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
604ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
605ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
606ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
607ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
608ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
609ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
610ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
611ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
612ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
613ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
614ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
615ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
616ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMULTIPLYROW_SSE2)
617ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
618ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMultiplyRow = ARGBMultiplyRow_Any_SSE2;
619ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
620ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBMultiplyRow = ARGBMultiplyRow_SSE2;
621ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
622ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
623ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
624ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMULTIPLYROW_AVX2)
625ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
626ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMultiplyRow = ARGBMultiplyRow_Any_AVX2;
627ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
628ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBMultiplyRow = ARGBMultiplyRow_AVX2;
629ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
630ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
631ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
632ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBMULTIPLYROW_NEON)
633ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
634ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMultiplyRow = ARGBMultiplyRow_Any_NEON;
635ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
636ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBMultiplyRow = ARGBMultiplyRow_NEON;
637ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
638ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
639ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
640ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
641ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Multiply plane
642ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
643ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBMultiplyRow(src_argb0, src_argb1, dst_argb, width);
644ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
645ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
646ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
647ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
648ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
649ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
650ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
651ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Add 2 ARGB images and store to destination.
652ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
653ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBAdd(const uint8* src_argb0, int src_stride_argb0,
654ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            const uint8* src_argb1, int src_stride_argb1,
655ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            uint8* dst_argb, int dst_stride_argb,
656ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            int width, int height) {
657ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
658ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBAddRow)(const uint8* src0, const uint8* src1, uint8* dst,
659ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     int width) = ARGBAddRow_C;
660ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
661ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
662ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
663ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
664ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
665ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
666ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
667ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
668ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
669ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
670ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
671ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
672ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
673ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
674ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
675ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
676ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
677ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBADDROW_SSE2) && defined(_MSC_VER)
678ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
679ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow = ARGBAddRow_SSE2;
680ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
681ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
682ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBADDROW_SSE2) && !defined(_MSC_VER)
683ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
684ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow = ARGBAddRow_Any_SSE2;
685ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
686ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAddRow = ARGBAddRow_SSE2;
687ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
688ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
689ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
690ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBADDROW_AVX2)
691ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
692ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow = ARGBAddRow_Any_AVX2;
693ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
694ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAddRow = ARGBAddRow_AVX2;
695ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
696ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
697ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
698ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBADDROW_NEON)
699ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
700ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow = ARGBAddRow_Any_NEON;
701ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
702ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAddRow = ARGBAddRow_NEON;
703ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
704ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
705ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
706ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
707ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Add plane
708ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
709ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAddRow(src_argb0, src_argb1, dst_argb, width);
710ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
711ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
712ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
713ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
714ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
715ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
716ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
717ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Subtract 2 ARGB images and store to destination.
718ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
719ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSubtract(const uint8* src_argb0, int src_stride_argb0,
720ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 const uint8* src_argb1, int src_stride_argb1,
721ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_argb, int dst_stride_argb,
722ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
723ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
724ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBSubtractRow)(const uint8* src0, const uint8* src1, uint8* dst,
725ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int width) = ARGBSubtractRow_C;
726ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
727ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
728ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
729ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
730ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
731ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
732ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
733ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
734ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
735ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
736ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
737ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
738ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
739ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
740ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
741ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
742ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
743ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSUBTRACTROW_SSE2)
744ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
745ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSubtractRow = ARGBSubtractRow_Any_SSE2;
746ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
747ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBSubtractRow = ARGBSubtractRow_SSE2;
748ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
749ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
750ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
751ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSUBTRACTROW_AVX2)
752ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
753ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSubtractRow = ARGBSubtractRow_Any_AVX2;
754ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
755ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBSubtractRow = ARGBSubtractRow_AVX2;
756ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
757ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
758ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
759ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSUBTRACTROW_NEON)
760ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
761ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSubtractRow = ARGBSubtractRow_Any_NEON;
762ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
763ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBSubtractRow = ARGBSubtractRow_NEON;
764ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
765ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
766ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
767ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
768ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Subtract plane
769ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
770ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSubtractRow(src_argb0, src_argb1, dst_argb, width);
771ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
772ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
773ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
774ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
775ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
776ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
777ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
778ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert I422 to BGRA.
779ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
780ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I422ToBGRA(const uint8* src_y, int src_stride_y,
781ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
782ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
783ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_bgra, int dst_stride_bgra,
784ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
785ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
786ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*I422ToBGRARow)(const uint8* y_buf,
787ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* u_buf,
788ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* v_buf,
789ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* rgb_buf,
790ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width) = I422ToBGRARow_C;
791ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
792ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_bgra ||
793ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
794ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
795ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
796ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
797ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
798ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
799ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_bgra = dst_bgra + (height - 1) * dst_stride_bgra;
800ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_bgra = -dst_stride_bgra;
801ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
802ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
803ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
804ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_u * 2 == width &&
805ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_v * 2 == width &&
806ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_bgra == width * 4) {
807ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
808ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
809ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = src_stride_u = src_stride_v = dst_stride_bgra = 0;
810ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
811ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TOBGRAROW_NEON)
812ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
813ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToBGRARow = I422ToBGRARow_Any_NEON;
814ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
815ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToBGRARow = I422ToBGRARow_NEON;
816ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
817ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
818ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_I422TOBGRAROW_SSSE3)
819ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
820ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToBGRARow = I422ToBGRARow_Any_SSSE3;
821ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
822ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToBGRARow = I422ToBGRARow_Unaligned_SSSE3;
823ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(dst_bgra, 16) && IS_ALIGNED(dst_stride_bgra, 16)) {
824ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        I422ToBGRARow = I422ToBGRARow_SSSE3;
825ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
826ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
827ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
828ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_I422TOBGRAROW_MIPS_DSPR2)
829ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
830ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
831ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
832ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
833ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_bgra, 4) && IS_ALIGNED(dst_stride_bgra, 4)) {
834ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToBGRARow = I422ToBGRARow_MIPS_DSPR2;
835ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
836ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
837ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
838ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
839ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToBGRARow(src_y, src_u, src_v, dst_bgra, width);
840ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_bgra += dst_stride_bgra;
841ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
842ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u += src_stride_u;
843ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v += src_stride_v;
844ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
845ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
846ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
847ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
848ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert I422 to ABGR.
849ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
850ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I422ToABGR(const uint8* src_y, int src_stride_y,
851ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
852ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
853ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_abgr, int dst_stride_abgr,
854ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
855ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
856ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*I422ToABGRRow)(const uint8* y_buf,
857ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* u_buf,
858ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* v_buf,
859ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* rgb_buf,
860ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width) = I422ToABGRRow_C;
861ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
862ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_abgr ||
863ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
864ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
865ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
866ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
867ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
868ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
869ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr;
870ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_abgr = -dst_stride_abgr;
871ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
872ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
873ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
874ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_u * 2 == width &&
875ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_v * 2 == width &&
876ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_abgr == width * 4) {
877ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
878ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
879ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = src_stride_u = src_stride_v = dst_stride_abgr = 0;
880ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
881ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TOABGRROW_NEON)
882ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
883ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToABGRRow = I422ToABGRRow_Any_NEON;
884ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
885ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToABGRRow = I422ToABGRRow_NEON;
886ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
887ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
888ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_I422TOABGRROW_SSSE3)
889ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
890ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToABGRRow = I422ToABGRRow_Any_SSSE3;
891ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
892ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToABGRRow = I422ToABGRRow_Unaligned_SSSE3;
893ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(dst_abgr, 16) && IS_ALIGNED(dst_stride_abgr, 16)) {
894ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        I422ToABGRRow = I422ToABGRRow_SSSE3;
895ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
896ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
897ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
898ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
899ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
900ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
901ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToABGRRow(src_y, src_u, src_v, dst_abgr, width);
902ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_abgr += dst_stride_abgr;
903ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
904ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u += src_stride_u;
905ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v += src_stride_v;
906ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
907ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
908ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
909ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
910ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert I422 to RGBA.
911ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
912ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I422ToRGBA(const uint8* src_y, int src_stride_y,
913ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_u, int src_stride_u,
914ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               const uint8* src_v, int src_stride_v,
915ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_rgba, int dst_stride_rgba,
916ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
917ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
918ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*I422ToRGBARow)(const uint8* y_buf,
919ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* u_buf,
920ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        const uint8* v_buf,
921ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* rgb_buf,
922ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width) = I422ToRGBARow_C;
923ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_u || !src_v ||
924ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !dst_rgba ||
925ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
926ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
927ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
928ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
929ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
930ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
931ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
932ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_rgba = -dst_stride_rgba;
933ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
934ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
935ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
936ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_u * 2 == width &&
937ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_v * 2 == width &&
938ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_rgba == width * 4) {
939ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
940ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
941ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = src_stride_u = src_stride_v = dst_stride_rgba = 0;
942ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
943ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_I422TORGBAROW_NEON)
944ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
945ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToRGBARow = I422ToRGBARow_Any_NEON;
946ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
947ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToRGBARow = I422ToRGBARow_NEON;
948ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
949ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
950ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_I422TORGBAROW_SSSE3)
951ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
952ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
953ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
954ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      I422ToRGBARow = I422ToRGBARow_Unaligned_SSSE3;
955ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(dst_rgba, 16) && IS_ALIGNED(dst_stride_rgba, 16)) {
956ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        I422ToRGBARow = I422ToRGBARow_SSSE3;
957ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
958ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
959ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
960ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
961ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
962ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
963ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    I422ToRGBARow(src_y, src_u, src_v, dst_rgba, width);
964ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgba += dst_stride_rgba;
965ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
966ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_u += src_stride_u;
967ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_v += src_stride_v;
968ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
969ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
970ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
971ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
972ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert NV12 to RGB565.
973ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
974ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint NV12ToRGB565(const uint8* src_y, int src_stride_y,
975ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 const uint8* src_uv, int src_stride_uv,
976ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_rgb565, int dst_stride_rgb565,
977ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
978ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
979ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*NV12ToRGB565Row)(const uint8* y_buf,
980ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          const uint8* uv_buf,
981ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint8* rgb_buf,
982ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int width) = NV12ToRGB565Row_C;
983ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_uv || !dst_rgb565 ||
984ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
985ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
986ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
987ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
988ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
989ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
990ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
991ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_rgb565 = -dst_stride_rgb565;
992ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
993ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_NV12TORGB565ROW_SSSE3)
994ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
995ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
996ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
997ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
998ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
999ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1000ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_NV12TORGB565ROW_NEON)
1001ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1002ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
1003ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1004ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      NV12ToRGB565Row = NV12ToRGB565Row_NEON;
1005ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1006ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1007ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1008ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1009ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1010ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV12ToRGB565Row(src_y, src_uv, dst_rgb565, width);
1011ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgb565 += dst_stride_rgb565;
1012ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
1013ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (y & 1) {
1014ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_uv += src_stride_uv;
1015ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1016ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1017ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1018ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1019ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1020ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert NV21 to RGB565.
1021ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1022ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint NV21ToRGB565(const uint8* src_y, int src_stride_y,
1023ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 const uint8* src_vu, int src_stride_vu,
1024ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 uint8* dst_rgb565, int dst_stride_rgb565,
1025ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int width, int height) {
1026ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1027ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*NV21ToRGB565Row)(const uint8* y_buf,
1028ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          const uint8* src_vu,
1029ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint8* rgb_buf,
1030ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int width) = NV21ToRGB565Row_C;
1031ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !src_vu || !dst_rgb565 ||
1032ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
1033ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1034ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1035ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1036ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1037ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1038ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
1039ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_rgb565 = -dst_stride_rgb565;
1040ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1041ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_NV21TORGB565ROW_SSSE3)
1042ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
1043ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV21ToRGB565Row = NV21ToRGB565Row_Any_SSSE3;
1044ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1045ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      NV21ToRGB565Row = NV21ToRGB565Row_SSSE3;
1046ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1047ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1048ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_NV21TORGB565ROW_NEON)
1049ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1050ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV21ToRGB565Row = NV21ToRGB565Row_Any_NEON;
1051ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1052ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      NV21ToRGB565Row = NV21ToRGB565Row_NEON;
1053ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1054ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1055ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1056ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1057ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1058ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    NV21ToRGB565Row(src_y, src_vu, dst_rgb565, width);
1059ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_rgb565 += dst_stride_rgb565;
1060ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
1061ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (y & 1) {
1062ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_vu += src_stride_vu;
1063ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1064ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1065ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1066ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1067ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1068ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1069ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid SetPlane(uint8* dst_y, int dst_stride_y,
1070ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int width, int height,
1071ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint32 value) {
1072ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1073ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint32 v32 = value | (value << 8) | (value << 16) | (value << 24);
1074ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SetRow)(uint8* dst, uint32 value, int pix) = SetRow_C;
1075ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1076ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_y == width) {
1077ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1078ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1079ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_y = 0;
1080ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1081ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SETROW_NEON)
1082ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) &&
1083ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(width, 16) &&
1084ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
1085ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SetRow = SetRow_NEON;
1086ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1087ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1088ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SETROW_X86)
1089ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) {
1090ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SetRow = SetRow_X86;
1091ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1092ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1093ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1094ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Set plane
1095ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1096ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SetRow(dst_y, v32, width);
1097ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_y += dst_stride_y;
1098ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1099ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Draw a rectangle into I420
1102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint I420Rect(uint8* dst_y, int dst_stride_y,
1104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_u, int dst_stride_u,
1105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_v, int dst_stride_v,
1106ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int x, int y,
1107ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height,
1108ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int value_y, int value_u, int value_v) {
1109ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfwidth = (width + 1) >> 1;
1110ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int halfheight = (height + 1) >> 1;
1111ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* start_y = dst_y + y * dst_stride_y + x;
1112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* start_u = dst_u + (y / 2) * dst_stride_u + (x / 2);
1113ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* start_v = dst_v + (y / 2) * dst_stride_v + (x / 2);
1114ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_y || !dst_u || !dst_v ||
1115ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height <= 0 ||
1116ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      x < 0 || y < 0 ||
1117ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      value_y < 0 || value_y > 255 ||
1118ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      value_u < 0 || value_u > 255 ||
1119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      value_v < 0 || value_v > 255) {
1120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1121ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1123ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  SetPlane(start_y, dst_stride_y, width, height, value_y);
1124ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  SetPlane(start_u, dst_stride_u, halfwidth, halfheight, value_u);
1125ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  SetPlane(start_v, dst_stride_v, halfwidth, halfheight, value_v);
1126ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1127ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1128ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1129ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Draw a rectangle into ARGB
1130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBRect(uint8* dst_argb, int dst_stride_argb,
1132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int dst_x, int dst_y,
1133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height,
1134ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint32 value) {
1135ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb ||
1136ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height <= 0 ||
1137ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_x < 0 || dst_y < 0) {
1138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1140ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  dst_argb += dst_y * dst_stride_argb + dst_x * 4;
1141ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1142ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SETROW_NEON)
1148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16) &&
1149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSetRows_NEON(dst_argb, value, width, dst_stride_argb, height);
1151ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return 0;
1152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SETROW_X86)
1155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86)) {
1156ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSetRows_X86(dst_argb, value, width, dst_stride_argb, height);
1157ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return 0;
1158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1160ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ARGBSetRows_C(dst_argb, value, width, dst_stride_argb, height);
1161ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1162ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1163ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1164ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert unattentuated ARGB to preattenuated ARGB.
1165ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// An unattenutated ARGB alpha blend uses the formula
1166ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// p = a * f + (1 - a) * b
1167ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// where
1168ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   p is output pixel
1169ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   f is foreground pixel
1170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   b is background pixel
1171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   a is alpha value from foreground pixel
1172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// An preattenutated ARGB alpha blend uses the formula
1173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// p = f + (1 - a) * b
1174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// where
1175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   f is foreground pixel premultiplied by alpha
1176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBAttenuate(const uint8* src_argb, int src_stride_argb,
1179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint8* dst_argb, int dst_stride_argb,
1180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int width, int height) {
1181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb,
1183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           int width) = ARGBAttenuateRow_C;
1184ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
1185ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1186ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1191ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1193ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1194ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1195ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1196ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1197ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1198ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1199ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBATTENUATEROW_SSE2)
1200ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 4 &&
1201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
1202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1203ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSE2;
1204ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1205ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAttenuateRow = ARGBAttenuateRow_SSE2;
1206ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1207ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1208ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1209ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBATTENUATEROW_SSSE3)
1210ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 4) {
1211ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
1212ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1213ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
1214ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1215ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1216ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1217ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBATTENUATEROW_AVX2)
1218ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
1219ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
1220ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1221ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
1222ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1223ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1224ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1225ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBATTENUATEROW_NEON)
1226ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
1228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
1230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1232ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1233ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1234ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1235ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBAttenuateRow(src_argb, dst_argb, width);
1236ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1237ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1238ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1239ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1240ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1241ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1242ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert preattentuated ARGB to unattenuated ARGB.
1243ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1244ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBUnattenuate(const uint8* src_argb, int src_stride_argb,
1245ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    uint8* dst_argb, int dst_stride_argb,
1246ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    int width, int height) {
1247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBUnattenuateRow)(const uint8* src_argb, uint8* dst_argb,
1249ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                             int width) = ARGBUnattenuateRow_C;
1250ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
1251ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1252ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1253ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1254ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1255ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1256ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1257ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1258ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1259ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1260ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1261ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1262ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1263ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1264ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1265ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBUNATTENUATEROW_SSE2)
1266ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
1267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBUnattenuateRow = ARGBUnattenuateRow_Any_SSE2;
1268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1269ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBUnattenuateRow = ARGBUnattenuateRow_SSE2;
1270ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1271ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1272ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1273ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBUNATTENUATEROW_AVX2)
1274ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
1275ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBUnattenuateRow = ARGBUnattenuateRow_Any_AVX2;
1276ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1277ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBUnattenuateRow = ARGBUnattenuateRow_AVX2;
1278ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1279ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1280ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1281ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// TODO(fbarchard): Neon version.
1282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1284ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBUnattenuateRow(src_argb, dst_argb, width);
1285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1288ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1290ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Convert ARGB to Grayed ARGB.
1292ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBGrayTo(const uint8* src_argb, int src_stride_argb,
1294ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               uint8* dst_argb, int dst_stride_argb,
1295ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               int width, int height) {
1296ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1297ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBGrayRow)(const uint8* src_argb, uint8* dst_argb,
1298ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      int width) = ARGBGrayRow_C;
1299ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
1300ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1301ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1302ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1303ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1304ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1305ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1306ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1307ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1308ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1309ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1310ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1311ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1312ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1313ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1314ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBGRAYROW_SSSE3)
1315ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) &&
1316ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
1317ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1318ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow = ARGBGrayRow_SSSE3;
1319ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1320ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_ARGBGRAYROW_NEON)
1321ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1322ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow = ARGBGrayRow_NEON;
1323ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1324ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1325ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1326ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1327ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow(src_argb, dst_argb, width);
1328ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1329ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1330ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1331ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1332ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1333ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1334ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Make a rectangle of ARGB gray scale.
1335ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1336ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBGray(uint8* dst_argb, int dst_stride_argb,
1337ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int dst_x, int dst_y,
1338ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height) {
1339ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1340ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBGrayRow)(const uint8* src_argb, uint8* dst_argb,
1341ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      int width) = ARGBGrayRow_C;
1342ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1343ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) {
1344ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1345ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1346ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1347ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1348ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1349ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1350ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1351ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1352ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBGRAYROW_SSSE3)
1353ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) &&
1354ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1355ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow = ARGBGrayRow_SSSE3;
1356ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1357ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_ARGBGRAYROW_NEON)
1358ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1359ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow = ARGBGrayRow_NEON;
1360ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1361ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1362ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1363ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBGrayRow(dst, dst, width);
1364ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1365ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1366ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1367ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1368ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1369ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Make a rectangle of ARGB Sepia tone.
1370ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1371ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSepia(uint8* dst_argb, int dst_stride_argb,
1372ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int dst_x, int dst_y, int width, int height) {
1373ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1374ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBSepiaRow)(uint8* dst_argb, int width) = ARGBSepiaRow_C;
1375ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1376ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) {
1377ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1378ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1379ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1380ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1381ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1382ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1383ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1384ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1385ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSEPIAROW_SSSE3)
1386ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) &&
1387ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1388ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSepiaRow = ARGBSepiaRow_SSSE3;
1389ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1390ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_ARGBSEPIAROW_NEON)
1391ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1392ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSepiaRow = ARGBSepiaRow_NEON;
1393ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1394ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1395ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1396ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBSepiaRow(dst, width);
1397ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1398ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1399ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1400ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1401ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1402ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a 4x4 matrix to each ARGB pixel.
1403ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Note: Normally for shading, but can be used to swizzle or invert.
1404ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1405ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBColorMatrix(const uint8* src_argb, int src_stride_argb,
1406ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    uint8* dst_argb, int dst_stride_argb,
1407ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    const int8* matrix_argb,
1408ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    int width, int height) {
1409ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1410ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBColorMatrixRow)(const uint8* src_argb, uint8* dst_argb,
1411ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const int8* matrix_argb, int width) = ARGBColorMatrixRow_C;
1412ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || !matrix_argb || width <= 0 || height == 0) {
1413ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1414ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1415ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1416ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1417ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1418ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1419ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1420ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1421ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1422ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1423ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1424ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1425ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1426ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1427ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOLORMATRIXROW_SSSE3)
1428ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) &&
1429ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1430ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorMatrixRow = ARGBColorMatrixRow_SSSE3;
1431ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1432ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_ARGBCOLORMATRIXROW_NEON)
1433ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1434ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorMatrixRow = ARGBColorMatrixRow_NEON;
1435ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1436ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1437ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1438ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorMatrixRow(src_argb, dst_argb, matrix_argb, width);
1439ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1440ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1441ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1442ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1443ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1444ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1445ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a 4x3 matrix to each ARGB pixel.
1446ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Deprecated.
1447ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1448ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint RGBColorMatrix(uint8* dst_argb, int dst_stride_argb,
1449ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   const int8* matrix_rgb,
1450ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   int dst_x, int dst_y, int width, int height) {
1451ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  SIMD_ALIGNED(int8 matrix_argb[16]);
1452ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1453ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || !matrix_rgb || width <= 0 || height <= 0 ||
1454ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_x < 0 || dst_y < 0) {
1455ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1456ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1457ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1458ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Convert 4x3 7 bit matrix to 4x4 6 bit matrix.
1459ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[0] = matrix_rgb[0] / 2;
1460ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[1] = matrix_rgb[1] / 2;
1461ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[2] = matrix_rgb[2] / 2;
1462ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[3] = matrix_rgb[3] / 2;
1463ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[4] = matrix_rgb[4] / 2;
1464ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[5] = matrix_rgb[5] / 2;
1465ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[6] = matrix_rgb[6] / 2;
1466ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[7] = matrix_rgb[7] / 2;
1467ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[8] = matrix_rgb[8] / 2;
1468ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[9] = matrix_rgb[9] / 2;
1469ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[10] = matrix_rgb[10] / 2;
1470ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[11] = matrix_rgb[11] / 2;
1471ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[14] = matrix_argb[13] = matrix_argb[12] = 0;
1472ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  matrix_argb[15] = 64;  // 1.0
1473ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1474ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBColorMatrix((const uint8*)(dst), dst_stride_argb,
1475ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         dst, dst_stride_argb,
1476ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         &matrix_argb[0], width, height);
1477ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1478ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1479ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a color table each ARGB pixel.
1480ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Table contains 256 ARGB values.
1481ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1482ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBColorTable(uint8* dst_argb, int dst_stride_argb,
1483ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   const uint8* table_argb,
1484ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   int dst_x, int dst_y, int width, int height) {
1485ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1486ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBColorTableRow)(uint8* dst_argb, const uint8* table_argb,
1487ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            int width) = ARGBColorTableRow_C;
1488ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1489ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || !table_argb || width <= 0 || height <= 0 ||
1490ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_x < 0 || dst_y < 0) {
1491ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1492ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1493ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1494ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1495ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1496ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1497ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1498ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1499ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOLORTABLEROW_X86)
1500ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86)) {
1501ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorTableRow = ARGBColorTableRow_X86;
1502ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1503ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1504ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1505ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBColorTableRow(dst, table_argb, width);
1506ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1507ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1508ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1509ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1510ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1511ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a color table each ARGB pixel but preserve destination alpha.
1512ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Table contains 256 ARGB values.
1513ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1514ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint RGBColorTable(uint8* dst_argb, int dst_stride_argb,
1515ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  const uint8* table_argb,
1516ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int dst_x, int dst_y, int width, int height) {
1517ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1518ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*RGBColorTableRow)(uint8* dst_argb, const uint8* table_argb,
1519ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           int width) = RGBColorTableRow_C;
1520ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1521ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || !table_argb || width <= 0 || height <= 0 ||
1522ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_x < 0 || dst_y < 0) {
1523ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1524ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1525ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1526ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1527ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1528ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1529ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1530ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1531ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_RGBCOLORTABLEROW_X86)
1532ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasX86)) {
1533ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    RGBColorTableRow = RGBColorTableRow_X86;
1534ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1535ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1536ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1537ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    RGBColorTableRow(dst, table_argb, width);
1538ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1539ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1540ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1541ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1542ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1543ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// ARGBQuantize is used to posterize art.
1544ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// e.g. rgb / qvalue * qvalue + qvalue / 2
1545ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// But the low levels implement efficiently with 3 parameters, and could be
1546ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// used for other high level operations.
1547ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// dst_argb[0] = (b * scale >> 16) * interval_size + interval_offset;
1548ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// where scale is 1 / interval_size as a fixed point value.
1549ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// The divide is replaces with a multiply by reciprocal fixed point multiply.
1550ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Caveat - although SSE2 saturates, the C function does not and should be used
1551ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// with care if doing anything but quantization.
1552ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1553ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBQuantize(uint8* dst_argb, int dst_stride_argb,
1554ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int scale, int interval_size, int interval_offset,
1555ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                 int dst_x, int dst_y, int width, int height) {
1556ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1557ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBQuantizeRow)(uint8* dst_argb, int scale, int interval_size,
1558ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          int interval_offset, int width) = ARGBQuantizeRow_C;
1559ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4;
1560ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0 ||
1561ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      interval_size < 1 || interval_size > 255) {
1562ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1563ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1564ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1565ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (dst_stride_argb == width * 4) {
1566ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1567ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1568ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = 0;
1569ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1570ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBQUANTIZEROW_SSE2)
1571ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) &&
1572ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1573ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBQuantizeRow = ARGBQuantizeRow_SSE2;
1574ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1575ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_ARGBQUANTIZEROW_NEON)
1576ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1577ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBQuantizeRow = ARGBQuantizeRow_NEON;
1578ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1579ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1580ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1581ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBQuantizeRow(dst, scale, interval_size, interval_offset, width);
1582ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst += dst_stride_argb;
1583ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1584ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1585ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1586ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1587ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Computes table of cumulative sum for image where the value is the sum
1588ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// of all values above and to the left of the entry. Used by ARGBBlur.
1589ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1590ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBComputeCumulativeSum(const uint8* src_argb, int src_stride_argb,
1591ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                             int32* dst_cumsum, int dst_stride32_cumsum,
1592ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                             int width, int height) {
1593ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1594ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ComputeCumulativeSumRow)(const uint8* row, int32* cumsum,
1595ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C;
1596ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int32* previous_cumsum = dst_cumsum;
1597ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!dst_cumsum || !src_argb || width <= 0 || height <= 0) {
1598ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1599ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1600ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_CUMULATIVESUMTOAVERAGEROW_SSE2)
1601ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1602ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ComputeCumulativeSumRow = ComputeCumulativeSumRow_SSE2;
1603ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1604ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1605ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  memset(dst_cumsum, 0, width * sizeof(dst_cumsum[0]) * 4);  // 4 int per pixel.
1606ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1607ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ComputeCumulativeSumRow(src_argb, dst_cumsum, previous_cumsum, width);
1608ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    previous_cumsum = dst_cumsum;
1609ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_cumsum += dst_stride32_cumsum;
1610ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1611ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1612ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1613ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1614ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1615ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Blur ARGB image.
1616ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Caller should allocate CumulativeSum table of width * height * 16 bytes
1617ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// aligned to 16 byte boundary. height can be radius * 2 + 2 to save memory
1618ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// as the buffer is treated as circular.
1619ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1620ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBBlur(const uint8* src_argb, int src_stride_argb,
1621ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             uint8* dst_argb, int dst_stride_argb,
1622ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int32* dst_cumsum, int dst_stride32_cumsum,
1623ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             int width, int height, int radius) {
1624ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1625ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ComputeCumulativeSumRow)(const uint8 *row, int32 *cumsum,
1626ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C;
1627ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*CumulativeSumToAverageRow)(const int32* topleft, const int32* botleft,
1628ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int width, int area, uint8* dst, int count) = CumulativeSumToAverageRow_C;
1629ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int32* cumsum_bot_row;
1630ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int32* max_cumsum_bot_row;
1631ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int32* cumsum_top_row;
1632ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1633ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
1634ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1635ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1636ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1637ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1638ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1639ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1640ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1641ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (radius > height) {
1642ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    radius = height;
1643ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1644ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (radius > (width / 2 - 1)) {
1645ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    radius = width / 2 - 1;
1646ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1647ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (radius <= 0) {
1648ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1649ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1650ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_CUMULATIVESUMTOAVERAGEROW_SSE2)
1651ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1652ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ComputeCumulativeSumRow = ComputeCumulativeSumRow_SSE2;
1653ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CumulativeSumToAverageRow = CumulativeSumToAverageRow_SSE2;
1654ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1655ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1656ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Compute enough CumulativeSum for first row to be blurred. After this
1657ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // one row of CumulativeSum is updated at a time.
1658ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ARGBComputeCumulativeSum(src_argb, src_stride_argb,
1659ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           dst_cumsum, dst_stride32_cumsum,
1660ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           width, radius);
1661ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1662ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  src_argb = src_argb + radius * src_stride_argb;
1663ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  cumsum_bot_row = &dst_cumsum[(radius - 1) * dst_stride32_cumsum];
1664ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1665ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  max_cumsum_bot_row = &dst_cumsum[(radius * 2 + 2) * dst_stride32_cumsum];
1666ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  cumsum_top_row = &dst_cumsum[0];
1667ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1668ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1669ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int top_y = ((y - radius - 1) >= 0) ? (y - radius - 1) : 0;
1670ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int bot_y = ((y + radius) < height) ? (y + radius) : (height - 1);
1671ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int area = radius * (bot_y - top_y);
1672ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int boxwidth = radius * 4;
1673ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int x;
1674ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int n;
1675ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1676ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Increment cumsum_top_row pointer with circular buffer wrap around.
1677ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (top_y) {
1678ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      cumsum_top_row += dst_stride32_cumsum;
1679ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (cumsum_top_row >= max_cumsum_bot_row) {
1680ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        cumsum_top_row = dst_cumsum;
1681ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
1682ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1683ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Increment cumsum_bot_row pointer with circular buffer wrap around and
1684ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // then fill in a row of CumulativeSum.
1685ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if ((y + radius) < height) {
1686ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const int32* prev_cumsum_bot_row = cumsum_bot_row;
1687ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      cumsum_bot_row += dst_stride32_cumsum;
1688ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (cumsum_bot_row >= max_cumsum_bot_row) {
1689ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        cumsum_bot_row = dst_cumsum;
1690ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
1691ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ComputeCumulativeSumRow(src_argb, cumsum_bot_row, prev_cumsum_bot_row,
1692ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              width);
1693ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_argb += src_stride_argb;
1694ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1695ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1696ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Left clipped.
1697ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    for (x = 0; x < radius + 1; ++x) {
1698ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      CumulativeSumToAverageRow(cumsum_top_row, cumsum_bot_row,
1699ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                boxwidth, area, &dst_argb[x * 4], 1);
1700ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      area += (bot_y - top_y);
1701ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      boxwidth += 4;
1702ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1703ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1704ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Middle unclipped.
1705ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    n = (width - 1) - radius - x + 1;
1706ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    CumulativeSumToAverageRow(cumsum_top_row, cumsum_bot_row,
1707ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              boxwidth, area, &dst_argb[x * 4], n);
1708ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1709ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Right clipped.
1710ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    for (x += n; x <= width - 1; ++x) {
1711ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      area -= (bot_y - top_y);
1712ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      boxwidth -= 4;
1713ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      CumulativeSumToAverageRow(cumsum_top_row + (x - radius - 1) * 4,
1714ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                cumsum_bot_row + (x - radius - 1) * 4,
1715ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                boxwidth, area, &dst_argb[x * 4], 1);
1716ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1717ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1718ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1719ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1720ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1721ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1722ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Multiply ARGB image by a specified ARGB value.
1723ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1724ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBShade(const uint8* src_argb, int src_stride_argb,
1725ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint8* dst_argb, int dst_stride_argb,
1726ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int width, int height, uint32 value) {
1727ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1728ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBShadeRow)(const uint8* src_argb, uint8* dst_argb,
1729ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       int width, uint32 value) = ARGBShadeRow_C;
1730ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0 || value == 0u) {
1731ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1732ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1733ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1734ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1735ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
1736ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1737ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1738ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1739ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
1740ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1741ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1742ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1743ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
1744ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1745ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHADEROW_SSE2)
1746ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) &&
1747ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
1748ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1749ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShadeRow = ARGBShadeRow_SSE2;
1750ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1751ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#elif defined(HAS_ARGBSHADEROW_NEON)
1752ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
1753ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShadeRow = ARGBShadeRow_NEON;
1754ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1755ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1756ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1757ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1758ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShadeRow(src_argb, dst_argb, width, value);
1759ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
1760ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1761ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1762ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1763ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1764ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1765ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Interpolate 2 ARGB images by specified amount (0 to 255).
1766ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1767ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0,
1768ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    const uint8* src_argb1, int src_stride_argb1,
1769ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    uint8* dst_argb, int dst_stride_argb,
1770ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    int width, int height, int interpolation) {
1771ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1772ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr,
1773ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         ptrdiff_t src_stride, int dst_width,
1774ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         int source_y_fraction) = InterpolateRow_C;
1775ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) {
1776ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1777ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1778ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1779ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1780ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1781ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1782ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_stride_argb = -dst_stride_argb;
1783ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1784ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1785ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb0 == width * 4 &&
1786ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_stride_argb1 == width * 4 &&
1787ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1788ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1789ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1790ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0;
1791ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1792ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSE2)
1793ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
1794ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSE2;
1795ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1796ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_Unaligned_SSE2;
1797ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(src_argb0, 16) && IS_ALIGNED(src_stride_argb0, 16) &&
1798ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          IS_ALIGNED(src_argb1, 16) && IS_ALIGNED(src_stride_argb1, 16) &&
1799ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1800ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow = InterpolateRow_SSE2;
1801ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
1802ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1803ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1804ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1805ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_SSSE3)
1806ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 4) {
1807ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_SSSE3;
1808ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1809ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_Unaligned_SSSE3;
1810ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(src_argb0, 16) && IS_ALIGNED(src_stride_argb0, 16) &&
1811ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          IS_ALIGNED(src_argb1, 16) && IS_ALIGNED(src_stride_argb1, 16) &&
1812ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1813ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        InterpolateRow = InterpolateRow_SSSE3;
1814ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
1815ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1816ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1817ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1818ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_AVX2)
1819ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 8) {
1820ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_AVX2;
1821ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1822ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_AVX2;
1823ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1824ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1825ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1826ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROW_NEON)
1827ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 4) {
1828ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow = InterpolateRow_Any_NEON;
1829ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1830ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      InterpolateRow = InterpolateRow_NEON;
1831ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1832ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1833ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1834ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2)
1835ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && width >= 1 &&
1836ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb0, 4) && IS_ALIGNED(src_stride_argb0, 4) &&
1837ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb1, 4) && IS_ALIGNED(src_stride_argb1, 4) &&
1838ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
1839ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ScaleARGBFilterRows = InterpolateRow_MIPS_DSPR2;
1840ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1841ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1842ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1843ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1844ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    InterpolateRow(dst_argb, src_argb0, src_argb1 - src_argb0,
1845ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   width * 4, interpolation);
1846ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb0 += src_stride_argb0;
1847ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb1 += src_stride_argb1;
1848ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1849ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1850ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1851ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1852ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1853ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Shuffle ARGB channel order.  e.g. BGRA to ARGB.
1854ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
1855ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBShuffle(const uint8* src_bgra, int src_stride_bgra,
1856ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                uint8* dst_argb, int dst_stride_argb,
1857ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                const uint8* shuffler, int width, int height) {
1858ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1859ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBShuffleRow)(const uint8* src_bgra, uint8* dst_argb,
1860ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         const uint8* shuffler, int pix) = ARGBShuffleRow_C;
1861ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_bgra || !dst_argb ||
1862ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width <= 0 || height == 0) {
1863ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1864ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1865ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1866ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1867ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1868ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_bgra = src_bgra + (height - 1) * src_stride_bgra;
1869ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_bgra = -src_stride_bgra;
1870ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1871ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
1872ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_bgra == width * 4 &&
1873ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
1874ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
1875ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
1876ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_bgra = dst_stride_argb = 0;
1877ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1878ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHUFFLEROW_SSE2)
1879ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 4) {
1880ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow = ARGBShuffleRow_Any_SSE2;
1881ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1882ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBShuffleRow = ARGBShuffleRow_SSE2;
1883ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1884ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1885ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1886ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHUFFLEROW_SSSE3)
1887ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
1888ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow = ARGBShuffleRow_Any_SSSE3;
1889ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1890ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBShuffleRow = ARGBShuffleRow_Unaligned_SSSE3;
1891ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (IS_ALIGNED(src_bgra, 16) && IS_ALIGNED(src_stride_bgra, 16) &&
1892ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
1893ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        ARGBShuffleRow = ARGBShuffleRow_SSSE3;
1894ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
1895ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1896ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1897ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1898ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHUFFLEROW_AVX2)
1899ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && width >= 16) {
1900ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow = ARGBShuffleRow_Any_AVX2;
1901ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 16)) {
1902ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBShuffleRow = ARGBShuffleRow_AVX2;
1903ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1904ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1905ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1906ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBSHUFFLEROW_NEON)
1907ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 4) {
1908ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow = ARGBShuffleRow_Any_NEON;
1909ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 4)) {
1910ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBShuffleRow = ARGBShuffleRow_NEON;
1911ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1912ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1913ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1914ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1915ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
1916ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBShuffleRow(src_bgra, dst_argb, shuffler, width);
1917ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_bgra += src_stride_bgra;
1918ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
1919ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1920ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
1921ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1922ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1923ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Sobel ARGB effect.
1924ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic int ARGBSobelize(const uint8* src_argb, int src_stride_argb,
1925ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        uint8* dst_argb, int dst_stride_argb,
1926ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        int width, int height,
1927ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        void (*SobelRow)(const uint8* src_sobelx,
1928ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                         const uint8* src_sobely,
1929ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                         uint8* dst, int width)) {
1930ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
1931ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer,
1932ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         uint32 selector, int pix) = ARGBToBayerGGRow_C;
1933ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1,
1934ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    uint8* dst_sobely, int width) = SobelYRow_C;
1935ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1,
1936ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    const uint8* src_y2, uint8* dst_sobely, int width) =
1937ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      SobelXRow_C;
1938ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int kEdge = 16;  // Extra pixels at start of row for extrude/align.
1939ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb  || !dst_argb || width <= 0 || height == 0) {
1940ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
1941ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1942ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
1943ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
1944ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
1945ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb  = src_argb  + (height - 1) * src_stride_argb;
1946ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
1947ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1948ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // ARGBToBayer used to select G channel from ARGB.
1949ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBTOBAYERGGROW_SSE2)
1950ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
1951ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
1952ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBToBayerRow = ARGBToBayerGGRow_Any_SSE2;
1953ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1954ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBToBayerRow = ARGBToBayerGGRow_SSE2;
1955ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1956ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1957ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1958ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBTOBAYERROW_SSSE3)
1959ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && width >= 8 &&
1960ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
1961ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBToBayerRow = ARGBToBayerRow_Any_SSSE3;
1962ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1963ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBToBayerRow = ARGBToBayerRow_SSSE3;
1964ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1965ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1966ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1967ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBTOBAYERGGROW_NEON)
1968ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1969ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBToBayerRow = ARGBToBayerGGRow_Any_NEON;
1970ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (IS_ALIGNED(width, 8)) {
1971ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBToBayerRow = ARGBToBayerGGRow_NEON;
1972ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
1973ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1974ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1975ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELYROW_SSE2)
1976ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1977ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelYRow = SobelYRow_SSE2;
1978ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1979ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1980ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELYROW_NEON)
1981ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1982ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelYRow = SobelYRow_NEON;
1983ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1984ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1985ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELXROW_SSE2)
1986ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2)) {
1987ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelXRow = SobelXRow_SSE2;
1988ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1989ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1990ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELXROW_NEON)
1991ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON)) {
1992ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelXRow = SobelXRow_NEON;
1993ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
1994ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
1995ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  {
1996ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // 3 rows with edges before/after.
1997ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    const int kRowSize = (width + kEdge + 15) & ~15;
1998ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    align_buffer_64(rows, kRowSize * 2 + (kEdge + kRowSize * 3 + kEdge));
1999ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_sobelx = rows;
2000ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_sobely = rows + kRowSize;
2001ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_y = rows + kRowSize * 2;
2002ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2003ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Convert first row.
2004ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_y0 = row_y + kEdge;
2005ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_y1 = row_y0 + kRowSize;
2006ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint8* row_y2 = row_y1 + kRowSize;
2007ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBToBayerRow(src_argb, row_y0, 0x0d090501, width);
2008ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    row_y0[-1] = row_y0[0];
2009ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    memset(row_y0 + width, row_y0[width - 1], 16);  // Extrude 16 for valgrind.
2010ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBToBayerRow(src_argb, row_y1, 0x0d090501, width);
2011ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    row_y1[-1] = row_y1[0];
2012ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    memset(row_y1 + width, row_y1[width - 1], 16);
2013ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    memset(row_y2 + width, 0, 16);
2014ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2015ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    for (y = 0; y < height; ++y) {
2016ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      // Convert next row of ARGB to Y.
2017ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (y < (height - 1)) {
2018ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_argb += src_stride_argb;
2019ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
2020ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBToBayerRow(src_argb, row_y2, 0x0d090501, width);
2021ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      row_y2[-1] = row_y2[0];
2022ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      row_y2[width] = row_y2[width - 1];
2023ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2024ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      SobelXRow(row_y0 - 1, row_y1 - 1, row_y2 - 1, row_sobelx, width);
2025ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      SobelYRow(row_y0 - 1, row_y2 - 1, row_sobely, width);
2026ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      SobelRow(row_sobelx, row_sobely, dst_argb, width);
2027ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2028ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      // Cycle thru circular queue of 3 row_y buffers.
2029ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      {
2030ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        uint8* row_yt = row_y0;
2031ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        row_y0 = row_y1;
2032ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        row_y1 = row_y2;
2033ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        row_y2 = row_yt;
2034ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
2035ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2036ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_argb += dst_stride_argb;
2037ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
2038ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    free_aligned_buffer_64(rows);
2039ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2040ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2041ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2042ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2043ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Sobel ARGB effect.
2044ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2045ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSobel(const uint8* src_argb, int src_stride_argb,
2046ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              uint8* dst_argb, int dst_stride_argb,
2047ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              int width, int height) {
2048ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely,
2049ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   uint8* dst_argb, int width) = SobelRow_C;
2050ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELROW_SSE2)
2051ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) &&
2052ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
2053ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelRow = SobelRow_SSE2;
2054ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2055ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2056ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELROW_NEON)
2057ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
2058ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelRow = SobelRow_NEON;
2059ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2060ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2061ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
2062ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      width, height, SobelRow);
2063ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2064ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2065ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Sobel ARGB effect with planar output.
2066ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2067ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb,
2068ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     uint8* dst_y, int dst_stride_y,
2069ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     int width, int height) {
2070ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely,
2071ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint8* dst_, int width) = SobelToPlaneRow_C;
2072ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELTOPLANEROW_SSE2)
2073ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) &&
2074ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
2075ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelToPlaneRow = SobelToPlaneRow_SSE2;
2076ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2077ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2078ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELTOPLANEROW_NEON)
2079ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) {
2080ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelToPlaneRow = SobelToPlaneRow_NEON;
2081ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2082ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2083ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBSobelize(src_argb, src_stride_argb, dst_y, dst_stride_y,
2084ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      width, height, SobelToPlaneRow);
2085ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2086ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2087ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// SobelXY ARGB effect.
2088ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Similar to Sobel, but also stores Sobel X in R and Sobel Y in B.  G = Sobel.
2089ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2090ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBSobelXY(const uint8* src_argb, int src_stride_argb,
2091ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                uint8* dst_argb, int dst_stride_argb,
2092ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                int width, int height) {
2093ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely,
2094ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     uint8* dst_argb, int width) = SobelXYRow_C;
2095ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELXYROW_SSE2)
2096ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) &&
2097ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
2098ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelXYRow = SobelXYRow_SSE2;
2099ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_SOBELXYROW_NEON)
2102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) {
2103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    SobelXYRow = SobelXYRow_NEON;
2104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2106ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
2107ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      width, height, SobelXYRow);
2108ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2109ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2110ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a 4x4 polynomial to each ARGB pixel.
2111ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBPolynomial(const uint8* src_argb, int src_stride_argb,
2113ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   uint8* dst_argb, int dst_stride_argb,
2114ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   const float* poly,
2115ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                   int width, int height) {
2116ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
2117ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBPolynomialRow)(const uint8* src_argb,
2118ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            uint8* dst_argb, const float* poly,
2119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                            int width) = ARGBPolynomialRow_C;
2120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || !poly || width <= 0 || height == 0) {
2121ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
2122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2123ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
2124ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
2125ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
2126ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb  = src_argb  + (height - 1) * src_stride_argb;
2127ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
2128ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2129ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
2130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
2131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
2132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
2133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
2134ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
2135ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2136ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBPOLYNOMIALROW_SSE2)
2137ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 2)) {
2138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBPolynomialRow = ARGBPolynomialRow_SSE2;
2139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2140ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2141ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBPOLYNOMIALROW_AVX2)
2142ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && TestCpuFlag(kCpuHasFMA3) &&
2143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(width, 2)) {
2144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBPolynomialRow = ARGBPolynomialRow_AVX2;
2145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
2149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBPolynomialRow(src_argb, dst_argb, poly, width);
2150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
2151ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
2152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2156ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Apply a lumacolortable to each ARGB pixel.
2157ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBLumaColorTable(const uint8* src_argb, int src_stride_argb,
2159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       uint8* dst_argb, int dst_stride_argb,
2160ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       const uint8* luma,
2161ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       int width, int height) {
2162ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
2163ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBLumaColorTableRow)(const uint8* src_argb, uint8* dst_argb,
2164ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int width, const uint8* luma, const uint32 lumacoeff) =
2165ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBLumaColorTableRow_C;
2166ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || !luma || width <= 0 || height == 0) {
2167ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
2168ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2169ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
2170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
2171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
2172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb  = src_argb  + (height - 1) * src_stride_argb;
2173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
2174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
2176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
2177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
2178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
2179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
2180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
2181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBLUMACOLORTABLEROW_SSSE3)
2183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4)) {
2184ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBLumaColorTableRow = ARGBLumaColorTableRow_SSSE3;
2185ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2186ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
2189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBLumaColorTableRow(src_argb, dst_argb, width, luma, 0x00264b0f);
2190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
2191ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
2192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2193ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2194ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2195ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2196ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy Alpha from one ARGB image to another.
2197ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2198ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBCopyAlpha(const uint8* src_argb, int src_stride_argb,
2199ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint8* dst_argb, int dst_stride_argb,
2200ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int width, int height) {
2201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
2202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBCopyAlphaRow)(const uint8* src_argb, uint8* dst_argb, int width) =
2203ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBCopyAlphaRow_C;
2204ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
2205ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
2206ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2207ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
2208ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
2209ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
2210ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb = src_argb + (height - 1) * src_stride_argb;
2211ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = -src_stride_argb;
2212ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2213ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
2214ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_argb == width * 4 &&
2215ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
2216ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
2217ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
2218ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_argb = dst_stride_argb = 0;
2219ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2220ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOPYALPHAROW_SSE2)
2221ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) &&
2222ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
2223ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16) &&
2224ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(width, 8)) {
2225ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyAlphaRow = ARGBCopyAlphaRow_SSE2;
2226ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOPYALPHAROW_AVX2)
2229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) {
2230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyAlphaRow = ARGBCopyAlphaRow_AVX2;
2231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2232ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2233ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2234ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
2235ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyAlphaRow(src_argb, dst_argb, width);
2236ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_argb += src_stride_argb;
2237ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
2238ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2239ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2240ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2241ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2242ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// Copy a planar Y channel to the alpha channel of a destination ARGB image.
2243ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
2244ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y,
2245ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     uint8* dst_argb, int dst_stride_argb,
2246ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     int width, int height) {
2247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int y;
2248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  void (*ARGBCopyYToAlphaRow)(const uint8* src_y, uint8* dst_argb, int width) =
2249ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      ARGBCopyYToAlphaRow_C;
2250ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!src_y || !dst_argb || width <= 0 || height == 0) {
2251ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
2252ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2253ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Negative height means invert the image.
2254ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (height < 0) {
2255ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = -height;
2256ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y = src_y + (height - 1) * src_stride_y;
2257ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = -src_stride_y;
2258ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2259ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Coalesce rows.
2260ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_stride_y == width &&
2261ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      dst_stride_argb == width * 4) {
2262ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    width *= height;
2263ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    height = 1;
2264ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_stride_y = dst_stride_argb = 0;
2265ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2266ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOPYYTOALPHAROW_SSE2)
2267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasSSE2) &&
2268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
2269ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16) &&
2270ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      IS_ALIGNED(width, 8)) {
2271ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_SSE2;
2272ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2273ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2274ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#if defined(HAS_ARGBCOPYYTOALPHAROW_AVX2)
2275ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) {
2276ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_AVX2;
2277ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2278ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2279ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2280ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (y = 0; y < height; ++y) {
2281ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ARGBCopyYToAlphaRow(src_y, dst_argb, width);
2282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    src_y += src_stride_y;
2283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    dst_argb += dst_stride_argb;
2284ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
2285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
2286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
2287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2288ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef __cplusplus
2289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}  // extern "C"
2290ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}  // namespace libyuv
2291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
2292