1f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang/*
2f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  Copyright 2013 The LibYuv Project Authors. All rights reserved.
3f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *
4f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  Use of this source code is governed by a BSD-style license
5f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  that can be found in the LICENSE file in the root of the source
6f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  tree. An additional intellectual property rights grant can be found
7f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  in the file PATENTS. All contributing project authors may
8f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  be found in the AUTHORS file in the root of the source tree.
9f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang */
10f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
11f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/scale.h"
12f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
13f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include <assert.h>
14f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include <string.h>
15f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
16f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/cpu_id.h"
17f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/planar_functions.h"  // For CopyARGB
18f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/row.h"
19f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/scale_row.h"
20f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
21f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#ifdef __cplusplus
22f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangnamespace libyuv {
23f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangextern "C" {
24f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
25f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
26f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangstatic __inline int Abs(int v) {
27f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  return v >= 0 ? v : -v;
28f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
29f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
30f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// CPU agnostic row functions
31f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown2_C(const uint8* src_ptr, ptrdiff_t src_stride,
32f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                     uint8* dst, int dst_width) {
33f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
34f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
35f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[1];
36f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src_ptr[3];
37f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
38f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 4;
39f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
40f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
41f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[1];
42f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
43f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
44f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
45f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown2_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
46f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        uint16* dst, int dst_width) {
47f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
48f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
49f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[1];
50f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src_ptr[3];
51f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
52f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 4;
53f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
54f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
55f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[1];
56f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
57f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
58f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
59f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown2Linear_C(const uint8* src_ptr, ptrdiff_t src_stride,
60f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           uint8* dst, int dst_width) {
61f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* s = src_ptr;
62f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
63f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
64f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + 1) >> 1;
65f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = (s[2] + s[3] + 1) >> 1;
66f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
67f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
68f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
69f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
70f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + 1) >> 1;
71f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
72f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
73f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
74f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown2Linear_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
75f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                              uint16* dst, int dst_width) {
76f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint16* s = src_ptr;
77f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
78f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
79f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + 1) >> 1;
80f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = (s[2] + s[3] + 1) >> 1;
81f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
82f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
83f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
84f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
85f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + 1) >> 1;
86f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
87f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
88f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
89f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown2Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
90f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        uint8* dst, int dst_width) {
91f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* s = src_ptr;
92f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* t = src_ptr + src_stride;
93f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
94f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
95f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
96f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2;
97f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
98f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
99f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    t += 4;
100f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
101f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
102f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
103f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
104f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
105f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
106f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown2Box_Odd_C(const uint8* src_ptr, ptrdiff_t src_stride,
107f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            uint8* dst, int dst_width) {
108f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* s = src_ptr;
109f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* t = src_ptr + src_stride;
110f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
111f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  dst_width -= 1;
112f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
113f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
114f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2;
115f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
116f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
117f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    t += 4;
118f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
119f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
120f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
121f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 1;
122f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 2;
123f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    t += 2;
124f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
125f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  dst[0] = (s[0] + t[0] + 1) >> 1;
126f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
127f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
128f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown2Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
129f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           uint16* dst, int dst_width) {
130f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint16* s = src_ptr;
131f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint16* t = src_ptr + src_stride;
132f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
133f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
134f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
135f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2;
136f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
137f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
138f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    t += 4;
139f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
140f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
141f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
142f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
143f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
144f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
145f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown4_C(const uint8* src_ptr, ptrdiff_t src_stride,
146f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                     uint8* dst, int dst_width) {
147f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
148f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
149f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[2];
150f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src_ptr[6];
151f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
152f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
153f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
154f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
155f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[2];
156f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
157f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
158f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
159f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown4_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
160f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        uint16* dst, int dst_width) {
161f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
162f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
163f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[2];
164f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src_ptr[6];
165f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
166f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
167f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
168f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
169f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[2];
170f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
171f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
172f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
173f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown4Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
174f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        uint8* dst, int dst_width) {
175f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  intptr_t stride = src_stride;
176f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
177f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
178f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
179f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 0] + src_ptr[stride + 1] +
180f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 2] + src_ptr[stride + 3] +
181f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 0] + src_ptr[stride * 2 + 1] +
182f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 2] + src_ptr[stride * 2 + 3] +
183f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 0] + src_ptr[stride * 3 + 1] +
184f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 2] + src_ptr[stride * 3 + 3] +
185f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             8) >> 4;
186f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = (src_ptr[4] + src_ptr[5] + src_ptr[6] + src_ptr[7] +
187f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 4] + src_ptr[stride + 5] +
188f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 6] + src_ptr[stride + 7] +
189f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5] +
190f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7] +
191f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 4] + src_ptr[stride * 3 + 5] +
192f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 6] + src_ptr[stride * 3 + 7] +
193f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             8) >> 4;
194f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
195f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
196f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
197f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
198f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
199f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 0] + src_ptr[stride + 1] +
200f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 2] + src_ptr[stride + 3] +
201f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 0] + src_ptr[stride * 2 + 1] +
202f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 2] + src_ptr[stride * 2 + 3] +
203f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 0] + src_ptr[stride * 3 + 1] +
204f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 2] + src_ptr[stride * 3 + 3] +
205f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             8) >> 4;
206f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
207f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
208f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
209f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown4Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
210f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           uint16* dst, int dst_width) {
211f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  intptr_t stride = src_stride;
212f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
213f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
214f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
215f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 0] + src_ptr[stride + 1] +
216f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 2] + src_ptr[stride + 3] +
217f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 0] + src_ptr[stride * 2 + 1] +
218f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 2] + src_ptr[stride * 2 + 3] +
219f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 0] + src_ptr[stride * 3 + 1] +
220f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 2] + src_ptr[stride * 3 + 3] +
221f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             8) >> 4;
222f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = (src_ptr[4] + src_ptr[5] + src_ptr[6] + src_ptr[7] +
223f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 4] + src_ptr[stride + 5] +
224f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 6] + src_ptr[stride + 7] +
225f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5] +
226f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7] +
227f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 4] + src_ptr[stride * 3 + 5] +
228f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 6] + src_ptr[stride * 3 + 7] +
229f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             8) >> 4;
230f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
231f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
232f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
233f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
234f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
235f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 0] + src_ptr[stride + 1] +
236f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride + 2] + src_ptr[stride + 3] +
237f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 0] + src_ptr[stride * 2 + 1] +
238f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 2 + 2] + src_ptr[stride * 2 + 3] +
239f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 0] + src_ptr[stride * 3 + 1] +
240f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             src_ptr[stride * 3 + 2] + src_ptr[stride * 3 + 3] +
241f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang             8) >> 4;
242f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
243f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
244f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
245f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown34_C(const uint8* src_ptr, ptrdiff_t src_stride,
246f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                      uint8* dst, int dst_width) {
247f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
248f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
249f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; x += 3) {
250f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[0];
251f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src_ptr[1];
252f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[2] = src_ptr[3];
253f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 3;
254f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 4;
255f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
256f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
257f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
258f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown34_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
259f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         uint16* dst, int dst_width) {
260f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
261f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
262f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; x += 3) {
263f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[0];
264f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src_ptr[1];
265f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[2] = src_ptr[3];
266f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 3;
267f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 4;
268f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
269f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
270f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
271f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Filter rows 0 and 1 together, 3 : 1
272f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown34_0_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
273f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            uint8* d, int dst_width) {
274f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* s = src_ptr;
275f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* t = src_ptr + src_stride;
276f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
277f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
278f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; x += 3) {
279f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
280f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
281f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
282f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
283f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
284f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
285f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[0] = (a0 * 3 + b0 + 2) >> 2;
286f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[1] = (a1 * 3 + b1 + 2) >> 2;
287f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[2] = (a2 * 3 + b2 + 2) >> 2;
288f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d += 3;
289f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
290f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    t += 4;
291f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
292f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
293f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
294f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown34_0_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
295f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               uint16* d, int dst_width) {
296f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint16* s = src_ptr;
297f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint16* t = src_ptr + src_stride;
298f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
299f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
300f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; x += 3) {
301f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
302f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
303f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
304f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
305f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
306f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
307f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[0] = (a0 * 3 + b0 + 2) >> 2;
308f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[1] = (a1 * 3 + b1 + 2) >> 2;
309f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[2] = (a2 * 3 + b2 + 2) >> 2;
310f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d += 3;
311f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
312f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    t += 4;
313f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
314f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
315f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
316f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Filter rows 1 and 2 together, 1 : 1
317f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown34_1_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
318f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            uint8* d, int dst_width) {
319f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* s = src_ptr;
320f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint8* t = src_ptr + src_stride;
321f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
322f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
323f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; x += 3) {
324f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
325f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
326f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
327f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
328f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
329f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint8 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
330f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[0] = (a0 + b0 + 1) >> 1;
331f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[1] = (a1 + b1 + 1) >> 1;
332f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[2] = (a2 + b2 + 1) >> 1;
333f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d += 3;
334f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
335f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    t += 4;
336f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
337f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
338f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
339f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown34_1_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
340f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               uint16* d, int dst_width) {
341f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint16* s = src_ptr;
342f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint16* t = src_ptr + src_stride;
343f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
344f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
345f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; x += 3) {
346f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
347f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
348f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
349f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
350f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
351f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint16 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
352f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[0] = (a0 + b0 + 1) >> 1;
353f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[1] = (a1 + b1 + 1) >> 1;
354f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d[2] = (a2 + b2 + 1) >> 1;
355f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    d += 3;
356f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    s += 4;
357f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    t += 4;
358f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
359f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
360f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
361f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Scales a single row of pixels using point sampling.
362f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleCols_C(uint8* dst_ptr, const uint8* src_ptr,
363f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                 int dst_width, int x, int dx) {
364f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
365f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
366f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = src_ptr[x >> 16];
367f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
368f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = src_ptr[x >> 16];
369f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
370f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
371f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
372f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
373f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = src_ptr[x >> 16];
374f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
375f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
376f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
377f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleCols_16_C(uint16* dst_ptr, const uint16* src_ptr,
378f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                    int dst_width, int x, int dx) {
379f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
380f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
381f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = src_ptr[x >> 16];
382f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
383f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = src_ptr[x >> 16];
384f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
385f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
386f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
387f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
388f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = src_ptr[x >> 16];
389f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
390f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
391f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
392f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Scales a single row of pixels up by 2x using point sampling.
393f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleColsUp2_C(uint8* dst_ptr, const uint8* src_ptr,
394f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                    int dst_width, int x, int dx) {
395f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
396f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
397f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = dst_ptr[0] = src_ptr[0];
398f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 1;
399f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
400f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
401f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
402f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = src_ptr[0];
403f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
404f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
405f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
406f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleColsUp2_16_C(uint16* dst_ptr, const uint16* src_ptr,
407f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                       int dst_width, int x, int dx) {
408f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
409f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
410f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = dst_ptr[0] = src_ptr[0];
411f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 1;
412f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
413f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
414f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
415f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = src_ptr[0];
416f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
417f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
418f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
419f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// (1-f)a + fb can be replaced with a + f(b-a)
420f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(__arm__) || defined(__aarch64__)
421f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define BLENDER(a, b, f) (uint8)((int)(a) + \
422f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    ((((int)((f)) * ((int)(b) - (int)(a))) + 0x8000) >> 16))
423f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#else
424f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// inteluses 7 bit math with rounding.
425f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define BLENDER(a, b, f) (uint8)((int)(a) + \
426f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    (((int)((f) >> 9) * ((int)(b) - (int)(a)) + 0x40) >> 7))
427f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
428f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
429f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleFilterCols_C(uint8* dst_ptr, const uint8* src_ptr,
430f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                       int dst_width, int x, int dx) {
431f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
432f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
433f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xi = x >> 16;
434f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int a = src_ptr[xi];
435f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int b = src_ptr[xi + 1];
436f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
437f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
438f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    xi = x >> 16;
439f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    a = src_ptr[xi];
440f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    b = src_ptr[xi + 1];
441f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = BLENDER(a, b, x & 0xffff);
442f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
443f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
444f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
445f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
446f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xi = x >> 16;
447f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int a = src_ptr[xi];
448f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int b = src_ptr[xi + 1];
449f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
450f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
451f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
452f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
453f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleFilterCols64_C(uint8* dst_ptr, const uint8* src_ptr,
454f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         int dst_width, int x32, int dx) {
455f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int64 x = (int64)(x32);
456f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
457f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
458f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int64 xi = x >> 16;
459f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int a = src_ptr[xi];
460f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int b = src_ptr[xi + 1];
461f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
462f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
463f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    xi = x >> 16;
464f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    a = src_ptr[xi];
465f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    b = src_ptr[xi + 1];
466f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = BLENDER(a, b, x & 0xffff);
467f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
468f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
469f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
470f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
471f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int64 xi = x >> 16;
472f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int a = src_ptr[xi];
473f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int b = src_ptr[xi + 1];
474f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
475f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
476f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
477f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef BLENDER
478f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
479f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Same as 8 bit arm blender but return is cast to uint16
480f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define BLENDER(a, b, f) (uint16)((int)(a) + \
481f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    ((((int)((f)) * ((int)(b) - (int)(a))) + 0x8000) >> 16))
482f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
483f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleFilterCols_16_C(uint16* dst_ptr, const uint16* src_ptr,
484f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                       int dst_width, int x, int dx) {
485f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
486f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
487f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xi = x >> 16;
488f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int a = src_ptr[xi];
489f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int b = src_ptr[xi + 1];
490f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
491f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
492f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    xi = x >> 16;
493f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    a = src_ptr[xi];
494f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    b = src_ptr[xi + 1];
495f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = BLENDER(a, b, x & 0xffff);
496f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
497f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
498f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
499f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
500f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xi = x >> 16;
501f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int a = src_ptr[xi];
502f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int b = src_ptr[xi + 1];
503f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
504f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
505f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
506f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
507f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleFilterCols64_16_C(uint16* dst_ptr, const uint16* src_ptr,
508f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         int dst_width, int x32, int dx) {
509f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int64 x = (int64)(x32);
510f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
511f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
512f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int64 xi = x >> 16;
513f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int a = src_ptr[xi];
514f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int b = src_ptr[xi + 1];
515f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
516f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
517f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    xi = x >> 16;
518f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    a = src_ptr[xi];
519f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    b = src_ptr[xi + 1];
520f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = BLENDER(a, b, x & 0xffff);
521f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
522f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
523f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
524f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
525f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int64 xi = x >> 16;
526f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int a = src_ptr[xi];
527f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int b = src_ptr[xi + 1];
528f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = BLENDER(a, b, x & 0xffff);
529f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
530f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
531f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef BLENDER
532f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
533f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown38_C(const uint8* src_ptr, ptrdiff_t src_stride,
534f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                      uint8* dst, int dst_width) {
535f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
536f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dst_width % 3 == 0);
537f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; x += 3) {
538f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[0];
539f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src_ptr[3];
540f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[2] = src_ptr[6];
541f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 3;
542f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
543f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
544f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
545f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
546f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown38_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
547f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         uint16* dst, int dst_width) {
548f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
549f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dst_width % 3 == 0);
550f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; x += 3) {
551f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src_ptr[0];
552f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src_ptr[3];
553f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[2] = src_ptr[6];
554f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 3;
555f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
556f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
557f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
558f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
559f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// 8x3 -> 3x1
560f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown38_3_Box_C(const uint8* src_ptr,
561f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            ptrdiff_t src_stride,
562f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            uint8* dst_ptr, int dst_width) {
563f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  intptr_t stride = src_stride;
564f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int i;
565f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
566f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (i = 0; i < dst_width; i += 3) {
567f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
568f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 0] + src_ptr[stride + 1] +
569f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 2] + src_ptr[stride * 2 + 0] +
570f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2]) *
571f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        (65536 / 9) >> 16;
572f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
573f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 3] + src_ptr[stride + 4] +
574f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 5] + src_ptr[stride * 2 + 3] +
575f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5]) *
576f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        (65536 / 9) >> 16;
577f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
578f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 6] + src_ptr[stride + 7] +
579f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7]) *
580f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        (65536 / 6) >> 16;
581f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
582f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 3;
583f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
584f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
585f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
586f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown38_3_Box_16_C(const uint16* src_ptr,
587f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               ptrdiff_t src_stride,
588f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               uint16* dst_ptr, int dst_width) {
589f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  intptr_t stride = src_stride;
590f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int i;
591f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
592f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (i = 0; i < dst_width; i += 3) {
593f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
594f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 0] + src_ptr[stride + 1] +
595f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 2] + src_ptr[stride * 2 + 0] +
596f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2]) *
597f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        (65536 / 9) >> 16;
598f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
599f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 3] + src_ptr[stride + 4] +
600f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 5] + src_ptr[stride * 2 + 3] +
601f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5]) *
602f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        (65536 / 9) >> 16;
603f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
604f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 6] + src_ptr[stride + 7] +
605f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7]) *
606f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        (65536 / 6) >> 16;
607f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
608f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 3;
609f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
610f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
611f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
612f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// 8x2 -> 3x1
613f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown38_2_Box_C(const uint8* src_ptr, ptrdiff_t src_stride,
614f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            uint8* dst_ptr, int dst_width) {
615f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  intptr_t stride = src_stride;
616f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int i;
617f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
618f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (i = 0; i < dst_width; i += 3) {
619f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
620f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 0] + src_ptr[stride + 1] +
621f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 2]) * (65536 / 6) >> 16;
622f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
623f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 3] + src_ptr[stride + 4] +
624f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 5]) * (65536 / 6) >> 16;
625f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
626f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 6] + src_ptr[stride + 7]) *
627f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        (65536 / 4) >> 16;
628f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
629f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 3;
630f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
631f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
632f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
633f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleRowDown38_2_Box_16_C(const uint16* src_ptr, ptrdiff_t src_stride,
634f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               uint16* dst_ptr, int dst_width) {
635f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  intptr_t stride = src_stride;
636f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int i;
637f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert((dst_width % 3 == 0) && (dst_width > 0));
638f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (i = 0; i < dst_width; i += 3) {
639f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
640f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 0] + src_ptr[stride + 1] +
641f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 2]) * (65536 / 6) >> 16;
642f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
643f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 3] + src_ptr[stride + 4] +
644f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 5]) * (65536 / 6) >> 16;
645f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
646f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        src_ptr[stride + 6] + src_ptr[stride + 7]) *
647f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        (65536 / 4) >> 16;
648f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 8;
649f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 3;
650f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
651f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
652f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
653f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleAddRow_C(const uint8* src_ptr, uint16* dst_ptr, int src_width) {
654f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
655f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(src_width > 0);
656f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < src_width - 1; x += 2) {
657f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] += src_ptr[0];
658f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] += src_ptr[1];
659f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 2;
660f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
661f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
662f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (src_width & 1) {
663f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] += src_ptr[0];
664f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
665f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
666f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
667f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleAddRow_16_C(const uint16* src_ptr, uint32* dst_ptr, int src_width) {
668f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
669f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(src_width > 0);
670f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < src_width - 1; x += 2) {
671f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] += src_ptr[0];
672f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[1] += src_ptr[1];
673f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_ptr += 2;
674f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr += 2;
675f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
676f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (src_width & 1) {
677f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_ptr[0] += src_ptr[0];
678f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
679f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
680f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
681f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBRowDown2_C(const uint8* src_argb,
682f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         ptrdiff_t src_stride,
683f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                         uint8* dst_argb, int dst_width) {
684f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint32* src = (const uint32*)(src_argb);
685f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  uint32* dst = (uint32*)(dst_argb);
686f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
687f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
688f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
689f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[1];
690f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src[3];
691f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src += 4;
692f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
693f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
694f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
695f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[1];
696f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
697f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
698f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
699f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBRowDown2Linear_C(const uint8* src_argb,
700f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               ptrdiff_t src_stride,
701f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               uint8* dst_argb, int dst_width) {
702f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
703f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; ++x) {
704f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[0] = (src_argb[0] + src_argb[4] + 1) >> 1;
705f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[1] = (src_argb[1] + src_argb[5] + 1) >> 1;
706f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[2] = (src_argb[2] + src_argb[6] + 1) >> 1;
707f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[3] = (src_argb[3] + src_argb[7] + 1) >> 1;
708f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_argb += 8;
709f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb += 4;
710f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
711f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
712f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
713f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBRowDown2Box_C(const uint8* src_argb, ptrdiff_t src_stride,
714f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            uint8* dst_argb, int dst_width) {
715f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
716f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; ++x) {
717f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[0] = (src_argb[0] + src_argb[4] +
718f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_argb[src_stride] + src_argb[src_stride + 4] + 2) >> 2;
719f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[1] = (src_argb[1] + src_argb[5] +
720f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_argb[src_stride + 1] + src_argb[src_stride + 5] + 2) >> 2;
721f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[2] = (src_argb[2] + src_argb[6] +
722f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_argb[src_stride + 2] + src_argb[src_stride + 6] + 2) >> 2;
723f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[3] = (src_argb[3] + src_argb[7] +
724f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_argb[src_stride + 3] + src_argb[src_stride + 7] + 2) >> 2;
725f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_argb += 8;
726f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb += 4;
727f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
728f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
729f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
730f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBRowDownEven_C(const uint8* src_argb, ptrdiff_t src_stride,
731f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            int src_stepx,
732f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                            uint8* dst_argb, int dst_width) {
733f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint32* src = (const uint32*)(src_argb);
734f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  uint32* dst = (uint32*)(dst_argb);
735f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
736f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
737f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width - 1; x += 2) {
738f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[0];
739f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src[src_stepx];
740f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src += src_stepx * 2;
741f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
742f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
743f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
744f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[0];
745f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
746f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
747f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
748f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBRowDownEvenBox_C(const uint8* src_argb,
749f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               ptrdiff_t src_stride,
750f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               int src_stepx,
751f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                               uint8* dst_argb, int dst_width) {
752f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int x;
753f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (x = 0; x < dst_width; ++x) {
754f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[0] = (src_argb[0] + src_argb[4] +
755f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_argb[src_stride] + src_argb[src_stride + 4] + 2) >> 2;
756f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[1] = (src_argb[1] + src_argb[5] +
757f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_argb[src_stride + 1] + src_argb[src_stride + 5] + 2) >> 2;
758f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[2] = (src_argb[2] + src_argb[6] +
759f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_argb[src_stride + 2] + src_argb[src_stride + 6] + 2) >> 2;
760f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb[3] = (src_argb[3] + src_argb[7] +
761f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                  src_argb[src_stride + 3] + src_argb[src_stride + 7] + 2) >> 2;
762f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_argb += src_stepx * 4;
763f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb += 4;
764f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
765f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
766f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
767f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Scales a single row of pixels using point sampling.
768f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBCols_C(uint8* dst_argb, const uint8* src_argb,
769f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                     int dst_width, int x, int dx) {
770f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint32* src = (const uint32*)(src_argb);
771f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  uint32* dst = (uint32*)(dst_argb);
772f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
773f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
774f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[x >> 16];
775f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
776f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src[x >> 16];
777f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
778f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
779f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
780f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
781f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[x >> 16];
782f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
783f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
784f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
785f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBCols64_C(uint8* dst_argb, const uint8* src_argb,
786f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                       int dst_width, int x32, int dx) {
787f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int64 x = (int64)(x32);
788f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint32* src = (const uint32*)(src_argb);
789f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  uint32* dst = (uint32*)(dst_argb);
790f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
791f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
792f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[x >> 16];
793f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
794f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = src[x >> 16];
795f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
796f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
797f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
798f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
799f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[x >> 16];
800f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
801f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
802f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
803f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Scales a single row of pixels up by 2x using point sampling.
804f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBColsUp2_C(uint8* dst_argb, const uint8* src_argb,
805f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        int dst_width, int x, int dx) {
806f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint32* src = (const uint32*)(src_argb);
807f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  uint32* dst = (uint32*)(dst_argb);
808f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
809f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
810f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = dst[0] = src[0];
811f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src += 1;
812f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
813f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
814f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
815f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = src[0];
816f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
817f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
818f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
819f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// TODO(fbarchard): Replace 0x7f ^ f with 128-f.  bug=607.
820f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Mimics SSSE3 blender
821f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define BLENDER1(a, b, f) ((a) * (0x7f ^ f) + (b) * f) >> 7
822f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define BLENDERC(a, b, f, s) (uint32)( \
823f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    BLENDER1(((a) >> s) & 255, ((b) >> s) & 255, f) << s)
824f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define BLENDER(a, b, f) \
825f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    BLENDERC(a, b, f, 24) | BLENDERC(a, b, f, 16) | \
826f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    BLENDERC(a, b, f, 8) | BLENDERC(a, b, f, 0)
827f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
828f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBFilterCols_C(uint8* dst_argb, const uint8* src_argb,
829f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           int dst_width, int x, int dx) {
830f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint32* src = (const uint32*)(src_argb);
831f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  uint32* dst = (uint32*)(dst_argb);
832f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
833f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
834f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xi = x >> 16;
835f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xf = (x >> 9) & 0x7f;
836f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint32 a = src[xi];
837f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint32 b = src[xi + 1];
838f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = BLENDER(a, b, xf);
839f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
840f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    xi = x >> 16;
841f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    xf = (x >> 9) & 0x7f;
842f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    a = src[xi];
843f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    b = src[xi + 1];
844f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = BLENDER(a, b, xf);
845f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
846f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
847f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
848f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
849f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xi = x >> 16;
850f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xf = (x >> 9) & 0x7f;
851f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint32 a = src[xi];
852f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint32 b = src[xi + 1];
853f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = BLENDER(a, b, xf);
854f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
855f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
856f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
857f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleARGBFilterCols64_C(uint8* dst_argb, const uint8* src_argb,
858f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                             int dst_width, int x32, int dx) {
859f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int64 x = (int64)(x32);
860f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const uint32* src = (const uint32*)(src_argb);
861f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  uint32* dst = (uint32*)(dst_argb);
862f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
863f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_width - 1; j += 2) {
864f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int64 xi = x >> 16;
865f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xf = (x >> 9) & 0x7f;
866f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint32 a = src[xi];
867f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint32 b = src[xi + 1];
868f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = BLENDER(a, b, xf);
869f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
870f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    xi = x >> 16;
871f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    xf = (x >> 9) & 0x7f;
872f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    a = src[xi];
873f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    b = src[xi + 1];
874f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[1] = BLENDER(a, b, xf);
875f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    x += dx;
876f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst += 2;
877f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
878f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width & 1) {
879f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int64 xi = x >> 16;
880f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int xf = (x >> 9) & 0x7f;
881f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint32 a = src[xi];
882f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    uint32 b = src[xi + 1];
883f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst[0] = BLENDER(a, b, xf);
884f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
885f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
886f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef BLENDER1
887f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef BLENDERC
888f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef BLENDER
889f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
890f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Scale plane vertically with bilinear interpolation.
891f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScalePlaneVertical(int src_height,
892f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        int dst_width, int dst_height,
893f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        int src_stride, int dst_stride,
894f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        const uint8* src_argb, uint8* dst_argb,
895f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        int x, int y, int dy,
896f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                        int bpp, enum FilterMode filtering) {
897f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // TODO(fbarchard): Allow higher bpp.
898f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int dst_width_bytes = dst_width * bpp;
899f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
900f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
901f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow_C;
902f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
903f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
904f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(bpp >= 1 && bpp <= 4);
905f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(src_height != 0);
906f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dst_width > 0);
907f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dst_height > 0);
908f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  src_argb += (x >> 16) * bpp;
909f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_SSSE3)
910f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasSSSE3)) {
911f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_SSSE3;
912f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 16)) {
913f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_SSSE3;
914f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
915f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
916f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
917f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_AVX2)
918f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasAVX2)) {
919f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_AVX2;
920f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 32)) {
921f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_AVX2;
922f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
923f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
924f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
925f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_NEON)
926f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasNEON)) {
927f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_NEON;
928f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 16)) {
929f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_NEON;
930f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
931f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
932f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
933f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_DSPR2)
934f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasDSPR2) &&
935f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) &&
936f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) {
937f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_DSPR2;
938f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 4)) {
939f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_DSPR2;
940f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
941f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
942f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
943f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_height; ++j) {
944f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int yi;
945f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int yf;
946f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (y > max_y) {
947f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      y = max_y;
948f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
949f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    yi = y >> 16;
950f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    yf = filtering ? ((y >> 8) & 255) : 0;
951f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow(dst_argb, src_argb + yi * src_stride,
952f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                   src_stride, dst_width_bytes, yf);
953f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb += dst_stride;
954f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    y += dy;
955f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
956f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
957f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScalePlaneVertical_16(int src_height,
958f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           int dst_width, int dst_height,
959f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           int src_stride, int dst_stride,
960f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           const uint16* src_argb, uint16* dst_argb,
961f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           int x, int y, int dy,
962f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                           int wpp, enum FilterMode filtering) {
963f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // TODO(fbarchard): Allow higher wpp.
964f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int dst_width_words = dst_width * wpp;
965f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  void (*InterpolateRow)(uint16* dst_argb, const uint16* src_argb,
966f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
967f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow_16_C;
968f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
969f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int j;
970f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(wpp >= 1 && wpp <= 2);
971f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(src_height != 0);
972f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dst_width > 0);
973f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dst_height > 0);
974f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  src_argb += (x >> 16) * wpp;
975f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_16_SSE2)
976f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasSSE2)) {
977f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_16_SSE2;
978f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 16)) {
979f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_16_SSE2;
980f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
981f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
982f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
983f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_16_SSSE3)
984f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasSSSE3)) {
985f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_16_SSSE3;
986f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 16)) {
987f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_16_SSSE3;
988f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
989f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
990f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
991f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_16_AVX2)
992f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasAVX2)) {
993f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_16_AVX2;
994f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 32)) {
995f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_16_AVX2;
996f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
997f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
998f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
999f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_16_NEON)
1000f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasNEON)) {
1001f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_16_NEON;
1002f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 16)) {
1003f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_16_NEON;
1004f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1005f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1006f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
1007f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#if defined(HAS_INTERPOLATEROW_16_DSPR2)
1008f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (TestCpuFlag(kCpuHasDSPR2) &&
1009f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) &&
1010f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) {
1011f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow = InterpolateRow_Any_16_DSPR2;
1012f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (IS_ALIGNED(dst_width_bytes, 4)) {
1013f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      InterpolateRow = InterpolateRow_16_DSPR2;
1014f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1015f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1016f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
1017f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (j = 0; j < dst_height; ++j) {
1018f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int yi;
1019f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    int yf;
1020f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (y > max_y) {
1021f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      y = max_y;
1022f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1023f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    yi = y >> 16;
1024f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    yf = filtering ? ((y >> 8) & 255) : 0;
1025f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    InterpolateRow(dst_argb, src_argb + yi * src_stride,
1026f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                   src_stride, dst_width_words, yf);
1027f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_argb += dst_stride;
1028f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    y += dy;
1029f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1030f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
1031f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
1032f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Simplify the filtering based on scale factors.
1033f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangenum FilterMode ScaleFilterReduce(int src_width, int src_height,
1034f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                                  int dst_width, int dst_height,
1035f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                                  enum FilterMode filtering) {
1036f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (src_width < 0) {
1037f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_width = -src_width;
1038f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1039f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (src_height < 0) {
1040f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    src_height = -src_height;
1041f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1042f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (filtering == kFilterBox) {
1043f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // If scaling both axis to 0.5 or larger, switch from Box to Bilinear.
1044f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (dst_width * 2 >= src_width && dst_height * 2 >= src_height) {
1045f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      filtering = kFilterBilinear;
1046f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1047f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1048f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (filtering == kFilterBilinear) {
1049f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (src_height == 1) {
1050f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      filtering = kFilterLinear;
1051f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1052f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // TODO(fbarchard): Detect any odd scale factor and reduce to Linear.
1053f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (dst_height == src_height || dst_height * 3 == src_height) {
1054f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      filtering = kFilterLinear;
1055f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1056f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // TODO(fbarchard): Remove 1 pixel wide filter restriction, which is to
1057f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // avoid reading 2 pixels horizontally that causes memory exception.
1058f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (src_width == 1) {
1059f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      filtering = kFilterNone;
1060f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1061f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1062f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (filtering == kFilterLinear) {
1063f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (src_width == 1) {
1064f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      filtering = kFilterNone;
1065f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1066f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // TODO(fbarchard): Detect any odd scale factor and reduce to None.
1067f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (dst_width == src_width || dst_width * 3 == src_width) {
1068f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      filtering = kFilterNone;
1069f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1070f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1071f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  return filtering;
1072f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
1073f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
1074f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Divide num by div and return as 16.16 fixed point result.
1075f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangint FixedDiv_C(int num, int div) {
1076f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  return (int)(((int64)(num) << 16) / div);
1077f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
1078f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
1079f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Divide num by div and return as 16.16 fixed point result.
1080f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangint FixedDiv1_C(int num, int div) {
1081f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  return (int)((((int64)(num) << 16) - 0x00010001) /
1082f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                          (div - 1));
1083f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
1084f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
1085f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s)
1086f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
1087f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang// Compute slope values for stepping.
1088f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangvoid ScaleSlope(int src_width, int src_height,
1089f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                int dst_width, int dst_height,
1090f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                enum FilterMode filtering,
1091f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang                int* x, int* y, int* dx, int* dy) {
1092f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(x != NULL);
1093f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(y != NULL);
1094f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dx != NULL);
1095f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dy != NULL);
1096f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(src_width != 0);
1097f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(src_height != 0);
1098f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dst_width > 0);
1099f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  assert(dst_height > 0);
1100f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // Check for 1 pixel and avoid FixedDiv overflow.
1101f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_width == 1 && src_width >= 32768) {
1102f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_width = src_width;
1103f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1104f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (dst_height == 1 && src_height >= 32768) {
1105f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    dst_height = src_height;
1106f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1107f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (filtering == kFilterBox) {
1108f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // Scale step for point sampling duplicates all pixels equally.
1109f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *dx = FixedDiv(Abs(src_width), dst_width);
1110f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *dy = FixedDiv(src_height, dst_height);
1111f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *x = 0;
1112f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *y = 0;
1113f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  } else if (filtering == kFilterBilinear) {
1114f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // Scale step for bilinear sampling renders last pixel once for upsample.
1115f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (dst_width <= Abs(src_width)) {
1116f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *dx = FixedDiv(Abs(src_width), dst_width);
1117f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *x = CENTERSTART(*dx, -32768);  // Subtract 0.5 (32768) to center filter.
1118f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    } else if (dst_width > 1) {
1119f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *dx = FixedDiv1(Abs(src_width), dst_width);
1120f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *x = 0;
1121f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1122f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (dst_height <= src_height) {
1123f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *dy = FixedDiv(src_height,  dst_height);
1124f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *y = CENTERSTART(*dy, -32768);  // Subtract 0.5 (32768) to center filter.
1125f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    } else if (dst_height > 1) {
1126f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *dy = FixedDiv1(src_height, dst_height);
1127f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *y = 0;
1128f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1129f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  } else if (filtering == kFilterLinear) {
1130f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // Scale step for bilinear sampling renders last pixel once for upsample.
1131f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (dst_width <= Abs(src_width)) {
1132f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *dx = FixedDiv(Abs(src_width), dst_width);
1133f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *x = CENTERSTART(*dx, -32768);  // Subtract 0.5 (32768) to center filter.
1134f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    } else if (dst_width > 1) {
1135f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *dx = FixedDiv1(Abs(src_width), dst_width);
1136f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      *x = 0;
1137f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
1138f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *dy = FixedDiv(src_height, dst_height);
1139f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *y = *dy >> 1;
1140f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  } else {
1141f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // Scale step for point sampling duplicates all pixels equally.
1142f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *dx = FixedDiv(Abs(src_width), dst_width);
1143f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *dy = FixedDiv(src_height, dst_height);
1144f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *x = CENTERSTART(*dx, 0);
1145f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *y = CENTERSTART(*dy, 0);
1146f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1147f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // Negative src_width means horizontally mirror.
1148f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  if (src_width < 0) {
1149f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *x += (dst_width - 1) * *dx;
1150f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    *dx = -*dx;
1151f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    // src_width = -src_width;   // Caller must do this.
1152f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
1153f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
1154f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#undef CENTERSTART
1155f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
1156f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#ifdef __cplusplus
1157f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}  // extern "C"
1158f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}  // namespace libyuv
1159f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#endif
1160