GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 31.9% 90 / 0 / 282
Functions: 58.3% 7 / 0 / 12
Branches: 24.7% 74 / 0 / 300

filters/resize.cpp
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
2 // http://avisynth.nl
3
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 // http://www.gnu.org/copyleft/gpl.html .
18 //
19 // Linking Avisynth statically or dynamically with other modules is making a
20 // combined work based on Avisynth. Thus, the terms and conditions of the GNU
21 // General Public License cover the whole combination.
22 //
23 // As a special exception, the copyright holders of Avisynth give you
24 // permission to link Avisynth with independent modules that communicate with
25 // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
26 // terms of these independent modules, and to copy and distribute the
27 // resulting combined work under terms of your choice, provided that
28 // every copy of the combined work is accompanied by a complete copy of
29 // the source code of Avisynth (the version of Avisynth used to produce the
30 // combined work), being distributed under the terms of the GNU General
31 // Public License plus this exception. An independent module is a module
32 // which is not derived from or based on Avisynth, such as 3rd-party filters,
33 // import and export plugins, or graphical user interfaces.
34
35
36 #include "resize.h"
37 #ifdef INTEL_INTRINSICS
38 #include "intel/resize_sse.h"
39 #endif
40 #include "../core/internal.h"
41 #include <avs/alignment.h>
42 #include <stdint.h>
43 #include <type_traits>
44
45
46 /********************************************************************
47 ***** Declare index of new filters for Avisynth's filter engine *****
48 ********************************************************************/
49
50 extern const AVSFunction Resize_filters[] = {
51 { "VerticalReduceBy2", BUILTIN_FUNC_PREFIX, "c", VerticalReduceBy2::Create }, // src clip
52 { "HorizontalReduceBy2", BUILTIN_FUNC_PREFIX, "c", HorizontalReduceBy2::Create }, // src clip
53 { "ReduceBy2", BUILTIN_FUNC_PREFIX, "c", Create_ReduceBy2 }, // src clip
54 { 0 }
55 };
56
57 template<typename pixel_t>
58 3 static void vertical_reduce_c(BYTE* _dstp, const BYTE* _srcp, int _dst_pitch, int _src_pitch, size_t row_size, size_t height) {
59 3 size_t width = row_size / sizeof(pixel_t);
60 3 int dst_pitch = _dst_pitch / sizeof(pixel_t);
61 3 int src_pitch = _src_pitch / sizeof(pixel_t);
62 3 const pixel_t* srcp = reinterpret_cast<const pixel_t*>(_srcp);
63 3 pixel_t* dstp = reinterpret_cast<pixel_t*>(_dstp);
64
65 3 const pixel_t* srcp_next = srcp + src_pitch;
66 3 const pixel_t* srcp_next2 = srcp + src_pitch * 2;
67
68 pixel_t rounding;
69 if (!std::is_floating_point<pixel_t>::value)
70 3 rounding = 2;
71 else
72 rounding = 0; // float: no rounding
73
74
2/6
void vertical_reduce_c<float>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✗ Branch 8 → 4 not taken.
✗ Branch 8 → 9 not taken.
void vertical_reduce_c<unsigned char>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✓ Branch 9 → 5 taken 6 times.
✓ Branch 9 → 10 taken 3 times.
void vertical_reduce_c<unsigned short>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✗ Branch 9 → 5 not taken.
✗ Branch 9 → 10 not taken.
9 for (size_t y = 0; y < height - 1; ++y) {
75
2/6
void vertical_reduce_c<float>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✗ Branch 6 → 5 not taken.
✗ Branch 6 → 7 not taken.
void vertical_reduce_c<unsigned char>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✓ Branch 7 → 6 taken 42 times.
✓ Branch 7 → 8 taken 6 times.
void vertical_reduce_c<unsigned short>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✗ Branch 7 → 6 not taken.
✗ Branch 7 → 8 not taken.
48 for (size_t x = 0; x < width; ++x) {
76 42 dstp[x] = (srcp[x] + 2 * srcp_next[x] + srcp_next2[x] + rounding) / 4; // >> 2; /4 float friendly
77 }
78 6 dstp += dst_pitch;
79 6 srcp += src_pitch * 2;
80 6 srcp_next += src_pitch * 2;
81 6 srcp_next2 += src_pitch * 2;
82 }
83
2/6
void vertical_reduce_c<float>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✗ Branch 11 → 10 not taken.
✗ Branch 11 → 12 not taken.
void vertical_reduce_c<unsigned char>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✓ Branch 12 → 11 taken 21 times.
✓ Branch 12 → 13 taken 3 times.
void vertical_reduce_c<unsigned short>(unsigned char*, unsigned char const*, int, int, unsigned long, unsigned long):
✗ Branch 12 → 11 not taken.
✗ Branch 12 → 13 not taken.
24 for (size_t x = 0; x < width; ++x) {
84 21 dstp[x] = (srcp[x] + 3 * srcp_next[x] + rounding) / 4; // >> 2; /4 float friendly
85 }
86 3 }
87
88 3 void vertical_reduce_core(BYTE* dstp, const BYTE* srcp, int dst_pitch, int src_pitch, int row_size, int height, int pixelsize, IScriptEnvironment* env) {
89
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3 times.
3 if (!srcp) {
90 return;
91 }
92 #ifdef INTEL_INTRINSICS
93
5/10
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 11 not taken.
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 11 not taken.
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 11 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 3 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 3 times.
3 if (pixelsize == 1 && (env->GetCPUFlags() & CPUF_SSE2) && IsPtrAligned(srcp, 16) && row_size >= 16) {
94 vertical_reduce_sse2(dstp, srcp, dst_pitch, src_pitch, row_size, height);
95 }
96 else
97 #ifdef X86_32
98 if (pixelsize == 1 && (env->GetCPUFlags() & CPUF_MMX) && row_size >= 8) {
99 vertical_reduce_mmx(dstp, srcp, dst_pitch, src_pitch, row_size, height);
100 }
101 else
102 #endif
103 #endif
104
1/3
✓ Branch 14 → 15 taken 3 times.
✗ Branch 14 → 16 not taken.
✗ Branch 14 → 17 not taken.
3 switch (pixelsize) {
105 3 case 1: vertical_reduce_c<uint8_t>(dstp, srcp, dst_pitch, src_pitch, row_size, height); break;
106 case 2: vertical_reduce_c<uint16_t>(dstp, srcp, dst_pitch, src_pitch, row_size, height); break;
107 default: //case 4:
108 vertical_reduce_c<float>(dstp, srcp, dst_pitch, src_pitch, row_size, height); break;
109 }
110
111 }
112
113
114 /*************************************
115 ******* Vertical 2:1 Reduction ******
116 ************************************/
117
118
119 1 VerticalReduceBy2::VerticalReduceBy2(PClip _child, IScriptEnvironment* env)
120
2/4
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 26 not taken.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 24 not taken.
1 : GenericVideoFilter(_child)
121 {
122
7/18
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 27 not taken.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 14 not taken.
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 27 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 11 taken 1 time.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 27 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 27 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 14 not taken.
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 19 not taken.
1 if (vi.IsPlanar() && (vi.IsYUV() || vi.IsYUVA()) && (vi.NumComponents() > 1)) {
123
1/2
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 27 not taken.
1 const int mod = 2 << vi.GetPlaneHeightSubsampling(PLANAR_U);
124 1 const int mask = mod - 1;
125
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 1 time.
1 if (vi.height & mask)
126 env->ThrowError("VerticalReduceBy2: Planar source height must be divisible by %d.", mod);
127 }
128
129
1/2
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 1 time.
1 if (vi.height & 1)
130 env->ThrowError("VerticalReduceBy2: Image height must be even");
131
132 1 original_height = vi.height;
133 1 vi.height >>= 1;
134
135
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 1 time.
1 if (vi.height < 3) {
136 env->ThrowError("VerticalReduceBy2: Image too small to be reduced by 2.");
137 }
138 1 }
139
140
141 1 PVideoFrame VerticalReduceBy2::GetFrame(int n, IScriptEnvironment* env) {
142
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 51 not taken.
1 PVideoFrame src = child->GetFrame(n, env);
143
1/2
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 49 not taken.
1 PVideoFrame dst = env->NewVideoFrameP(vi, &src);
144
1/2
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 47 not taken.
1 int pixelsize = vi.ComponentSize();
145
146
2/4
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 47 not taken.
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 32 not taken.
1 if (vi.IsPlanar()) {
147 1 int planesYUV[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A };
148 1 int planesRGB[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A };
149
2/8
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 46 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 1 time.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 46 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 13 not taken.
1 int* planes = vi.IsYUV() || vi.IsYUVA() ? planesYUV : planesRGB;
150
3/4
✓ Branch 29 → 30 taken 4 times.
✗ Branch 29 → 46 not taken.
✓ Branch 30 → 15 taken 3 times.
✓ Branch 30 → 31 taken 1 time.
4 for (int p = 0; p < vi.NumComponents(); p++)
151 {
152 3 int plane = planes[p];
153
7/14
✓ Branch 16 → 17 taken 3 times.
✗ Branch 16 → 46 not taken.
✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 46 not taken.
✓ Branch 20 → 21 taken 3 times.
✗ Branch 20 → 46 not taken.
✓ Branch 22 → 23 taken 3 times.
✗ Branch 22 → 46 not taken.
✓ Branch 24 → 25 taken 3 times.
✗ Branch 24 → 46 not taken.
✓ Branch 26 → 27 taken 3 times.
✗ Branch 26 → 46 not taken.
✓ Branch 27 → 28 taken 3 times.
✗ Branch 27 → 46 not taken.
3 vertical_reduce_core(dst->GetWritePtr(plane), src->GetReadPtr(plane), dst->GetPitch(plane), src->GetPitch(plane), dst->GetRowSize(plane), dst->GetHeight(plane), pixelsize, env);
154 }
155 }
156 else {
157 int src_pitch = src->GetPitch();
158 int dst_pitch = dst->GetPitch();
159 int row_size = src->GetRowSize();
160 BYTE* dstp = dst->GetWritePtr();
161 const BYTE* srcp = src->GetReadPtr();
162 vertical_reduce_core(dstp, srcp, dst_pitch, src_pitch, row_size, vi.height, pixelsize, env);
163 }
164 1 return dst;
165 1 }
166
167
168 /************************************
169 **** Horizontal 2:1 Reduction ******
170 ***********************************/
171
172 1 HorizontalReduceBy2::HorizontalReduceBy2(PClip _child, IScriptEnvironment* env)
173
2/4
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 32 not taken.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 30 not taken.
1 : GenericVideoFilter(_child)
174 {
175
7/18
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 33 not taken.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 14 not taken.
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 33 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 11 taken 1 time.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 33 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 33 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 14 not taken.
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 19 not taken.
1 if (vi.IsPlanar() && (vi.IsYUV() || vi.IsYUVA()) && (vi.NumComponents() > 1)) {
176
1/2
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 33 not taken.
1 const int mod = 2 << vi.GetPlaneWidthSubsampling(PLANAR_U);
177 1 const int mask = mod - 1;
178
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 1 time.
1 if (vi.width & mask)
179 env->ThrowError("HorizontalReduceBy2: Planar source width must be divisible by %d.", mod);
180 }
181
182
1/2
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 1 time.
1 if (vi.width & 1)
183 env->ThrowError("HorizontalReduceBy2: Image width must be even");
184
185
3/8
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 33 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 25 taken 1 time.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 1 time.
1 if (vi.IsYUY2() && (vi.width & 3))
186 env->ThrowError("HorizontalReduceBy2: YUY2 output image width must be even");
187
188
1/2
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 33 not taken.
1 pixelsize = vi.ComponentSize();
189 1 source_width = vi.width;
190 1 vi.width >>= 1;
191 1 }
192
193 template<typename pixel_t>
194 3 static void horizontal_reduce_core(PVideoFrame& dst, PVideoFrame& src, int plane) {
195
196 pixel_t rounding;
197 if (!std::is_floating_point<pixel_t>::value)
198 3 rounding = 1;
199 else
200 rounding = 0; // float: no rounding
201
202 3 const pixel_t* srcp = reinterpret_cast<const pixel_t*>(src->GetReadPtr(plane));
203 3 pixel_t* dstp = reinterpret_cast<pixel_t*>(dst->GetWritePtr(plane));
204 3 int src_gap = (src->GetPitch(plane) - src->GetRowSize(plane)) / sizeof(pixel_t); //aka 'modulo' in VDub filter terminology
205 3 int dst_gap = (dst->GetPitch(plane) - dst->GetRowSize(plane)) / sizeof(pixel_t);
206 3 int yloops = dst->GetHeight(plane);
207 3 int xloops = dst->GetRowSize(plane) / sizeof(pixel_t) - 1;
208
2/6
void horizontal_reduce_core<float>(PVideoFrame&, PVideoFrame&, int):
✗ Branch 24 → 20 not taken.
✗ Branch 24 → 25 not taken.
void horizontal_reduce_core<unsigned char>(PVideoFrame&, PVideoFrame&, int):
✓ Branch 25 → 21 taken 9 times.
✓ Branch 25 → 26 taken 3 times.
void horizontal_reduce_core<unsigned short>(PVideoFrame&, PVideoFrame&, int):
✗ Branch 25 → 21 not taken.
✗ Branch 25 → 26 not taken.
12 for (int y = 0; y < yloops; y++) {
209
2/6
void horizontal_reduce_core<float>(PVideoFrame&, PVideoFrame&, int):
✗ Branch 22 → 21 not taken.
✗ Branch 22 → 23 not taken.
void horizontal_reduce_core<unsigned char>(PVideoFrame&, PVideoFrame&, int):
✓ Branch 23 → 22 taken 27 times.
✓ Branch 23 → 24 taken 9 times.
void horizontal_reduce_core<unsigned short>(PVideoFrame&, PVideoFrame&, int):
✗ Branch 23 → 22 not taken.
✗ Branch 23 → 24 not taken.
36 for (int x = 0; x < xloops; x++) {
210 27 *dstp = (srcp[0] + 2 * srcp[1] + srcp[2] + rounding * 2) / 4; // >> 2; float-friendly
211 27 dstp++;
212 27 srcp += 2;
213 }
214 9 *dstp = (srcp[0] + srcp[1] + rounding) / 2; // >> 1; float-friendly
215 9 dstp += dst_gap + 1;
216 9 srcp += src_gap + 2;
217 }
218 3 }
219
220 1 PVideoFrame HorizontalReduceBy2::GetFrame(int n, IScriptEnvironment* env)
221 {
222
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 114 not taken.
1 PVideoFrame src = child->GetFrame(n, env);
223
1/2
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 112 not taken.
1 PVideoFrame dst = env->NewVideoFrameP(vi, &src);
224
2/4
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 110 not taken.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 25 not taken.
1 if (vi.IsPlanar()) {
225
226 1 int planesYUV[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A };
227 1 int planesRGB[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A };
228
2/8
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 109 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 11 taken 1 time.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 109 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
1 int* planes = vi.IsYUV() || vi.IsYUVA() ? planesYUV : planesRGB;
229
3/4
✓ Branch 22 → 23 taken 4 times.
✗ Branch 22 → 109 not taken.
✓ Branch 23 → 14 taken 3 times.
✓ Branch 23 → 24 taken 1 time.
4 for (int p = 0; p < vi.NumComponents(); p++)
230 {
231 3 int plane = planes[p];
232
1/3
✓ Branch 14 → 15 taken 3 times.
✗ Branch 14 → 17 not taken.
✗ Branch 14 → 19 not taken.
3 switch (pixelsize) {
233
1/2
✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 109 not taken.
3 case 1: horizontal_reduce_core<uint8_t>(dst, src, plane); break;
234 case 2: horizontal_reduce_core<uint16_t>(dst, src, plane); break;
235 default: // case 4:
236 horizontal_reduce_core<float>(dst, src, plane); break;
237 }
238 }
239 1 return dst;
240 }
241
242 int src_gap = src->GetPitch() - src->GetRowSize(); //aka 'modulo' in VDub filter terminology
243 int dst_gap = dst->GetPitch() - dst->GetRowSize();
244
245 BYTE* dstp = dst->GetWritePtr();
246
247 if (vi.IsYUY2() && (!(vi.width & 1))) {
248
249 const BYTE* srcp = src->GetReadPtr();
250 for (int y = vi.height; y > 0; --y) {
251 for (int x = (vi.width >> 1) - 1; x; --x) {
252 dstp[0] = (srcp[0] + 2 * srcp[2] + srcp[4] + 2) >> 2;
253 dstp[1] = (srcp[1] + 2 * srcp[5] + srcp[9] + 2) >> 2;
254 dstp[2] = (srcp[4] + 2 * srcp[6] + srcp[8] + 2) >> 2;
255 dstp[3] = (srcp[3] + 2 * srcp[7] + srcp[11] + 2) >> 2;
256 dstp += 4;
257 srcp += 8;
258 }
259 dstp[0] = (srcp[0] + 2 * srcp[2] + srcp[4] + 2) >> 2;
260 dstp[1] = (srcp[1] + srcp[5] + 1) >> 1;
261 dstp[2] = (srcp[4] + srcp[6] + 1) >> 1;
262 dstp[3] = (srcp[3] + srcp[7] + 1) >> 1;
263 dstp += dst_gap + 4;
264 srcp += src_gap + 8;
265
266 }
267 }
268 else if (vi.IsRGB24() || vi.IsRGB48()) {
269 const BYTE* srcp = src->GetReadPtr();
270 if (pixelsize == 1) {
271 for (int y = vi.height; y > 0; --y) {
272 for (int x = (source_width - 1) >> 1; x; --x) {
273 dstp[0] = (srcp[0] + 2 * srcp[3] + srcp[6] + 2) >> 2;
274 dstp[1] = (srcp[1] + 2 * srcp[4] + srcp[7] + 2) >> 2;
275 dstp[2] = (srcp[2] + 2 * srcp[5] + srcp[8] + 2) >> 2;
276 dstp += 3;
277 srcp += 6;
278 }
279 if (source_width & 1) {
280 dstp += dst_gap;
281 srcp += src_gap + 3;
282 }
283 else {
284 dstp[0] = (srcp[0] + srcp[3] + 1) >> 1;
285 dstp[1] = (srcp[1] + srcp[4] + 1) >> 1;
286 dstp[2] = (srcp[2] + srcp[5] + 1) >> 1;
287 dstp += dst_gap + 3;
288 srcp += src_gap + 6;
289 }
290 }
291 }
292 else { // pixelsize==2 RGB48
293 uint16_t* dstp16 = reinterpret_cast<uint16_t*>(dstp);
294 const uint16_t* srcp16 = reinterpret_cast<const uint16_t*>(srcp);
295 dst_gap /= sizeof(uint16_t);
296 src_gap /= sizeof(uint16_t);
297 for (int y = vi.height; y > 0; --y) {
298 for (int x = (source_width - 1) >> 1; x; --x) {
299 dstp16[0] = (srcp16[0] + 2 * srcp16[3] + srcp16[6] + 2) >> 2;
300 dstp16[1] = (srcp16[1] + 2 * srcp16[4] + srcp16[7] + 2) >> 2;
301 dstp16[2] = (srcp16[2] + 2 * srcp16[5] + srcp16[8] + 2) >> 2;
302 dstp16 += 3;
303 srcp16 += 6;
304 }
305 if (source_width & 1) {
306 dstp16 += dst_gap;
307 srcp16 += src_gap + 3;
308 }
309 else {
310 dstp16[0] = (srcp16[0] + srcp16[3] + 1) >> 1;
311 dstp16[1] = (srcp16[1] + srcp16[4] + 1) >> 1;
312 dstp16[2] = (srcp16[2] + srcp16[5] + 1) >> 1;
313 dstp16 += dst_gap + 3;
314 srcp16 += src_gap + 6;
315 }
316 }
317 }
318 }
319 else if (vi.IsRGB32() || vi.IsRGB64()) { //rgb32
320 const BYTE* srcp = src->GetReadPtr();
321 if (pixelsize == 1) {
322 for (int y = vi.height; y > 0; --y) {
323 for (int x = (source_width - 1) >> 1; x; --x) {
324 dstp[0] = (srcp[0] + 2 * srcp[4] + srcp[8] + 2) >> 2;
325 dstp[1] = (srcp[1] + 2 * srcp[5] + srcp[9] + 2) >> 2;
326 dstp[2] = (srcp[2] + 2 * srcp[6] + srcp[10] + 2) >> 2;
327 dstp[3] = (srcp[3] + 2 * srcp[7] + srcp[11] + 2) >> 2;
328 dstp += 4;
329 srcp += 8;
330 }
331 if (source_width & 1) {
332 dstp += dst_gap;
333 srcp += src_gap + 4;
334 }
335 else {
336 dstp[0] = (srcp[0] + srcp[4] + 1) >> 1;
337 dstp[1] = (srcp[1] + srcp[5] + 1) >> 1;
338 dstp[2] = (srcp[2] + srcp[6] + 1) >> 1;
339 dstp[3] = (srcp[3] + srcp[7] + 1) >> 1;
340 dstp += dst_gap + 4;
341 srcp += src_gap + 8;
342 }
343 }
344 }
345 else { // pixelsize==2 rgb64
346 uint16_t* dstp16 = reinterpret_cast<uint16_t*>(dstp);
347 const uint16_t* srcp16 = reinterpret_cast<const uint16_t*>(srcp);
348 dst_gap /= sizeof(uint16_t);
349 src_gap /= sizeof(uint16_t);
350 for (int y = vi.height; y > 0; --y) {
351 for (int x = (source_width - 1) >> 1; x; --x) {
352 dstp16[0] = (srcp16[0] + 2 * srcp16[4] + srcp16[8] + 2) >> 2;
353 dstp16[1] = (srcp16[1] + 2 * srcp16[5] + srcp16[9] + 2) >> 2;
354 dstp16[2] = (srcp16[2] + 2 * srcp16[6] + srcp16[10] + 2) >> 2;
355 dstp16[3] = (srcp16[3] + 2 * srcp16[7] + srcp16[11] + 2) >> 2;
356 dstp16 += 4;
357 srcp16 += 8;
358 }
359 if (source_width & 1) {
360 dstp16 += dst_gap;
361 srcp16 += src_gap + 4;
362 }
363 else {
364 dstp16[0] = (srcp16[0] + srcp16[4] + 1) >> 1;
365 dstp16[1] = (srcp16[1] + srcp16[5] + 1) >> 1;
366 dstp16[2] = (srcp16[2] + srcp16[6] + 1) >> 1;
367 dstp16[3] = (srcp16[3] + srcp16[7] + 1) >> 1;
368 dstp16 += dst_gap + 4;
369 srcp16 += src_gap + 8;
370 }
371 }
372 }
373 }
374 return dst;
375 1 }
376
377 /**************************************
378 ***** ReduceBy2 Factory Method *****
379 *************************************/
380
381
382 AVSValue __cdecl Create_ReduceBy2(AVSValue args, void*, IScriptEnvironment* env)
383 {
384 return new HorizontalReduceBy2(new VerticalReduceBy2(args[0].AsClip(), env), env);
385 }
386
387
388
389