149bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com/*
25fcf38cfc8b262f667933492a14b423a341d3795fbarchard@google.com *  Copyright 2013 The LibYuv Project Authors. All rights reserved.
349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com *
449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com *  Use of this source code is governed by a BSD-style license
549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com *  that can be found in the LICENSE file in the root of the source
649bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com *  tree. An additional intellectual property rights grant can be found
749bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com *  in the file PATENTS. All contributing project authors may
849bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com *  be found in the AUTHORS file in the root of the source tree.
949bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com */
1049bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com
1149bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#include "libyuv/scale.h"
1249bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com
1349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#include <assert.h>
1449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#include <string.h>
1549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com
1649bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#include "libyuv/cpu_id.h"
1749bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#include "libyuv/planar_functions.h"  // For CopyARGB
1849bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#include "libyuv/row.h"
195fcf38cfc8b262f667933492a14b423a341d3795fbarchard@google.com#include "libyuv/scale_row.h"
2049bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com
2149bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#ifdef __cplusplus
2249bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.comnamespace libyuv {
2349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.comextern "C" {
2449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#endif
2549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com
265e24e55f980cedec6ea37b184f28b33b7e918922fbarchard@google.comstatic __inline int Abs(int v) {
275e24e55f980cedec6ea37b184f28b33b7e918922fbarchard@google.com  return v >= 0 ? v : -v;
285e24e55f980cedec6ea37b184f28b33b7e918922fbarchard@google.com}
295e24e55f980cedec6ea37b184f28b33b7e918922fbarchard@google.com
30dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// CPU agnostic row functions
311f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.comvoid ScaleRowDown2_C(const uint8* src_ptr, ptrdiff_t src_stride,
32dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                     uint8* dst, int dst_width) {
33ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
34ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
35dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src_ptr[1];
36dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = src_ptr[3];
37dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
38dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_ptr += 4;
3906f730d8a64e1a3095347eb2eb68dc69e1626e03fbarchard@google.com  }
40dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
41dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src_ptr[1];
42dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
43dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
44dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
45b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown2_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
46b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                        uint16* dst, int dst_width) {
47b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
48b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
49b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = src_ptr[1];
50b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[1] = src_ptr[3];
51b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst += 2;
52b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    src_ptr += 4;
53b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
54b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
55b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = src_ptr[1];
56b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
57b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
58b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
59dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleRowDown2Linear_C(const uint8* src_ptr, ptrdiff_t src_stride,
60dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                           uint8* dst, int dst_width) {
61dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  const uint8* s = src_ptr;
62ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
63ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
64dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = (s[0] + s[1] + 1) >> 1;
65dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = (s[2] + s[3] + 1) >> 1;
66dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
67dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    s += 4;
6806f730d8a64e1a3095347eb2eb68dc69e1626e03fbarchard@google.com  }
69dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
70dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = (s[0] + s[1] + 1) >> 1;
71dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
72dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
73dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
74b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown2Linear_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
75b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                              uint16* dst, int dst_width) {
76b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  const uint16* s = src_ptr;
77b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
78b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
79b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = (s[0] + s[1] + 1) >> 1;
80b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[1] = (s[2] + s[3] + 1) >> 1;
81b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst += 2;
82b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    s += 4;
83b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
84b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
85b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = (s[0] + s[1] + 1) >> 1;
86b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
87b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
88b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
89dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleRowDown2Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
90dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                        uint8* dst, int dst_width) {
91dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  const uint8* s = src_ptr;
92dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  const uint8* t = src_ptr + src_stride;
93ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
94ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
95dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
96dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2;
97dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
98dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    s += 4;
99dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    t += 4;
10006f730d8a64e1a3095347eb2eb68dc69e1626e03fbarchard@google.com  }
101dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
102dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
103dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
104dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
105dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
106b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown2Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
107b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                           uint16* dst, int dst_width) {
108b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  const uint16* s = src_ptr;
109b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  const uint16* t = src_ptr + src_stride;
110b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
111b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
112b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
113b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2;
114b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst += 2;
115b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    s += 4;
116b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    t += 4;
117b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
118b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
119b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
120b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
121b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
122b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
1231f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.comvoid ScaleRowDown4_C(const uint8* src_ptr, ptrdiff_t src_stride,
124dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                     uint8* dst, int dst_width) {
125ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
126ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
127dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src_ptr[2];
128dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = src_ptr[6];
129dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
130dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_ptr += 8;
13106f730d8a64e1a3095347eb2eb68dc69e1626e03fbarchard@google.com  }
132dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
133dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src_ptr[2];
134dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
135dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
136dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
137b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown4_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
138b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                        uint16* dst, int dst_width) {
139b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
140b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
141b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = src_ptr[2];
142b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[1] = src_ptr[6];
143b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst += 2;
144b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    src_ptr += 8;
145b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
146b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
147b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = src_ptr[2];
148b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
149b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
150b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
151dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleRowDown4Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
152dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                        uint8* dst, int dst_width) {
153dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  intptr_t stride = src_stride;
154ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
155ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
156dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
157dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride + 0] + src_ptr[stride + 1] +
158dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride + 2] + src_ptr[stride + 3] +
159dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 2 + 0] + src_ptr[stride * 2 + 1] +
160dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 2 + 2] + src_ptr[stride * 2 + 3] +
161dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 3 + 0] + src_ptr[stride * 3 + 1] +
162dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 3 + 2] + src_ptr[stride * 3 + 3] +
163dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             8) >> 4;
164dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = (src_ptr[4] + src_ptr[5] + src_ptr[6] + src_ptr[7] +
165dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride + 4] + src_ptr[stride + 5] +
166dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride + 6] + src_ptr[stride + 7] +
167dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5] +
168dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7] +
169dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 3 + 4] + src_ptr[stride * 3 + 5] +
170dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 3 + 6] + src_ptr[stride * 3 + 7] +
171dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             8) >> 4;
172dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
173dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_ptr += 8;
17406f730d8a64e1a3095347eb2eb68dc69e1626e03fbarchard@google.com  }
175dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
176dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
177dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride + 0] + src_ptr[stride + 1] +
178dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride + 2] + src_ptr[stride + 3] +
179dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 2 + 0] + src_ptr[stride * 2 + 1] +
180dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 2 + 2] + src_ptr[stride * 2 + 3] +
181dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 3 + 0] + src_ptr[stride * 3 + 1] +
182dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             src_ptr[stride * 3 + 2] + src_ptr[stride * 3 + 3] +
183dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com             8) >> 4;
184dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
185dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
186dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
187b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown4Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
188b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                           uint16* dst, int dst_width) {
189b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  intptr_t stride = src_stride;
190b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
191b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
192b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
193b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride + 0] + src_ptr[stride + 1] +
194b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride + 2] + src_ptr[stride + 3] +
195b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 2 + 0] + src_ptr[stride * 2 + 1] +
196b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 2 + 2] + src_ptr[stride * 2 + 3] +
197b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 3 + 0] + src_ptr[stride * 3 + 1] +
198b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 3 + 2] + src_ptr[stride * 3 + 3] +
199b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             8) >> 4;
200b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[1] = (src_ptr[4] + src_ptr[5] + src_ptr[6] + src_ptr[7] +
201b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride + 4] + src_ptr[stride + 5] +
202b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride + 6] + src_ptr[stride + 7] +
203b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5] +
204b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7] +
205b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 3 + 4] + src_ptr[stride * 3 + 5] +
206b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 3 + 6] + src_ptr[stride * 3 + 7] +
207b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             8) >> 4;
208b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst += 2;
209b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    src_ptr += 8;
210b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
211b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
212b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
213b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride + 0] + src_ptr[stride + 1] +
214b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride + 2] + src_ptr[stride + 3] +
215b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 2 + 0] + src_ptr[stride * 2 + 1] +
216b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 2 + 2] + src_ptr[stride * 2 + 3] +
217b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 3 + 0] + src_ptr[stride * 3 + 1] +
218b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             src_ptr[stride * 3 + 2] + src_ptr[stride * 3 + 3] +
219b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com             8) >> 4;
220b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
221b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
222b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
2231f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.comvoid ScaleRowDown34_C(const uint8* src_ptr, ptrdiff_t src_stride,
224dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                      uint8* dst, int dst_width) {
225ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
226dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
227ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width; x += 3) {
228dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src_ptr[0];
229dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = src_ptr[1];
230dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[2] = src_ptr[3];
231dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 3;
232dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_ptr += 4;
23306f730d8a64e1a3095347eb2eb68dc69e1626e03fbarchard@google.com  }
234dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
235dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
236b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown34_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
237b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                         uint16* dst, int dst_width) {
238b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
239b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
240b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width; x += 3) {
241b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = src_ptr[0];
242b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[1] = src_ptr[1];
243b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[2] = src_ptr[3];
244b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst += 3;
245b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    src_ptr += 4;
246b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
247b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
248b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
249dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// Filter rows 0 and 1 together, 3 : 1
250dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleRowDown34_0_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
251dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                            uint8* d, int dst_width) {
252dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  const uint8* s = src_ptr;
253dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  const uint8* t = src_ptr + src_stride;
254ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
255ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
256ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width; x += 3) {
257dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
258dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
259dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
260dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
261dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
262dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
263dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    d[0] = (a0 * 3 + b0 + 2) >> 2;
264dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    d[1] = (a1 * 3 + b1 + 2) >> 2;
265dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    d[2] = (a2 * 3 + b2 + 2) >> 2;
266dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    d += 3;
267dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    s += 4;
268dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    t += 4;
26906f730d8a64e1a3095347eb2eb68dc69e1626e03fbarchard@google.com  }
270dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
271dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
272b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown34_0_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
273b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                               uint16* d, int dst_width) {
274b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  const uint16* s = src_ptr;
275b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  const uint16* t = src_ptr + src_stride;
276b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
277b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
278b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width; x += 3) {
279b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
280b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
281b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
282b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
283b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
284b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
285b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    d[0] = (a0 * 3 + b0 + 2) >> 2;
286b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    d[1] = (a1 * 3 + b1 + 2) >> 2;
287b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    d[2] = (a2 * 3 + b2 + 2) >> 2;
288b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    d += 3;
289b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    s += 4;
290b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    t += 4;
291b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
292b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
293b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
294dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// Filter rows 1 and 2 together, 1 : 1
295dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleRowDown34_1_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
296dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                            uint8* d, int dst_width) {
297dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  const uint8* s = src_ptr;
298dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  const uint8* t = src_ptr + src_stride;
299ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
300ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
301ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width; x += 3) {
302dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
303dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
304dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
305dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
306dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
307dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint8 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
308dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    d[0] = (a0 + b0 + 1) >> 1;
309dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    d[1] = (a1 + b1 + 1) >> 1;
310dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    d[2] = (a2 + b2 + 1) >> 1;
311dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    d += 3;
312dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    s += 4;
313dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    t += 4;
31406f730d8a64e1a3095347eb2eb68dc69e1626e03fbarchard@google.com  }
315dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
316dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
317b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown34_1_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
318b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                               uint16* d, int dst_width) {
319b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  const uint16* s = src_ptr;
320b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  const uint16* t = src_ptr + src_stride;
321b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
322b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
323b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width; x += 3) {
324b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
325b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
326b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
327b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
328b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
329b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    uint16 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
330b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    d[0] = (a0 + b0 + 1) >> 1;
331b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    d[1] = (a1 + b1 + 1) >> 1;
332b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    d[2] = (a2 + b2 + 1) >> 1;
333b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    d += 3;
334b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    s += 4;
335b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    t += 4;
336b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
337b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
338b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
339dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// Scales a single row of pixels using point sampling.
340dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleCols_C(uint8* dst_ptr, const uint8* src_ptr,
341dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                 int dst_width, int x, int dx) {
342ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
343ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
344dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[0] = src_ptr[x >> 16];
345dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    x += dx;
346dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[1] = src_ptr[x >> 16];
347dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    x += dx;
348dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr += 2;
349dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
350dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
351dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[0] = src_ptr[x >> 16];
352dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
353dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
354dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
355b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleCols_16_C(uint16* dst_ptr, const uint16* src_ptr,
356b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                    int dst_width, int x, int dx) {
357b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int j;
358b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
359b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = src_ptr[x >> 16];
360b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    x += dx;
361b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[1] = src_ptr[x >> 16];
362b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    x += dx;
363b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr += 2;
364b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
365b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
366b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = src_ptr[x >> 16];
367b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
368b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
369b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
370dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// Scales a single row of pixels up by 2x using point sampling.
371dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleColsUp2_C(uint8* dst_ptr, const uint8* src_ptr,
3721f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com                    int dst_width, int x, int dx) {
373ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
374ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
375dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[1] = dst_ptr[0] = src_ptr[0];
376dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_ptr += 1;
377dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr += 2;
378dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
379dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
380dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[0] = src_ptr[0];
381dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
382dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
383dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
384b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleColsUp2_16_C(uint16* dst_ptr, const uint16* src_ptr,
385b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                       int dst_width, int x, int dx) {
386b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int j;
387b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
388b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[1] = dst_ptr[0] = src_ptr[0];
389b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    src_ptr += 1;
390b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr += 2;
391b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
392b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
393b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = src_ptr[0];
394b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
395b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
396b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
397dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// (1-f)a + fb can be replaced with a + f(b-a)
398a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com#define BLENDER(a, b, f) (uint8)((int)(a) + \
399a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com    ((int)(f) * ((int)(b) - (int)(a)) >> 16))
400dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
401dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleFilterCols_C(uint8* dst_ptr, const uint8* src_ptr,
402dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                       int dst_width, int x, int dx) {
403ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
404ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
405dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int xi = x >> 16;
406dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int a = src_ptr[xi];
407dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int b = src_ptr[xi + 1];
408dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
409dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    x += dx;
410dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    xi = x >> 16;
411dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    a = src_ptr[xi];
412dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    b = src_ptr[xi + 1];
413dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[1] = BLENDER(a, b, x & 0xffff);
414dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    x += dx;
415dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr += 2;
416dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
417dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
418dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int xi = x >> 16;
419dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int a = src_ptr[xi];
420dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int b = src_ptr[xi + 1];
421dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
422dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
423dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
42490a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com
42590a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.comvoid ScaleFilterCols64_C(uint8* dst_ptr, const uint8* src_ptr,
42690a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com                         int dst_width, int x32, int dx) {
427a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  int64 x = (int64)(x32);
428ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
429ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
43090a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    int64 xi = x >> 16;
43190a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    int a = src_ptr[xi];
43290a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    int b = src_ptr[xi + 1];
43390a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
43490a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    x += dx;
43590a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    xi = x >> 16;
43690a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    a = src_ptr[xi];
43790a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    b = src_ptr[xi + 1];
43890a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    dst_ptr[1] = BLENDER(a, b, x & 0xffff);
43990a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    x += dx;
44090a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    dst_ptr += 2;
44190a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com  }
44290a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com  if (dst_width & 1) {
44390a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    int64 xi = x >> 16;
44490a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    int a = src_ptr[xi];
44590a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    int b = src_ptr[xi + 1];
44690a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
44790a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com  }
44890a36b29d3ffac9ecaa239191c7106c9993dc093fbarchard@google.com}
449dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com#undef BLENDER
450dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
451b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#define BLENDER(a, b, f) (uint16)((int)(a) + \
452b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    ((int)(f) * ((int)(b) - (int)(a)) >> 16))
453b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
454b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleFilterCols_16_C(uint16* dst_ptr, const uint16* src_ptr,
455b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                       int dst_width, int x, int dx) {
456b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int j;
457b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
458b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int xi = x >> 16;
459b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int a = src_ptr[xi];
460b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int b = src_ptr[xi + 1];
461b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
462b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    x += dx;
463b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    xi = x >> 16;
464b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    a = src_ptr[xi];
465b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    b = src_ptr[xi + 1];
466b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[1] = BLENDER(a, b, x & 0xffff);
467b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    x += dx;
468b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr += 2;
469b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
470b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
471b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int xi = x >> 16;
472b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int a = src_ptr[xi];
473b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int b = src_ptr[xi + 1];
474b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
475b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
476b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
477b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
478b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleFilterCols64_16_C(uint16* dst_ptr, const uint16* src_ptr,
479b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                         int dst_width, int x32, int dx) {
480b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int64 x = (int64)(x32);
481b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int j;
482b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
483b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int64 xi = x >> 16;
484b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int a = src_ptr[xi];
485b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int b = src_ptr[xi + 1];
486b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
487b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    x += dx;
488b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    xi = x >> 16;
489b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    a = src_ptr[xi];
490b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    b = src_ptr[xi + 1];
491b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[1] = BLENDER(a, b, x & 0xffff);
492b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    x += dx;
493b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr += 2;
494b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
495b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (dst_width & 1) {
496b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int64 xi = x >> 16;
497b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int a = src_ptr[xi];
498b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int b = src_ptr[xi + 1];
499b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
500b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
501b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
502b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#undef BLENDER
503b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
5041f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.comvoid ScaleRowDown38_C(const uint8* src_ptr, ptrdiff_t src_stride,
505dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                      uint8* dst, int dst_width) {
506ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
507dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  assert(dst_width % 3 == 0);
508ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width; x += 3) {
509dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src_ptr[0];
510dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = src_ptr[3];
511dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[2] = src_ptr[6];
512dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 3;
513dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_ptr += 8;
514dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
515dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
516dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
517b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown38_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
518b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                         uint16* dst, int dst_width) {
519b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
520b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert(dst_width % 3 == 0);
521b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < dst_width; x += 3) {
522b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[0] = src_ptr[0];
523b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[1] = src_ptr[3];
524b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst[2] = src_ptr[6];
525b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst += 3;
526b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    src_ptr += 8;
527b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
528b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
529b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
530dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// 8x3 -> 3x1
531dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleRowDown38_3_Box_C(const uint8* src_ptr,
532dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                            ptrdiff_t src_stride,
533dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                            uint8* dst_ptr, int dst_width) {
534dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  intptr_t stride = src_stride;
535ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int i;
536ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
537ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (i = 0; i < dst_width; i += 3) {
538dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
539dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 0] + src_ptr[stride + 1] +
540dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 2] + src_ptr[stride * 2 + 0] +
541dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2]) *
542dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        (65536 / 9) >> 16;
543dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
544dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 3] + src_ptr[stride + 4] +
545dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 5] + src_ptr[stride * 2 + 3] +
546dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5]) *
547dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        (65536 / 9) >> 16;
548dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
549dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 6] + src_ptr[stride + 7] +
550dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7]) *
551dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        (65536 / 6) >> 16;
552dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_ptr += 8;
553dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr += 3;
554dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
555dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
556dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
557b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown38_3_Box_16_C(const uint16* src_ptr,
558b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                               ptrdiff_t src_stride,
559b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                               uint16* dst_ptr, int dst_width) {
560b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  intptr_t stride = src_stride;
561b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int i;
562b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
563b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (i = 0; i < dst_width; i += 3) {
564b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
565b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 0] + src_ptr[stride + 1] +
566b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 2] + src_ptr[stride * 2 + 0] +
567b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2]) *
568b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        (65536 / 9) >> 16;
569b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
570b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 3] + src_ptr[stride + 4] +
571b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 5] + src_ptr[stride * 2 + 3] +
572b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5]) *
573b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        (65536 / 9) >> 16;
574b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
575b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 6] + src_ptr[stride + 7] +
576b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7]) *
577b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        (65536 / 6) >> 16;
578b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    src_ptr += 8;
579b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr += 3;
580b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
581b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
582b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
583dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// 8x2 -> 3x1
584dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleRowDown38_2_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
585dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                            uint8* dst_ptr, int dst_width) {
586dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  intptr_t stride = src_stride;
587ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int i;
588ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
589ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (i = 0; i < dst_width; i += 3) {
590dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
591dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 0] + src_ptr[stride + 1] +
592dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 2]) * (65536 / 6) >> 16;
593dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
594dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 3] + src_ptr[stride + 4] +
595dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 5]) * (65536 / 6) >> 16;
596dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
597dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        src_ptr[stride + 6] + src_ptr[stride + 7]) *
598dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com        (65536 / 4) >> 16;
599dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_ptr += 8;
600dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr += 3;
601dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
602dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
603dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
604b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleRowDown38_2_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
605b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                               uint16* dst_ptr, int dst_width) {
606b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  intptr_t stride = src_stride;
607b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int i;
608b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert((dst_width % 3 == 0) && (dst_width > 0));
609b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (i = 0; i < dst_width; i += 3) {
610b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
611b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 0] + src_ptr[stride + 1] +
612b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 2]) * (65536 / 6) >> 16;
613b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
614b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 3] + src_ptr[stride + 4] +
615b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 5]) * (65536 / 6) >> 16;
616b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
617b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        src_ptr[stride + 6] + src_ptr[stride + 7]) *
618b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        (65536 / 4) >> 16;
619b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    src_ptr += 8;
620b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr += 3;
621b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
622b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
623b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
624dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleAddRows_C(const uint8* src_ptr, ptrdiff_t src_stride,
625dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                    uint16* dst_ptr, int src_width, int src_height) {
626ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
627dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  assert(src_width > 0);
628dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  assert(src_height > 0);
629ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < src_width; ++x) {
630dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    const uint8* s = src_ptr + x;
631dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    unsigned int sum = 0u;
632ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com    int y;
633ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com    for (y = 0; y < src_height; ++y) {
634dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com      sum += s[0];
635dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com      s += src_stride;
636dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    }
637dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    // TODO(fbarchard): Consider limitting height to 256 to avoid overflow.
638dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_ptr[x] = sum < 65535u ? sum : 65535u;
639dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
640dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
641dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
642b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScaleAddRows_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
643b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                       uint32* dst_ptr, int src_width, int src_height) {
644b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int x;
645b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert(src_width > 0);
646b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert(src_height > 0);
647b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (x = 0; x < src_width; ++x) {
648b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    const uint16* s = src_ptr + x;
649b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    unsigned int sum = 0u;
650b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int y;
651b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    for (y = 0; y < src_height; ++y) {
652b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      sum += s[0];
653b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      s += src_stride;
654b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    }
655b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    // No risk of overflow here now
656b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_ptr[x] = sum;
657b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
658b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
659b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com
660dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleARGBRowDown2_C(const uint8* src_argb,
6611f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com                         ptrdiff_t src_stride,
662dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                         uint8* dst_argb, int dst_width) {
663a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  const uint32* src = (const uint32*)(src_argb);
664a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  uint32* dst = (uint32*)(dst_argb);
665dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
666ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
667ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
668dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src[1];
669dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = src[3];
670dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src += 4;
671dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
672dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
673dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
674dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src[1];
675dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
676dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
677dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
678dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleARGBRowDown2Linear_C(const uint8* src_argb,
6791f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com                               ptrdiff_t src_stride,
680dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                               uint8* dst_argb, int dst_width) {
681ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
682ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width; ++x) {
683dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[0] = (src_argb[0] + src_argb[4] + 1) >> 1;
684dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[1] = (src_argb[1] + src_argb[5] + 1) >> 1;
685dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[2] = (src_argb[2] + src_argb[6] + 1) >> 1;
686dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[3] = (src_argb[3] + src_argb[7] + 1) >> 1;
687dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_argb += 8;
688dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb += 4;
689dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
690dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
691dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
692dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleARGBRowDown2Box_C(const uint8* src_argb, ptrdiff_t src_stride,
693dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                            uint8* dst_argb, int dst_width) {
694ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
695ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width; ++x) {
696dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[0] = (src_argb[0] + src_argb[4] +
697dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                  src_argb[src_stride] + src_argb[src_stride + 4] + 2) >> 2;
698dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[1] = (src_argb[1] + src_argb[5] +
699dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                  src_argb[src_stride + 1] + src_argb[src_stride + 5] + 2) >> 2;
700dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[2] = (src_argb[2] + src_argb[6] +
701dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                  src_argb[src_stride + 2] + src_argb[src_stride + 6] + 2) >> 2;
702dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[3] = (src_argb[3] + src_argb[7] +
703dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                  src_argb[src_stride + 3] + src_argb[src_stride + 7] + 2) >> 2;
704dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_argb += 8;
705dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb += 4;
706dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
707dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
708dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
7091f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.comvoid ScaleARGBRowDownEven_C(const uint8* src_argb, ptrdiff_t src_stride,
710dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                            int src_stepx,
711dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                            uint8* dst_argb, int dst_width) {
712a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  const uint32* src = (const uint32*)(src_argb);
713a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  uint32* dst = (uint32*)(dst_argb);
714dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
715ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
716ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width - 1; x += 2) {
717dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src[0];
718dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = src[src_stepx];
719dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src += src_stepx * 2;
720dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
721dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
722dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
723dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src[0];
724dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
725dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
726dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
727dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleARGBRowDownEvenBox_C(const uint8* src_argb,
728dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                               ptrdiff_t src_stride,
729dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                               int src_stepx,
730dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                               uint8* dst_argb, int dst_width) {
731ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int x;
732ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (x = 0; x < dst_width; ++x) {
733dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[0] = (src_argb[0] + src_argb[4] +
734dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                  src_argb[src_stride] + src_argb[src_stride + 4] + 2) >> 2;
735dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[1] = (src_argb[1] + src_argb[5] +
736dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                  src_argb[src_stride + 1] + src_argb[src_stride + 5] + 2) >> 2;
737dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[2] = (src_argb[2] + src_argb[6] +
738dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                  src_argb[src_stride + 2] + src_argb[src_stride + 6] + 2) >> 2;
739dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb[3] = (src_argb[3] + src_argb[7] +
740dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                  src_argb[src_stride + 3] + src_argb[src_stride + 7] + 2) >> 2;
741dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src_argb += src_stepx * 4;
742dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst_argb += 4;
743dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
744dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
745dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
746dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// Scales a single row of pixels using point sampling.
747dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleARGBCols_C(uint8* dst_argb, const uint8* src_argb,
748dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                     int dst_width, int x, int dx) {
749a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  const uint32* src = (const uint32*)(src_argb);
750a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  uint32* dst = (uint32*)(dst_argb);
751ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
752ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
753dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src[x >> 16];
754dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    x += dx;
755dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = src[x >> 16];
756dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    x += dx;
757dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
758dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
759dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
760dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src[x >> 16];
761dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
762dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
763dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
764909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.comvoid ScaleARGBCols64_C(uint8* dst_argb, const uint8* src_argb,
765909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com                       int dst_width, int x32, int dx) {
766a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  int64 x = (int64)(x32);
767a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  const uint32* src = (const uint32*)(src_argb);
768a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  uint32* dst = (uint32*)(dst_argb);
769ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
770ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
771909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com    dst[0] = src[x >> 16];
772909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com    x += dx;
773909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com    dst[1] = src[x >> 16];
774909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com    x += dx;
775909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com    dst += 2;
776909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com  }
777909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com  if (dst_width & 1) {
778909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com    dst[0] = src[x >> 16];
779909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com  }
780909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com}
781909c76e317028a21db491413b2c5d1a05c1fde5bfbarchard@google.com
782dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// Scales a single row of pixels up by 2x using point sampling.
783dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleARGBColsUp2_C(uint8* dst_argb, const uint8* src_argb,
7841f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com                        int dst_width, int x, int dx) {
785a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  const uint32* src = (const uint32*)(src_argb);
786a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  uint32* dst = (uint32*)(dst_argb);
787ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
788ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
789dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = dst[0] = src[0];
790dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    src += 1;
791dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
792dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
793dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
794dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = src[0];
795dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
796dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
797dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
798dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com// Mimics SSSE3 blender
799dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com#define BLENDER1(a, b, f) ((a) * (0x7f ^ f) + (b) * f) >> 7
800a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com#define BLENDERC(a, b, f, s) (uint32)( \
801dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    BLENDER1(((a) >> s) & 255, ((b) >> s) & 255, f) << s)
802dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com#define BLENDER(a, b, f) \
803dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    BLENDERC(a, b, f, 24) | BLENDERC(a, b, f, 16) | \
804dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    BLENDERC(a, b, f, 8) | BLENDERC(a, b, f, 0)
805dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
806dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.comvoid ScaleARGBFilterCols_C(uint8* dst_argb, const uint8* src_argb,
807dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com                           int dst_width, int x, int dx) {
808a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  const uint32* src = (const uint32*)(src_argb);
809a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  uint32* dst = (uint32*)(dst_argb);
810ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
811ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
812dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int xi = x >> 16;
813dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int xf = (x >> 9) & 0x7f;
814dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint32 a = src[xi];
815dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint32 b = src[xi + 1];
816dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = BLENDER(a, b, xf);
817dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    x += dx;
818dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    xi = x >> 16;
819dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    xf = (x >> 9) & 0x7f;
820dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    a = src[xi];
821dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    b = src[xi + 1];
822dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[1] = BLENDER(a, b, xf);
823dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    x += dx;
824dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst += 2;
825dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
826dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  if (dst_width & 1) {
827dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int xi = x >> 16;
828dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    int xf = (x >> 9) & 0x7f;
829dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint32 a = src[xi];
830dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    uint32 b = src[xi + 1];
831dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com    dst[0] = BLENDER(a, b, xf);
832dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com  }
833dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com}
8346dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com
8356dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.comvoid ScaleARGBFilterCols64_C(uint8* dst_argb, const uint8* src_argb,
8366dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com                             int dst_width, int x32, int dx) {
837a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  int64 x = (int64)(x32);
838a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  const uint32* src = (const uint32*)(src_argb);
839a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  uint32* dst = (uint32*)(dst_argb);
840ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
841ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_width - 1; j += 2) {
8426dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    int64 xi = x >> 16;
8436dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    int xf = (x >> 9) & 0x7f;
8446dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    uint32 a = src[xi];
8456dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    uint32 b = src[xi + 1];
8466dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    dst[0] = BLENDER(a, b, xf);
8476dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    x += dx;
8486dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    xi = x >> 16;
8496dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    xf = (x >> 9) & 0x7f;
8506dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    a = src[xi];
8516dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    b = src[xi + 1];
8526dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    dst[1] = BLENDER(a, b, xf);
8536dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    x += dx;
8546dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    dst += 2;
8556dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com  }
8566dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com  if (dst_width & 1) {
8576dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    int64 xi = x >> 16;
8586dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    int xf = (x >> 9) & 0x7f;
8596dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    uint32 a = src[xi];
8606dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    uint32 b = src[xi + 1];
8616dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com    dst[0] = BLENDER(a, b, xf);
8626dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com  }
8636dc80ab585de785ea3492ac3f8a66f2252edb9f8fbarchard@google.com}
864dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com#undef BLENDER1
865dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com#undef BLENDERC
866dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com#undef BLENDER
867dbe4814361fb8fcbc462bbe45a2f39360e14a982fbarchard@google.com
8685fcf38cfc8b262f667933492a14b423a341d3795fbarchard@google.com// Scale plane vertically with bilinear interpolation.
8695fcf38cfc8b262f667933492a14b423a341d3795fbarchard@google.comvoid ScalePlaneVertical(int src_height,
8705fcf38cfc8b262f667933492a14b423a341d3795fbarchard@google.com                        int dst_width, int dst_height,
8715fcf38cfc8b262f667933492a14b423a341d3795fbarchard@google.com                        int src_stride, int dst_stride,
8725fcf38cfc8b262f667933492a14b423a341d3795fbarchard@google.com                        const uint8* src_argb, uint8* dst_argb,
8735fcf38cfc8b262f667933492a14b423a341d3795fbarchard@google.com                        int x, int y, int dy,
874db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com                        int bpp, enum FilterMode filtering) {
875ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  // TODO(fbarchard): Allow higher bpp.
876ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int dst_width_bytes = dst_width * bpp;
877ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
878ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
879ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com      InterpolateRow_C;
880ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
881ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  int j;
882ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  assert(bpp >= 1 && bpp <= 4);
88399a1298c54dc35348295165745521120818263b8fbarchard@google.com  assert(src_height != 0);
88449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com  assert(dst_width > 0);
88549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com  assert(dst_height > 0);
886ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  src_argb += (x >> 16) * bpp;
88749bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#if defined(HAS_INTERPOLATEROW_SSE2)
888ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && dst_width_bytes >= 16) {
88949bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    InterpolateRow = InterpolateRow_Any_SSE2;
890ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 16)) {
89149bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      InterpolateRow = InterpolateRow_Unaligned_SSE2;
89249bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
89349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
89449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com        InterpolateRow = InterpolateRow_SSE2;
89549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      }
89649bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    }
89749bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com  }
89849bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#endif
89949bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#if defined(HAS_INTERPOLATEROW_SSSE3)
900ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && dst_width_bytes >= 16) {
90149bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    InterpolateRow = InterpolateRow_Any_SSSE3;
902ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 16)) {
90349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      InterpolateRow = InterpolateRow_Unaligned_SSSE3;
90449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
90549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
90649bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com        InterpolateRow = InterpolateRow_SSSE3;
90749bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      }
90849bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    }
90949bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com  }
91049bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#endif
9112154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com#if defined(HAS_INTERPOLATEROW_AVX2)
912ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (TestCpuFlag(kCpuHasAVX2) && dst_width_bytes >= 32) {
9132154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com    InterpolateRow = InterpolateRow_Any_AVX2;
914ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 32)) {
9152154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com      InterpolateRow = InterpolateRow_AVX2;
9162154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com    }
9172154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com  }
9182154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com#endif
91949bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#if defined(HAS_INTERPOLATEROW_NEON)
920ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && dst_width_bytes >= 16) {
92149bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    InterpolateRow = InterpolateRow_Any_NEON;
922ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 16)) {
92349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      InterpolateRow = InterpolateRow_NEON;
92449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    }
92549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com  }
92649bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#endif
92749bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2)
928ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width_bytes >= 4 &&
92949bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) &&
93049bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) {
93149bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    InterpolateRow = InterpolateRow_Any_MIPS_DSPR2;
932ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 4)) {
93349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      InterpolateRow = InterpolateRow_MIPS_DSPR2;
93449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    }
93549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com  }
93649bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#endif
937ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com  for (j = 0; j < dst_height; ++j) {
938ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com    int yi;
939ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com    int yf;
94049bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    if (y > max_y) {
94149bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com      y = max_y;
94249bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    }
943ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com    yi = y >> 16;
944ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com    yf = filtering ? ((y >> 8) & 255) : 0;
945ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com    InterpolateRow(dst_argb, src_argb + yi * src_stride,
946ecf5a1446eca7ce9f66600cb08ad7a6e032eac91fbarchard@google.com                   src_stride, dst_width_bytes, yf);
94749bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    dst_argb += dst_stride;
94849bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com    y += dy;
94949bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com  }
95049bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com}
951b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid ScalePlaneVertical_16(int src_height,
952b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                           int dst_width, int dst_height,
953b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                           int src_stride, int dst_stride,
954b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                           const uint16* src_argb, uint16* dst_argb,
955b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                           int x, int y, int dy,
956b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                           int wpp, enum FilterMode filtering) {
957b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  // TODO(fbarchard): Allow higher wpp.
958b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int dst_width_words = dst_width * wpp;
959b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  void (*InterpolateRow)(uint16* dst_argb, const uint16* src_argb,
960b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
961b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      InterpolateRow_16_C;
962b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
963b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  int j;
964b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert(wpp >= 1 && wpp <= 2);
965b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert(src_height != 0);
966b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert(dst_width > 0);
967b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  assert(dst_height > 0);
968b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  src_argb += (x >> 16) * wpp;
969b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_INTERPOLATEROW_16_SSE2)
970b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (TestCpuFlag(kCpuHasSSE2) && dst_width_bytes >= 16) {
971b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    InterpolateRow = InterpolateRow_Any_16_SSE2;
972b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 16)) {
973b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      InterpolateRow = InterpolateRow_Unaligned_16_SSE2;
974b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
975b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
976b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        InterpolateRow = InterpolateRow_16_SSE2;
977b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      }
978b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    }
979b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
980b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif
981b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_INTERPOLATEROW_16_SSSE3)
982b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (TestCpuFlag(kCpuHasSSSE3) && dst_width_bytes >= 16) {
983b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    InterpolateRow = InterpolateRow_Any_16_SSSE3;
984b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 16)) {
985b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      InterpolateRow = InterpolateRow_Unaligned_16_SSSE3;
986b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) &&
987b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com          IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) {
988b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com        InterpolateRow = InterpolateRow_16_SSSE3;
989b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      }
990b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    }
991b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
992b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif
993b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_INTERPOLATEROW_16_AVX2)
994b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (TestCpuFlag(kCpuHasAVX2) && dst_width_bytes >= 32) {
995b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    InterpolateRow = InterpolateRow_Any_16_AVX2;
996b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 32)) {
997b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      InterpolateRow = InterpolateRow_16_AVX2;
998b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    }
999b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
1000b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif
1001b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_INTERPOLATEROW_16_NEON)
1002b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (TestCpuFlag(kCpuHasNEON) && dst_width_bytes >= 16) {
1003b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    InterpolateRow = InterpolateRow_Any_16_NEON;
1004b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 16)) {
1005b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      InterpolateRow = InterpolateRow_16_NEON;
1006b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    }
1007b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
1008b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif
1009b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_INTERPOLATEROWS_16_MIPS_DSPR2)
1010b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_width_bytes >= 4 &&
1011b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) &&
1012b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) {
1013b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    InterpolateRow = InterpolateRow_Any_16_MIPS_DSPR2;
1014b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    if (IS_ALIGNED(dst_width_bytes, 4)) {
1015b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      InterpolateRow = InterpolateRow_16_MIPS_DSPR2;
1016b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    }
1017b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
1018b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif
1019b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  for (j = 0; j < dst_height; ++j) {
1020b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int yi;
1021b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    int yf;
1022b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    if (y > max_y) {
1023b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com      y = max_y;
1024b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    }
1025b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    yi = y >> 16;
1026b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    yf = filtering ? ((y >> 8) & 255) : 0;
1027b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    InterpolateRow(dst_argb, src_argb + yi * src_stride,
1028b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com                   src_stride, dst_width_words, yf);
1029b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    dst_argb += dst_stride;
1030b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com    y += dy;
1031b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com  }
1032b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com}
103349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com
1034980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com// Simplify the filtering based on scale factors.
1035db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.comenum FilterMode ScaleFilterReduce(int src_width, int src_height,
1036db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com                                  int dst_width, int dst_height,
1037db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com                                  enum FilterMode filtering) {
1038ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (src_width < 0) {
1039ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    src_width = -src_width;
1040ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  }
1041ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (src_height < 0) {
1042ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    src_height = -src_height;
1043ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  }
1044ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (filtering == kFilterBox) {
1045ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    // If scaling both axis to 0.5 or larger, switch from Box to Bilinear.
1046ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (dst_width * 2 >= src_width && dst_height * 2 >= src_height) {
1047ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com      filtering = kFilterBilinear;
1048ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    }
1049ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    // If scaling to larger, switch from Box to Bilinear.
1050ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (dst_width >= src_width || dst_height >= src_height) {
1051ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com      filtering = kFilterBilinear;
1052ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    }
1053ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  }
1054ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (filtering == kFilterBilinear) {
1055ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (src_height == 1) {
1056ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com      filtering = kFilterLinear;
1057ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    }
1058ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    // TODO(fbarchard): Detect any odd scale factor and reduce to Linear.
1059ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (dst_height == src_height || dst_height * 3 == src_height) {
1060ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com      filtering = kFilterLinear;
1061ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    }
1062a6b8e0da516350c5395ffcfebd5c49f717c84bddfbarchard@google.com    // TODO(fbarchard): Remove 1 pixel wide filter restriction, which is to
1063a6b8e0da516350c5395ffcfebd5c49f717c84bddfbarchard@google.com    // avoid reading 2 pixels horizontally that causes memory exception.
1064a6b8e0da516350c5395ffcfebd5c49f717c84bddfbarchard@google.com    if (src_width == 1) {
1065a6b8e0da516350c5395ffcfebd5c49f717c84bddfbarchard@google.com      filtering = kFilterNone;
1066a6b8e0da516350c5395ffcfebd5c49f717c84bddfbarchard@google.com    }
1067ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  }
1068ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  if (filtering == kFilterLinear) {
1069ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (src_width == 1) {
1070ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com      filtering = kFilterNone;
1071ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    }
1072ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    // TODO(fbarchard): Detect any odd scale factor and reduce to None.
1073ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    if (dst_width == src_width || dst_width * 3 == src_width) {
1074ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com      filtering = kFilterNone;
1075ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com    }
1076ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  }
1077ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com  return filtering;
1078ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com}
1079ec0cc5bb2dc308a69f870adfbe019d5e5eea9f9ffbarchard@google.com
10805dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com// Divide num by div and return as 16.16 fixed point result.
10815dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.comint FixedDiv_C(int num, int div) {
1082a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  return (int)(((int64)(num) << 16) / div);
10835dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com}
10845dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com
10855dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com// Divide num by div and return as 16.16 fixed point result.
10865dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.comint FixedDiv1_C(int num, int div) {
1087a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  return (int)((((int64)(num) << 16) - 0x00010001) /
10885dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com                          (div - 1));
10895dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com}
10905dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com
1091980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com#define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s)
1092980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com
1093980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com// Compute slope values for stepping.
1094980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.comvoid ScaleSlope(int src_width, int src_height,
10955e24e55f980cedec6ea37b184f28b33b7e918922fbarchard@google.com                int dst_width, int dst_height,
1096db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com                enum FilterMode filtering,
1097980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com                int* x, int* y, int* dx, int* dy) {
1098980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  assert(x != NULL);
1099980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  assert(y != NULL);
1100980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  assert(dx != NULL);
1101980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  assert(dy != NULL);
1102980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  assert(src_width != 0);
1103980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  assert(src_height != 0);
1104980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  assert(dst_width > 0);
1105980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  assert(dst_height > 0);
1106ac9b96c076f1d62f34fbc9182d1aca46d2f0b75afbarchard@google.com  // Check for 1 pixel and avoid FixedDiv overflow.
1107dd4995805827539ee2c5b4b65c7514e62df2d358fbarchard@google.com  if (dst_width == 1 && src_width >= 32768) {
1108ac9b96c076f1d62f34fbc9182d1aca46d2f0b75afbarchard@google.com    dst_width = src_width;
1109ac9b96c076f1d62f34fbc9182d1aca46d2f0b75afbarchard@google.com  }
1110dd4995805827539ee2c5b4b65c7514e62df2d358fbarchard@google.com  if (dst_height == 1 && src_height >= 32768) {
1111ac9b96c076f1d62f34fbc9182d1aca46d2f0b75afbarchard@google.com    dst_height = src_height;
1112ac9b96c076f1d62f34fbc9182d1aca46d2f0b75afbarchard@google.com  }
1113980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  if (filtering == kFilterBox) {
1114980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    // Scale step for point sampling duplicates all pixels equally.
1115980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *dx = FixedDiv(Abs(src_width), dst_width);
1116980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *dy = FixedDiv(src_height, dst_height);
1117980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *x = 0;
1118980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *y = 0;
1119980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  } else if (filtering == kFilterBilinear) {
1120980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    // Scale step for bilinear sampling renders last pixel once for upsample.
1121980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    if (dst_width <= Abs(src_width)) {
1122980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com      *dx = FixedDiv(Abs(src_width), dst_width);
1123a6b8e0da516350c5395ffcfebd5c49f717c84bddfbarchard@google.com      *x = CENTERSTART(*dx, -32768);  // Subtract 0.5 (32768) to center filter.
1124980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    } else if (dst_width > 1) {
11255dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com      *dx = FixedDiv1(Abs(src_width), dst_width);
1126980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com      *x = 0;
1127980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    }
1128980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    if (dst_height <= src_height) {
1129980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com      *dy = FixedDiv(src_height,  dst_height);
1130a6b8e0da516350c5395ffcfebd5c49f717c84bddfbarchard@google.com      *y = CENTERSTART(*dy, -32768);  // Subtract 0.5 (32768) to center filter.
1131980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    } else if (dst_height > 1) {
11325dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com      *dy = FixedDiv1(src_height, dst_height);
1133980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com      *y = 0;
1134980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    }
1135980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  } else if (filtering == kFilterLinear) {
1136980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    // Scale step for bilinear sampling renders last pixel once for upsample.
1137980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    if (dst_width <= Abs(src_width)) {
1138980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com      *dx = FixedDiv(Abs(src_width), dst_width);
1139a6b8e0da516350c5395ffcfebd5c49f717c84bddfbarchard@google.com      *x = CENTERSTART(*dx, -32768);  // Subtract 0.5 (32768) to center filter.
1140980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    } else if (dst_width > 1) {
11415dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com      *dx = FixedDiv1(Abs(src_width), dst_width);
1142980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com      *x = 0;
1143980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    }
1144980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *dy = FixedDiv(src_height, dst_height);
1145980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *y = *dy >> 1;
1146980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  } else {
1147980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    // Scale step for point sampling duplicates all pixels equally.
1148980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *dx = FixedDiv(Abs(src_width), dst_width);
1149980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *dy = FixedDiv(src_height, dst_height);
1150980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *x = CENTERSTART(*dx, 0);
1151980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *y = CENTERSTART(*dy, 0);
1152980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  }
1153980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  // Negative src_width means horizontally mirror.
1154980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  if (src_width < 0) {
11555e24e55f980cedec6ea37b184f28b33b7e918922fbarchard@google.com    *x += (dst_width - 1) * *dx;
1156980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com    *dx = -*dx;
11576700a27c97a046d08386dfc7e4486ec285782007fbarchard@google.com    // src_width = -src_width;   // Caller must do this.
1158980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com  }
1159980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com}
1160980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com#undef CENTERSTART
1161980150f7f1c9cf99b1729d0274b46092a47449bdfbarchard@google.com
116249bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#ifdef __cplusplus
116349bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com}  // extern "C"
116449bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com}  // namespace libyuv
116549bbc1b4f368e7e30fe5f12663b2334a5213752efbarchard@google.com#endif
1166