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/6void 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/6void 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/6void 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/6void 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/6void 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 |