filters/histogram.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 | // FIXME: in general: how to display 32 bit floats? | ||
| 36 | // Do we have to assume it as if it is used after a limited -> full scale conversion? (preferred - everywhere!) | ||
| 37 | // Or with values simply: pixel_8bit / 255.0? | ||
| 38 | // Latter logic converts U=240 to (240-128)/255 instead of (240-128)/226 (=0.5) | ||
| 39 | // and Y=235 to 235/255 instead of (235-16)/219 (=1.0) | ||
| 40 | |||
| 41 | #include "histogram.h" | ||
| 42 | #include "../core/info.h" | ||
| 43 | #include "../core/internal.h" | ||
| 44 | #include "../convert/convert_planar.h" | ||
| 45 | #include "../convert/convert_audio.h" | ||
| 46 | #include "../convert/convert_helper.h" | ||
| 47 | #include "../convert/convert_matrix.h" | ||
| 48 | #include "colorbars_const.h" | ||
| 49 | |||
| 50 | #ifdef AVS_WINDOWS | ||
| 51 | #include <avs/win.h> | ||
| 52 | #else | ||
| 53 | #include <avs/posix.h> | ||
| 54 | #endif | ||
| 55 | |||
| 56 | #include <memory> | ||
| 57 | #include <avs/minmax.h> | ||
| 58 | #include <cstdio> | ||
| 59 | #include <cmath> | ||
| 60 | #include <stdint.h> | ||
| 61 | #include <vector> | ||
| 62 | |||
| 63 | |||
| 64 | constexpr double PI = 3.14159265358979323846; | ||
| 65 | // until c++20 <numbers> std::numbers::pi | ||
| 66 | |||
| 67 | /******************************************************************** | ||
| 68 | ***** Declare index of new filters for Avisynth's filter engine ***** | ||
| 69 | ********************************************************************/ | ||
| 70 | extern const AVSFunction Histogram_filters[] = { | ||
| 71 | { "Histogram", BUILTIN_FUNC_PREFIX, "c[mode]s[factor]f[bits]i[keepsource]b[markers]b[matrix]s[graticule]s[targets]b[axes]b[iq]b[iq_lines]b[circle]b[targets100]b", Histogram::Create }, | ||
| 72 | { 0 } | ||
| 73 | }; | ||
| 74 | |||
| 75 | /*********************************** | ||
| 76 | ******* Histogram Filter ****** | ||
| 77 | **********************************/ | ||
| 78 | |||
| 79 | 11 | Histogram::Histogram(PClip _child, Mode _mode, AVSValue _option, int _show_bits, bool _keepsource, bool _markers, const char* _matrix_name, histogram_color2_params _color2_params, IScriptEnvironment* env) | |
| 80 |
4/8✓ Branch 2 → 3 taken 11 times.
✗ Branch 2 → 151 not taken.
✓ Branch 3 → 4 taken 11 times.
✗ Branch 3 → 149 not taken.
✓ Branch 5 → 6 taken 11 times.
✗ Branch 5 → 173 not taken.
✓ Branch 6 → 7 taken 11 times.
✗ Branch 6 → 171 not taken.
|
11 | : GenericVideoFilter(_child), mode(_mode), option(_option), show_bits(_show_bits), keepsource(_keepsource), markers(_markers), color2_params(_color2_params) |
| 81 | { | ||
| 82 | 11 | bool optionValid = false; | |
| 83 | |||
| 84 |
1/2✓ Branch 8 → 9 taken 11 times.
✗ Branch 8 → 166 not taken.
|
11 | pixelsize = vi.ComponentSize(); |
| 85 |
1/2✓ Branch 9 → 10 taken 11 times.
✗ Branch 9 → 166 not taken.
|
11 | bits_per_pixel = vi.BitsPerComponent(); |
| 86 | |||
| 87 |
4/4✓ Branch 10 → 11 taken 10 times.
✓ Branch 10 → 12 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 9 times.
|
11 | if(show_bits < 8 || show_bits>12) |
| 88 |
1/2✗ Branch 12 → 13 not taken.
✓ Branch 12 → 166 taken 2 times.
|
2 | env->ThrowError("Histogram: bits parameter can only be 8, 9 .. 12"); |
| 89 | |||
| 90 | // until all histogram is ported | ||
| 91 |
2/4✓ Branch 13 → 14 taken 9 times.
✗ Branch 13 → 15 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 9 times.
|
9 | bool non8bit = show_bits != 8 || bits_per_pixel != 8; |
| 92 | |||
| 93 |
1/12✗ Branch 17 → 18 not taken.
✓ Branch 17 → 24 taken 9 times.
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 24 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 19 → 24 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 24 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 24 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
|
9 | if (non8bit && mode != ModeClassic && mode != ModeLevels && mode != ModeColor && mode != ModeColor2 && mode != ModeLuma) |
| 94 | { | ||
| 95 | ✗ | env->ThrowError("Histogram: this histogram type is available only for 8 bit formats and parameters"); | |
| 96 | } | ||
| 97 | |||
| 98 | // Obtain matrix (for YUV) and video range | ||
| 99 |
1/2✓ Branch 25 → 26 taken 9 times.
✗ Branch 25 → 166 not taken.
|
9 | auto frame0 = child->GetFrame(0, env); |
| 100 |
1/2✓ Branch 26 → 27 taken 9 times.
✗ Branch 26 → 164 not taken.
|
9 | const AVSMap* props = env->getFramePropsRO(frame0); |
| 101 | // default YUV matrix AVS_MATRIX_ST170_M (BT 601) | ||
| 102 |
1/2✓ Branch 27 → 28 taken 9 times.
✗ Branch 27 → 164 not taken.
|
9 | const bool rgb_in = vi.IsRGB(); |
| 103 |
1/2✓ Branch 28 → 29 taken 9 times.
✗ Branch 28 → 164 not taken.
|
9 | matrix_parse_merge_with_props(rgb_in, rgb_in /* rgb_out n/a */ , _matrix_name, props, theMatrix, theColorRange, theOutColorRange, env); |
| 104 | |||
| 105 | // theColorRange is either inherited | ||
| 106 | // - from defaults (RGB full YUV limited) or | ||
| 107 | // - _ColorRange frame property or | ||
| 108 | // - manual override from "matrix" param ":f" or ":l" designator | ||
| 109 | // theOutColorRange is only used in yuv-rgb converters | ||
| 110 | 9 | full_range = theColorRange == ColorRange_Compat_e::AVS_COLORRANGE_FULL; | |
| 111 | // Full range or limited? | ||
| 112 | // VectorScope modes (color, color2) require full range to | ||
| 113 | // - properly place the color boxes | ||
| 114 | // - When the histogram's virtual bit-size is different from the real video bit-depth | ||
| 115 | // then video-bit depth must be converted to the histogram's bit-depth either by | ||
| 116 | // limited (shift) or full range (stretch) method. | ||
| 117 | |||
| 118 | 9 | const int shift = 13; // not used here, we only get the floating point matrix | |
| 119 | // use matrix coeffs in color/color2 for positioning RGB color boxes for the actual YUV matrix. | ||
| 120 | // Detected input color range is theColorRange, detected matrix is theMatrix. | ||
| 121 |
2/4✓ Branch 29 → 30 taken 9 times.
✗ Branch 29 → 164 not taken.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 9 times.
|
9 | if (!do_BuildMatrix_Rgb2Yuv(theMatrix, theColorRange, theOutColorRange, shift, 32, /*ref*/matrix)) |
| 122 | ✗ | env->ThrowError("Histogram: Unsupported matrix."); | |
| 123 | |||
| 124 | 9 | origwidth = vi.width; | |
| 125 | 9 | origheight = vi.height; | |
| 126 | |||
| 127 |
2/2✓ Branch 32 → 33 taken 2 times.
✓ Branch 32 → 45 taken 7 times.
|
9 | if (mode == ModeClassic) { |
| 128 |
3/10✓ Branch 33 → 34 taken 2 times.
✗ Branch 33 → 164 not taken.
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 38 taken 2 times.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 164 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 38 not taken.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 2 times.
|
2 | if (!vi.IsYUV() && !vi.IsYUVA()) |
| 129 | ✗ | env->ThrowError("Histogram: YUV(A) data only"); | |
| 130 |
2/2✓ Branch 41 → 42 taken 1 time.
✓ Branch 41 → 43 taken 1 time.
|
2 | if(keepsource) |
| 131 | 1 | vi.width += (1 << show_bits); | |
| 132 | else | ||
| 133 | 1 | vi.width = (1 << show_bits); | |
| 134 |
1/2✓ Branch 44 → 45 taken 2 times.
✗ Branch 44 → 164 not taken.
|
2 | ClassicLUTInit(); |
| 135 | } | ||
| 136 | |||
| 137 |
2/2✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 58 taken 7 times.
|
9 | if (mode == ModeLevels) { |
| 138 |
2/4✓ Branch 46 → 47 taken 2 times.
✗ Branch 46 → 164 not taken.
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 2 times.
|
2 | if (!vi.IsPlanar()) { |
| 139 | ✗ | env->ThrowError("Histogram: Levels mode only available in PLANAR."); | |
| 140 | } | ||
| 141 |
1/2✓ Branch 49 → 50 taken 2 times.
✗ Branch 49 → 164 not taken.
|
2 | optionValid = option.IsFloat(); |
| 142 |
1/2✓ Branch 50 → 51 taken 2 times.
✗ Branch 50 → 164 not taken.
|
2 | const double factor = option.AsDblDef(100.0); // Population limit % factor |
| 143 |
2/4✓ Branch 51 → 52 taken 2 times.
✗ Branch 51 → 53 not taken.
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 2 times.
|
2 | if (factor < 0.0 || factor > 100.0) { |
| 144 | ✗ | env->ThrowError("Histogram: Levels population clamping must be between 0 and 100%"); | |
| 145 | } | ||
| 146 | // put diagram on the right side | ||
| 147 |
1/2✓ Branch 54 → 55 taken 2 times.
✗ Branch 54 → 57 not taken.
|
2 | if (keepsource) { |
| 148 | 2 | vi.width += (1 << show_bits); // 256 for 8 bit | |
| 149 | 2 | vi.height = max(256, vi.height); | |
| 150 | } | ||
| 151 | else { // or keep it alone | ||
| 152 | ✗ | vi.width = (1 << show_bits); | |
| 153 | ✗ | vi.height = 256; // only 224+1 (3*64 + 2*16 + 1) is used | |
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 |
4/4✓ Branch 58 → 59 taken 8 times.
✓ Branch 58 → 60 taken 1 time.
✓ Branch 59 → 60 taken 2 times.
✓ Branch 59 → 77 taken 6 times.
|
9 | if (mode == ModeColor || mode == ModeColor2) { |
| 158 |
2/4✓ Branch 60 → 61 taken 3 times.
✗ Branch 60 → 164 not taken.
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 63 taken 3 times.
|
3 | if (vi.IsRGB()) { |
| 159 | ✗ | env->ThrowError("Histogram: VectorScope modes (color, color2) are not available in RGB."); | |
| 160 | } | ||
| 161 |
2/4✓ Branch 63 → 64 taken 3 times.
✗ Branch 63 → 164 not taken.
✗ Branch 64 → 65 not taken.
✓ Branch 64 → 66 taken 3 times.
|
3 | if (!vi.IsPlanar()) { |
| 162 | ✗ | env->ThrowError("Histogram: VectorScope modes (color, color2) only available in PLANAR."); | |
| 163 | } | ||
| 164 |
3/4✓ Branch 66 → 67 taken 3 times.
✗ Branch 66 → 164 not taken.
✓ Branch 67 → 68 taken 1 time.
✓ Branch 67 → 69 taken 2 times.
|
3 | if (vi.IsY()) { |
| 165 |
1/2✗ Branch 68 → 69 not taken.
✓ Branch 68 → 164 taken 1 time.
|
1 | env->ThrowError("Histogram: VectorScope modes (color, color2) are not available in greyscale."); |
| 166 | } | ||
| 167 | // put diagram on the right side | ||
| 168 |
1/2✗ Branch 69 → 70 not taken.
✓ Branch 69 → 72 taken 2 times.
|
2 | if (keepsource) { |
| 169 | ✗ | vi.width += (1 << show_bits); // 256 for 8 bit | |
| 170 | ✗ | vi.height = max(1 << show_bits, vi.height); | |
| 171 | } | ||
| 172 | else { | ||
| 173 | 2 | vi.width = (1 << show_bits); // 256 for 8 bit | |
| 174 | 2 | vi.height = 1 << show_bits; | |
| 175 | } | ||
| 176 | |||
| 177 | // for params.circle == true | ||
| 178 | // precalculate 15 degree marker dots | ||
| 179 |
1/2✗ Branch 73 → 74 not taken.
✓ Branch 73 → 77 taken 2 times.
|
2 | if (color2_params.circle) { |
| 180 | ✗ | const int half = (1 << (show_bits - 1)) - 1; // 127 | |
| 181 | // dots are placed somewhat inside to the colorful circle, which is thicker for higher show_bits | ||
| 182 | ✗ | color2_innerF = 124.9; // .9 is for better visuals in subsampled mode | |
| 183 | ✗ | int R = (int)(1 + color2_innerF * (1 << (show_bits - 8)) + 0.5); // 126 for 8 bits | |
| 184 | |||
| 185 | ✗ | for (int y = 0; y < 24; y++) { // just inside the big circle | |
| 186 | ✗ | deg15c[y] = (int)(R * cos(y * PI / 12.) + 0.5) + half; | |
| 187 | ✗ | deg15s[y] = (int)(-R * sin(y * PI / 12.) + 0.5) + half; | |
| 188 | } | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 |
7/12✓ Branch 77 → 78 taken 1 time.
✓ Branch 77 → 83 taken 7 times.
✓ Branch 78 → 79 taken 1 time.
✗ Branch 78 → 164 not taken.
✓ Branch 79 → 80 taken 1 time.
✗ Branch 79 → 83 not taken.
✓ Branch 80 → 81 taken 1 time.
✗ Branch 80 → 164 not taken.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 1 time.
✗ Branch 84 → 85 not taken.
✓ Branch 84 → 86 taken 8 times.
|
8 | if (mode == ModeLuma && !vi.IsYUV() && !vi.IsYUVA()) { |
| 193 | ✗ | env->ThrowError("Histogram: Luma mode only available in YUV(A)."); | |
| 194 | } | ||
| 195 | |||
| 196 |
3/6✓ Branch 86 → 87 taken 8 times.
✗ Branch 86 → 89 not taken.
✓ Branch 87 → 88 taken 8 times.
✗ Branch 87 → 89 not taken.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 122 taken 8 times.
|
8 | if ((mode == ModeStereoY8)||(mode == ModeStereo)||(mode == ModeOverlay)) { |
| 197 | |||
| 198 | ✗ | child->SetCacheHints(CACHE_AUDIO,4096*1024); | |
| 199 | |||
| 200 | ✗ | if (!vi.HasVideo()) { | |
| 201 | ✗ | mode = ModeStereo; // force mode to ModeStereo. | |
| 202 | ✗ | vi.fps_numerator = 25; | |
| 203 | ✗ | vi.fps_denominator = 1; | |
| 204 | ✗ | vi.num_frames = vi.FramesFromAudioSamples(vi.num_audio_samples); | |
| 205 | } | ||
| 206 | ✗ | if (mode == ModeOverlay) { | |
| 207 | ✗ | if (keepsource) { | |
| 208 | ✗ | vi.height = max(512, vi.height); | |
| 209 | ✗ | vi.width = max(512, vi.width); | |
| 210 | } | ||
| 211 | else { | ||
| 212 | ✗ | vi.height = 512; | |
| 213 | ✗ | vi.width = 512; | |
| 214 | } | ||
| 215 | ✗ | if (vi.IsRGB()) { | |
| 216 | ✗ | env->ThrowError("Histogram: StereoOverlay mode is not available in RGB."); | |
| 217 | } | ||
| 218 | ✗ | if (!vi.IsPlanar()) { | |
| 219 | ✗ | env->ThrowError("Histogram: StereoOverlay only available in Y or YUV(A)."); | |
| 220 | } | ||
| 221 | ✗ | } else if (mode == ModeStereoY8) { | |
| 222 | ✗ | vi.pixel_type = VideoInfo::CS_Y8; | |
| 223 | ✗ | vi.height = 512; | |
| 224 | ✗ | vi.width = 512; | |
| 225 | } else { | ||
| 226 | ✗ | vi.pixel_type = VideoInfo::CS_YV12; | |
| 227 | ✗ | vi.height = 512; | |
| 228 | ✗ | vi.width = 512; | |
| 229 | } | ||
| 230 | ✗ | if (!vi.HasAudio()) { | |
| 231 | ✗ | env->ThrowError("Histogram: Stereo mode requires samples!"); | |
| 232 | } | ||
| 233 | ✗ | if (vi.AudioChannels() != 2) { | |
| 234 | ✗ | env->ThrowError("Histogram: Stereo mode only works on two audio channels."); | |
| 235 | } | ||
| 236 | |||
| 237 | ✗ | aud_clip = ConvertAudio::Create(child,SAMPLE_INT16,SAMPLE_INT16); | |
| 238 | } | ||
| 239 | |||
| 240 |
2/2✓ Branch 122 → 123 taken 1 time.
✓ Branch 122 → 140 taken 7 times.
|
8 | if (mode == ModeAudioLevels) { |
| 241 |
1/2✓ Branch 124 → 125 taken 1 time.
✗ Branch 124 → 164 not taken.
|
1 | child->SetCacheHints(CACHE_AUDIO, 4096*1024); |
| 242 |
2/4✓ Branch 125 → 126 taken 1 time.
✗ Branch 125 → 164 not taken.
✗ Branch 126 → 127 not taken.
✓ Branch 126 → 128 taken 1 time.
|
1 | if (vi.IsRGB()) { |
| 243 | ✗ | env->ThrowError("Histogram: Audiolevels mode is not available in RGB."); | |
| 244 | } | ||
| 245 |
2/4✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 164 not taken.
✗ Branch 129 → 130 not taken.
✓ Branch 129 → 131 taken 1 time.
|
1 | if (!vi.IsPlanar()) { |
| 246 | ✗ | env->ThrowError("Histogram: Audiolevels mode only available in planar YUV."); | |
| 247 | } | ||
| 248 |
2/4✓ Branch 131 → 132 taken 1 time.
✗ Branch 131 → 164 not taken.
✗ Branch 132 → 133 not taken.
✓ Branch 132 → 134 taken 1 time.
|
1 | if (vi.IsY8()) { |
| 249 | ✗ | env->ThrowError("Histogram: AudioLevels mode not available in Y8."); | |
| 250 | } | ||
| 251 | |||
| 252 |
3/6✓ Branch 134 → 135 taken 1 time.
✗ Branch 134 → 162 not taken.
✓ Branch 135 → 136 taken 1 time.
✗ Branch 135 → 160 not taken.
✓ Branch 136 → 137 taken 1 time.
✗ Branch 136 → 158 not taken.
|
1 | aud_clip = ConvertAudio::Create(child, SAMPLE_INT16, SAMPLE_INT16); |
| 253 | } | ||
| 254 | |||
| 255 |
5/8✓ Branch 140 → 141 taken 6 times.
✓ Branch 140 → 144 taken 2 times.
✓ Branch 141 → 142 taken 6 times.
✗ Branch 141 → 164 not taken.
✗ Branch 142 → 143 not taken.
✓ Branch 142 → 144 taken 6 times.
✗ Branch 145 → 146 not taken.
✓ Branch 145 → 147 taken 8 times.
|
8 | if (!optionValid && option.Defined()) |
| 256 | ✗ | env->ThrowError("Histogram: Unknown optional value."); | |
| 257 | 21 | } | |
| 258 | |||
| 259 | 7 | PVideoFrame __stdcall Histogram::GetFrame(int n, IScriptEnvironment* env) | |
| 260 | { | ||
| 261 |
5/9✓ Branch 2 → 3 taken 3 times.
✓ Branch 2 → 4 taken 1 time.
✓ Branch 2 → 5 taken 1 time.
✓ Branch 2 → 6 taken 1 time.
✓ Branch 2 → 7 taken 1 time.
✗ Branch 2 → 8 not taken.
✗ Branch 2 → 9 not taken.
✗ Branch 2 → 10 not taken.
✗ Branch 2 → 11 not taken.
|
7 | switch (mode) { |
| 262 | 3 | case ModeClassic: | |
| 263 | 3 | return DrawModeClassic(n, env); | |
| 264 | 1 | case ModeLevels: | |
| 265 | 1 | return DrawModeLevels(n, env); | |
| 266 | 1 | case ModeColor: | |
| 267 | 1 | return DrawModeColor(n, env); | |
| 268 | 1 | case ModeColor2: | |
| 269 | 1 | return DrawModeColor2(n, env); | |
| 270 | 1 | case ModeLuma: | |
| 271 | 1 | return DrawModeLuma(n, env); | |
| 272 | ✗ | case ModeStereoY8: | |
| 273 | case ModeStereo: | ||
| 274 | ✗ | return DrawModeStereo(n, env); | |
| 275 | ✗ | case ModeOverlay: | |
| 276 | ✗ | return DrawModeOverlay(n, env); | |
| 277 | ✗ | case ModeAudioLevels: | |
| 278 | ✗ | return DrawModeAudioLevels(n, env); | |
| 279 | } | ||
| 280 | ✗ | return DrawModeClassic(n, env); | |
| 281 | } | ||
| 282 | |||
| 283 | ✗ | inline void MixLuma(BYTE &src, int value, int alpha) { | |
| 284 | ✗ | src = src + BYTE(((value - (int)src) * alpha) >> 8); | |
| 285 | ✗ | } | |
| 286 | |||
| 287 | ✗ | PVideoFrame Histogram::DrawModeAudioLevels(int n, IScriptEnvironment* env) { | |
| 288 | ✗ | PVideoFrame src = child->GetFrame(n, env); | |
| 289 | ✗ | env->MakeWritable(&src); | |
| 290 | ✗ | const int w = src->GetRowSize(); | |
| 291 | ✗ | const int channels = vi.AudioChannels(); | |
| 292 | |||
| 293 | ✗ | constexpr int TEXT_HEIGHT = 20; // for DrawString | |
| 294 | ✗ | int bar_w = 60; // Must be divideable by 4 (for subsampling) | |
| 295 | ✗ | int total_width = (1+channels*2)*bar_w; // Total width in pixels. | |
| 296 | |||
| 297 | ✗ | if (total_width > w) { | |
| 298 | ✗ | bar_w = ((w / (1+channels*2)) / 4)* 4; | |
| 299 | } | ||
| 300 | ✗ | total_width = (1+channels*2)*bar_w; // Total width in pixels. | |
| 301 | ✗ | int bar_h = vi.height; | |
| 302 | |||
| 303 | // Get audio for current frame. | ||
| 304 | ✗ | const int64_t start = vi.AudioSamplesFromFrames(n); | |
| 305 | ✗ | const int count = (int)(vi.AudioSamplesFromFrames(1)); | |
| 306 | ✗ | signed short* samples = static_cast<signed short*>(_alloca(sizeof(signed short)* count * channels)); | |
| 307 | |||
| 308 | ✗ | aud_clip->GetAudio(samples, max((int64_t)0ll,start), count, env); | |
| 309 | |||
| 310 | // Find maximum volume and rms. | ||
| 311 | ✗ | int* channel_max = static_cast<int*>(_alloca(channels * sizeof(int))); | |
| 312 | ✗ | int64_t* channel_rms = static_cast<int64_t*>(_alloca(channels * sizeof(int64_t)));; | |
| 313 | |||
| 314 | ✗ | const int c = count*channels; | |
| 315 | ✗ | for (int ch = 0; ch<channels; ch++) { | |
| 316 | ✗ | int max_vol = 0; | |
| 317 | ✗ | int64_t rms_vol = 0; | |
| 318 | |||
| 319 | ✗ | for (int i = ch; i < c; i += channels) { | |
| 320 | ✗ | int sample = samples[i]; | |
| 321 | ✗ | sample *= sample; | |
| 322 | ✗ | rms_vol += sample; | |
| 323 | ✗ | max_vol = max(max_vol, sample); | |
| 324 | } | ||
| 325 | ✗ | channel_max[ch] = max_vol; | |
| 326 | ✗ | channel_rms[ch] = rms_vol; | |
| 327 | } | ||
| 328 | |||
| 329 | // Draw bars | ||
| 330 | ✗ | BYTE* srcpY = src->GetWritePtr(PLANAR_Y); | |
| 331 | ✗ | int Ypitch = src->GetPitch(PLANAR_Y); | |
| 332 | ✗ | BYTE* srcpU = src->GetWritePtr(PLANAR_U); | |
| 333 | ✗ | BYTE* srcpV = src->GetWritePtr(PLANAR_V); | |
| 334 | ✗ | int UVpitch = src->GetPitch(PLANAR_U); | |
| 335 | ✗ | int xSubS = vi.GetPlaneWidthSubsampling(PLANAR_U); | |
| 336 | ✗ | int ySubS = vi.GetPlaneHeightSubsampling(PLANAR_U); | |
| 337 | |||
| 338 | // Draw Dotted lines | ||
| 339 | ✗ | const int lines = 16; // Line every 6dB (96/6) | |
| 340 | int lines_y[lines]; | ||
| 341 | ✗ | float line_every = (float)bar_h / (float)lines; | |
| 342 | char text[32]; | ||
| 343 | ✗ | for (int i=0; i<lines; i++) { | |
| 344 | ✗ | lines_y[i] = (int)(line_every*i); | |
| 345 | ✗ | if (!(i&1)) { | |
| 346 | ✗ | snprintf(text, sizeof(text), "%3ddB", -i*6); | |
| 347 | ✗ | DrawStringPlanar(vi, src, 0, i ? lines_y[i] : TEXT_HEIGHT / 2, text); | |
| 348 | } | ||
| 349 | } | ||
| 350 | ✗ | for (int x=bar_w-16; x<total_width-bar_w+16; x++) { | |
| 351 | ✗ | if (!(x&12)) { | |
| 352 | ✗ | for (int i=0; i<lines; i++) { | |
| 353 | ✗ | srcpY[x+lines_y[i]*Ypitch] = 200; | |
| 354 | } | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 358 | ✗ | for (int ch = 0; ch<channels; ch++) { | |
| 359 | ✗ | int max = channel_max[ch]; | |
| 360 | ✗ | double ch_db = 96; | |
| 361 | ✗ | if (max > 0) { | |
| 362 | ✗ | ch_db = -8.685889638/2.0 * log((double)max/(32768.0*32768.0)); | |
| 363 | } | ||
| 364 | |||
| 365 | ✗ | int64_t rms = channel_rms[ch] / count; | |
| 366 | ✗ | double ch_rms = 96; | |
| 367 | ✗ | if (rms > 0) { | |
| 368 | ✗ | ch_rms = -8.685889638/2.0 * log((double)rms/(32768.0*32768.0)); | |
| 369 | } | ||
| 370 | |||
| 371 | ✗ | int x_pos = ((ch*2)+1)*bar_w+8; | |
| 372 | ✗ | int x_end = x_pos+bar_w-8; | |
| 373 | ✗ | int y_pos = (int)(((double)bar_h*ch_db) / 96.0); | |
| 374 | ✗ | int y_mid = (int)(((double)bar_h*ch_rms) / 96.0); | |
| 375 | ✗ | int y_end = src->GetHeight(PLANAR_Y); | |
| 376 | // Luma Red Blue | ||
| 377 | ✗ | int y_val = (max>=32767*32767) ? 78 : 90; | |
| 378 | ✗ | int a_val = (max>=32767*32767) ? 96 : 128; | |
| 379 | ✗ | for (int y = y_pos; y<y_mid; y++) { | |
| 380 | ✗ | for (int x = x_pos; x < x_end; x++) { | |
| 381 | ✗ | MixLuma(srcpY[x+y*Ypitch], y_val, a_val); | |
| 382 | } | ||
| 383 | } // Yellow Green | ||
| 384 | ✗ | y_val = (max>=32767*32767) ? 216 : 137; | |
| 385 | ✗ | a_val = (max>=32767*32767) ? 160 : 128; | |
| 386 | ✗ | for (int y = y_mid; y<y_end; y++) { | |
| 387 | ✗ | for (int x = x_pos; x < x_end; x++) { | |
| 388 | ✗ | MixLuma(srcpY[x+y*Ypitch], y_val, a_val); | |
| 389 | } | ||
| 390 | } | ||
| 391 | // Chroma | ||
| 392 | ✗ | x_pos >>= xSubS; | |
| 393 | ✗ | x_end >>= xSubS; | |
| 394 | ✗ | y_pos >>= ySubS; | |
| 395 | ✗ | y_mid >>= ySubS; | |
| 396 | ✗ | y_end = src->GetHeight(PLANAR_U);//Red Blue | |
| 397 | ✗ | BYTE u_val = (max>=32767*32767) ? 92 : 212; | |
| 398 | ✗ | BYTE v_val = (max>=32767*32767) ? 233 : 114; | |
| 399 | ✗ | for (int y = y_pos; y<y_mid; y++) { | |
| 400 | ✗ | for (int x = x_pos; x < x_end; x++) { | |
| 401 | ✗ | srcpU[x+y*UVpitch] = u_val; | |
| 402 | ✗ | srcpV[x+y*UVpitch] = v_val; | |
| 403 | } | ||
| 404 | } // Yellow Green | ||
| 405 | ✗ | u_val = (max>=32767*32767) ? 44 : 58; | |
| 406 | ✗ | v_val = (max>=32767*32767) ? 142 : 40; | |
| 407 | ✗ | for (int y = y_mid; y<y_end; y++) { | |
| 408 | ✗ | for (int x = x_pos; x < x_end; x++) { | |
| 409 | ✗ | srcpU[x+y*UVpitch] = u_val; | |
| 410 | ✗ | srcpV[x+y*UVpitch] = v_val; | |
| 411 | } | ||
| 412 | } | ||
| 413 | // Draw text | ||
| 414 | ✗ | snprintf(text, sizeof(text), "%6.2fdB", (float)-ch_db); | |
| 415 | ✗ | DrawStringPlanar(vi, src, ((ch*2)+1)*bar_w, vi.height- 2 * TEXT_HEIGHT + TEXT_HEIGHT / 2, text); | |
| 416 | ✗ | snprintf(text, sizeof(text), "%6.2fdB", (float)-ch_rms); | |
| 417 | ✗ | DrawStringPlanar(vi, src, ((ch*2)+1)*bar_w, vi.height- 1 * TEXT_HEIGHT + TEXT_HEIGHT / 2, text); | |
| 418 | |||
| 419 | } | ||
| 420 | |||
| 421 | ✗ | return src; | |
| 422 | ✗ | } | |
| 423 | |||
| 424 | ✗ | PVideoFrame Histogram::DrawModeOverlay(int n, IScriptEnvironment* env) { | |
| 425 | ✗ | PVideoFrame src = child->GetFrame(n, env); | |
| 426 | ✗ | PVideoFrame dst = env->NewVideoFrameP(vi, &src); | |
| 427 | |||
| 428 | ✗ | int64_t start = vi.AudioSamplesFromFrames(n); | |
| 429 | ✗ | int64_t end = vi.AudioSamplesFromFrames(n+1); | |
| 430 | ✗ | int64_t count = end-start; | |
| 431 | signed short* samples = static_cast<signed short*>( | ||
| 432 | ✗ | env->Allocate((int)count * vi.AudioChannels() * sizeof(unsigned short), 8, AVS_POOLED_ALLOC) | |
| 433 | ); | ||
| 434 | ✗ | if (!samples) { | |
| 435 | ✗ | env->ThrowError("Histogram: Could not reserve memory."); | |
| 436 | } | ||
| 437 | |||
| 438 | ✗ | int h = dst->GetHeight(); | |
| 439 | ✗ | int imgSize = h*dst->GetPitch(); | |
| 440 | ✗ | BYTE* dstp = dst->GetWritePtr(); | |
| 441 | ✗ | int p = dst->GetPitch(PLANAR_Y); | |
| 442 | |||
| 443 | ✗ | if ((src->GetHeight()<dst->GetHeight()) || (src->GetRowSize() < dst->GetRowSize())) { | |
| 444 | ✗ | memset(dstp, 16, imgSize); | |
| 445 | ✗ | int imgSizeU = dst->GetHeight(PLANAR_U) * dst->GetPitch(PLANAR_U); | |
| 446 | ✗ | if (imgSizeU) { | |
| 447 | ✗ | memset(dst->GetWritePtr(PLANAR_U), 128, imgSizeU); | |
| 448 | ✗ | memset(dst->GetWritePtr(PLANAR_V), 128, imgSizeU); | |
| 449 | } | ||
| 450 | } | ||
| 451 | |||
| 452 | ✗ | env->BitBlt(dstp, dst->GetPitch(), src->GetReadPtr(), src->GetPitch(), src->GetRowSize(), src->GetHeight()); | |
| 453 | ✗ | env->BitBlt(dst->GetWritePtr(PLANAR_U), dst->GetPitch(PLANAR_U), src->GetReadPtr(PLANAR_U), src->GetPitch(PLANAR_U), src->GetRowSize(PLANAR_U), src->GetHeight(PLANAR_U)); | |
| 454 | ✗ | env->BitBlt(dst->GetWritePtr(PLANAR_V), dst->GetPitch(PLANAR_V), src->GetReadPtr(PLANAR_V), src->GetPitch(PLANAR_V), src->GetRowSize(PLANAR_V), src->GetHeight(PLANAR_V)); | |
| 455 | |||
| 456 | ✗ | BYTE* _dstp = dstp; | |
| 457 | ✗ | for (int iY = 0; iY<512; iY++) { | |
| 458 | ✗ | for (int iX = 0; iX<512; iX++) { | |
| 459 | ✗ | _dstp[iX] >>= 1; | |
| 460 | } | ||
| 461 | ✗ | _dstp+=p; | |
| 462 | } | ||
| 463 | |||
| 464 | ✗ | aud_clip->GetAudio(samples, max((int64_t)0ll,start), count, env); | |
| 465 | |||
| 466 | ✗ | int c = (int)count; | |
| 467 | ✗ | for (int i=1; i < c;i++) { | |
| 468 | ✗ | int l1 = samples[i*2-2]; | |
| 469 | ✗ | int r1 = samples[i*2-1]; | |
| 470 | ✗ | int l2 = samples[i*2]; | |
| 471 | ✗ | int r2 = samples[i*2+1]; | |
| 472 | ✗ | for (int s = 0 ; s < 8; s++) { // 8 times supersampling (linear) | |
| 473 | ✗ | int l = (l1*s) + (l2*(8-s)); | |
| 474 | ✗ | int r = (r1*s) + (r2*(8-s)); | |
| 475 | ✗ | int y = 256+((l+r)>>11); | |
| 476 | ✗ | int x = 256+((l-r)>>11); | |
| 477 | ✗ | BYTE v = dstp[x+y*p]+48; | |
| 478 | ✗ | dstp[x+y*p] = min(v,(BYTE)235); | |
| 479 | } | ||
| 480 | } | ||
| 481 | |||
| 482 | ✗ | int y_off = p*256; | |
| 483 | ✗ | for (int x = 0; x < 512; x+=16) | |
| 484 | ✗ | dstp[y_off + x] = (dstp[y_off + x] > 127) ? 16 : 235; | |
| 485 | |||
| 486 | ✗ | for (int y = 0; y < 512;y+=16) | |
| 487 | ✗ | dstp[y*p+256] = (dstp[y*p+256]>127) ? 16 : 235 ; | |
| 488 | |||
| 489 | ✗ | env->Free(samples); | |
| 490 | ✗ | return dst; | |
| 491 | ✗ | } | |
| 492 | |||
| 493 | |||
| 494 | ✗ | PVideoFrame Histogram::DrawModeStereo(int n, IScriptEnvironment* env) { | |
| 495 | ✗ | PVideoFrame src = env->NewVideoFrame(vi); | |
| 496 | ✗ | int64_t start = vi.AudioSamplesFromFrames(n); | |
| 497 | ✗ | int64_t end = vi.AudioSamplesFromFrames(n+1); | |
| 498 | ✗ | int64_t count = end-start; | |
| 499 | signed short* samples = static_cast<signed short*>( | ||
| 500 | ✗ | env->Allocate((int)count * vi.AudioChannels() * sizeof(unsigned short), 8, AVS_POOLED_ALLOC) | |
| 501 | ); | ||
| 502 | ✗ | if (!samples) { | |
| 503 | ✗ | env->ThrowError("Histogram: Could not reserve memory."); | |
| 504 | } | ||
| 505 | |||
| 506 | ✗ | int h = src->GetHeight(); | |
| 507 | ✗ | int imgSize = h*src->GetPitch(); | |
| 508 | ✗ | BYTE* srcp = src->GetWritePtr(); | |
| 509 | ✗ | memset(srcp, 16, imgSize); | |
| 510 | ✗ | int p = src->GetPitch(); | |
| 511 | |||
| 512 | ✗ | aud_clip->GetAudio(samples, max((int64_t)0ll,start), count, env); | |
| 513 | |||
| 514 | ✗ | int c = (int)count; | |
| 515 | ✗ | for (int i=1; i < c;i++) { | |
| 516 | ✗ | int l1 = samples[i*2-2]; | |
| 517 | ✗ | int r1 = samples[i*2-1]; | |
| 518 | ✗ | int l2 = samples[i*2]; | |
| 519 | ✗ | int r2 = samples[i*2+1]; | |
| 520 | ✗ | for (int s = 0 ; s < 8; s++) { // 8 times supersampling (linear) | |
| 521 | ✗ | int l = (l1*s) + (l2*(8-s)); | |
| 522 | ✗ | int r = (r1*s) + (r2*(8-s)); | |
| 523 | ✗ | int y = 256+((l+r)>>11); | |
| 524 | ✗ | int x = 256+((l-r)>>11); | |
| 525 | ✗ | BYTE v = srcp[x+y*512]+48; | |
| 526 | ✗ | srcp[x+y*512] = min(v, (BYTE)235); | |
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | ✗ | int y_off = p*256; | |
| 531 | ✗ | for (int x = 0; x < 512; x+=16) | |
| 532 | ✗ | srcp[y_off + x] = (srcp[y_off + x] > 127) ? 16 : 235; | |
| 533 | |||
| 534 | ✗ | for (int y = 0; y < 512;y+=16) | |
| 535 | ✗ | srcp[y*p+256] = (srcp[y*p+256]>127) ? 16 : 235 ; | |
| 536 | |||
| 537 | ✗ | if (vi.IsYV12()) { | |
| 538 | ✗ | srcp = src->GetWritePtr(PLANAR_U); | |
| 539 | ✗ | imgSize = src->GetHeight(PLANAR_U) * src->GetPitch(PLANAR_U); | |
| 540 | ✗ | memset(srcp, 128, imgSize); | |
| 541 | ✗ | srcp = src->GetWritePtr(PLANAR_V); | |
| 542 | ✗ | memset(srcp, 128, imgSize); | |
| 543 | } | ||
| 544 | |||
| 545 | ✗ | env->Free(samples); | |
| 546 | ✗ | return src; | |
| 547 | ✗ | } | |
| 548 | |||
| 549 | |||
| 550 | 1 | PVideoFrame Histogram::DrawModeLuma(int n, IScriptEnvironment* env) { | |
| 551 | // amplify luminance. | ||
| 552 | // In this mode a 1 pixel luminance difference (8 bits world) will show as | ||
| 553 | // a 16 pixel luminance, thus seriously enhancing small flaws | ||
| 554 | 1 | PVideoFrame src = child->GetFrame(n, env); | |
| 555 |
1/2✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 84 not taken.
|
1 | env->MakeWritable(&src); |
| 556 |
1/2✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 84 not taken.
|
1 | const int h = src->GetHeight(); |
| 557 |
1/2✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 84 not taken.
|
1 | BYTE* srcp = src->GetWritePtr(); |
| 558 |
2/4✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 84 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 19 taken 1 time.
|
1 | if (vi.IsYUY2()) { |
| 559 | ✗ | int imgsize = h * src->GetPitch(); | |
| 560 | ✗ | for (int i=0; i<imgsize; i+=2) { | |
| 561 | ✗ | int p = srcp[i]; | |
| 562 | ✗ | p<<=4; | |
| 563 | ✗ | srcp[i+1] = 128; | |
| 564 | ✗ | srcp[i] = BYTE((p&256) ? (255-(p&0xff)) : p&0xff); | |
| 565 | } | ||
| 566 | } else { | ||
| 567 | 1 | const int w = vi.width; | |
| 568 |
1/2✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 84 not taken.
|
1 | const int pitch = src->GetPitch(); |
| 569 |
1/2✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 31 not taken.
|
1 | if (bits_per_pixel == 8) { |
| 570 |
2/2✓ Branch 30 → 23 taken 4 times.
✓ Branch 30 → 50 taken 1 time.
|
5 | for (int y = 0; y < h; y++) { |
| 571 |
2/2✓ Branch 28 → 24 taken 16 times.
✓ Branch 28 → 29 taken 4 times.
|
20 | for (int x = 0; x < w; x++) { |
| 572 | 16 | const int pixel = srcp[x] << 4; // *16 | |
| 573 |
2/2✓ Branch 24 → 25 taken 8 times.
✓ Branch 24 → 26 taken 8 times.
|
16 | srcp[x] = BYTE((pixel & 256) ? (255 - (pixel & 0xff)) : pixel & 0xff); |
| 574 | } | ||
| 575 | 4 | srcp += pitch; | |
| 576 | } | ||
| 577 | } | ||
| 578 | ✗ | else if (bits_per_pixel <= 16) { | |
| 579 | ✗ | const int overlimit = (1 << bits_per_pixel); | |
| 580 | ✗ | const int max_pixel_value = (1 << bits_per_pixel) - 1; | |
| 581 | ✗ | for (int y = 0; y < h; y++) { | |
| 582 | ✗ | for (int x = 0; x < w; x++) { | |
| 583 | ✗ | const int pixel = reinterpret_cast<uint16_t*>(srcp)[x] << 4; | |
| 584 | ✗ | reinterpret_cast<uint16_t*>(srcp)[x] = (uint16_t)((pixel & overlimit) ? (max_pixel_value - (pixel & max_pixel_value)) : pixel & max_pixel_value); | |
| 585 | } | ||
| 586 | ✗ | srcp += pitch; | |
| 587 | } | ||
| 588 | } | ||
| 589 | else { | ||
| 590 | // 32 bit float | ||
| 591 | // just simulated by converting to 8 bits | ||
| 592 | ✗ | for (int y = 0; y < h; y++) { | |
| 593 | ✗ | for (int x = 0; x < w; x++) { | |
| 594 | ✗ | const float pixel_f = reinterpret_cast<float*>(srcp)[x]; | |
| 595 | ✗ | const int pixel_i = (int)(pixel_f * 255.0f + 0.5f); | |
| 596 | ✗ | const int pixel = pixel_i << 4; // *16 | |
| 597 | ✗ | int pixel_out = BYTE((pixel & 256) ? (255 - (pixel & 0xff)) : pixel & 0xff); | |
| 598 | ✗ | const float pixel_out_f = pixel_out / 255.0f; | |
| 599 | ✗ | reinterpret_cast<float*>(srcp)[x] = pixel_out_f; | |
| 600 | } | ||
| 601 | ✗ | srcp += pitch; | |
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 |
2/4✓ Branch 50 → 51 taken 1 time.
✗ Branch 50 → 84 not taken.
✓ Branch 51 → 52 taken 1 time.
✗ Branch 51 → 82 not taken.
|
1 | if (vi.NumComponents() >= 3) { |
| 606 |
1/2✓ Branch 53 → 54 taken 1 time.
✗ Branch 53 → 84 not taken.
|
1 | auto dstp_u = src->GetWritePtr(PLANAR_U); |
| 607 |
1/2✓ Branch 55 → 56 taken 1 time.
✗ Branch 55 → 84 not taken.
|
1 | auto dstp_v = src->GetWritePtr(PLANAR_V); |
| 608 |
1/2✓ Branch 57 → 58 taken 1 time.
✗ Branch 57 → 84 not taken.
|
1 | auto height_uv = src->GetHeight(PLANAR_U); |
| 609 |
1/2✓ Branch 59 → 60 taken 1 time.
✗ Branch 59 → 84 not taken.
|
1 | auto rowsize_uv = src->GetRowSize(PLANAR_U); |
| 610 |
1/2✓ Branch 61 → 62 taken 1 time.
✗ Branch 61 → 84 not taken.
|
1 | auto pitch_uv = src->GetPitch(PLANAR_U); |
| 611 |
1/2✓ Branch 62 → 63 taken 1 time.
✗ Branch 62 → 64 not taken.
|
1 | if (bits_per_pixel == 8) |
| 612 |
1/2✓ Branch 63 → 67 taken 1 time.
✗ Branch 63 → 84 not taken.
|
1 | fill_chroma<uint8_t>(dstp_u, dstp_v, height_uv, rowsize_uv, pitch_uv, 128); |
| 613 | ✗ | else if (bits_per_pixel <= 16) | |
| 614 | ✗ | fill_chroma<uint16_t>(dstp_u, dstp_v, height_uv, rowsize_uv, pitch_uv, 128 << (bits_per_pixel - 8)); | |
| 615 | else // 32) | ||
| 616 | ✗ | fill_chroma<float>(dstp_u, dstp_v, height_uv, rowsize_uv, pitch_uv, 0.0f); | |
| 617 | |||
| 618 | // alpha | ||
| 619 |
2/4✓ Branch 67 → 68 taken 1 time.
✗ Branch 67 → 84 not taken.
✓ Branch 68 → 69 taken 1 time.
✗ Branch 68 → 82 not taken.
|
1 | if (vi.NumComponents() == 4) { |
| 620 |
1/2✓ Branch 70 → 71 taken 1 time.
✗ Branch 70 → 84 not taken.
|
1 | auto dstp_a = src->GetWritePtr(PLANAR_A); |
| 621 |
1/2✓ Branch 72 → 73 taken 1 time.
✗ Branch 72 → 84 not taken.
|
1 | auto height_a = src->GetHeight(PLANAR_A); |
| 622 |
1/2✓ Branch 74 → 75 taken 1 time.
✗ Branch 74 → 84 not taken.
|
1 | auto rowsize_a = src->GetRowSize(PLANAR_A); |
| 623 |
1/2✓ Branch 76 → 77 taken 1 time.
✗ Branch 76 → 84 not taken.
|
1 | auto pitch_a = src->GetPitch(PLANAR_A); |
| 624 |
1/2✓ Branch 77 → 78 taken 1 time.
✗ Branch 77 → 79 not taken.
|
1 | if (bits_per_pixel == 8) |
| 625 |
1/2✓ Branch 78 → 82 taken 1 time.
✗ Branch 78 → 84 not taken.
|
1 | fill_plane<uint8_t>(dstp_a, height_a, rowsize_a, pitch_a, 255); |
| 626 | ✗ | else if (bits_per_pixel <= 16) | |
| 627 | ✗ | fill_plane<uint16_t>(dstp_a, height_a, rowsize_a, pitch_a, (1 << bits_per_pixel) - 1); | |
| 628 | else // 32) | ||
| 629 | ✗ | fill_plane<float>(dstp_a, height_a, rowsize_a, pitch_a, 1.0f); | |
| 630 | } | ||
| 631 | } | ||
| 632 | } | ||
| 633 | 1 | return src; | |
| 634 | ✗ | } | |
| 635 | |||
| 636 | template<typename pixel_t> | ||
| 637 | ✗ | static void DrawModeColor2_DrawRect( | |
| 638 | pixel_t* dstp, int pitch, | ||
| 639 | pixel_t* dstpU, pixel_t* dstpV, int pitchUV, | ||
| 640 | int cx, int cy, // center in luma coords | ||
| 641 | int half_w, int half_h, // half-size in luma coords | ||
| 642 | int swidth, int sheight, | ||
| 643 | pixel_t luma_val, | ||
| 644 | pixel_t u_val, pixel_t v_val, | ||
| 645 | int limit_showwidth // bounds check | ||
| 646 | ) | ||
| 647 | { | ||
| 648 | // Draw horizontal top/bottom edges (luma) | ||
| 649 | ✗ | for (int x = cx - half_w; x <= cx + half_w; x++) { | |
| 650 | ✗ | if (x < 0 || x >= limit_showwidth) continue; | |
| 651 | ✗ | int y_top = cy - half_h; | |
| 652 | ✗ | int y_bot = cy + half_h; | |
| 653 | ✗ | if (y_top >= 0 && y_top < limit_showwidth) | |
| 654 | ✗ | dstp[x + y_top * pitch] = luma_val; | |
| 655 | ✗ | if (y_bot >= 0 && y_bot < limit_showwidth) | |
| 656 | ✗ | dstp[x + y_bot * pitch] = luma_val; | |
| 657 | } | ||
| 658 | |||
| 659 | // Draw vertical left/right edges (luma) | ||
| 660 | ✗ | for (int y = cy - half_h; y <= cy + half_h; y++) { | |
| 661 | ✗ | if (y < 0 || y >= limit_showwidth) continue; | |
| 662 | ✗ | int x_l = cx - half_w; | |
| 663 | ✗ | int x_r = cx + half_w; | |
| 664 | ✗ | if (x_l >= 0 && x_l < limit_showwidth) | |
| 665 | ✗ | dstp[x_l + y * pitch] = luma_val; | |
| 666 | ✗ | if (x_r >= 0 && x_r < limit_showwidth) | |
| 667 | ✗ | dstp[x_r + y * pitch] = luma_val; | |
| 668 | } | ||
| 669 | |||
| 670 | // Chroma planes (subsampled) | ||
| 671 | ✗ | const int limit_showwidth_uv = limit_showwidth >> swidth; | |
| 672 | ✗ | const int limit_showheight_uv = limit_showwidth >> sheight; | |
| 673 | |||
| 674 | // Convert luma coordinates to chroma coordinates | ||
| 675 | ✗ | const int cx_uv = cx >> swidth; | |
| 676 | ✗ | const int cy_uv = cy >> sheight; | |
| 677 | ✗ | const int half_w_uv = half_w >> swidth; | |
| 678 | ✗ | const int half_h_uv = half_h >> sheight; | |
| 679 | |||
| 680 | // Draw horizontal top/bottom edges (chroma) | ||
| 681 | ✗ | for (int x = cx_uv - half_w_uv; x <= cx_uv + half_w_uv; x++) { | |
| 682 | ✗ | if (x < 0 || x >= limit_showwidth_uv) continue; | |
| 683 | ✗ | int y_top = cy_uv - half_h_uv; | |
| 684 | ✗ | int y_bot = cy_uv + half_h_uv; | |
| 685 | ✗ | if (y_top >= 0 && y_top < limit_showheight_uv) { | |
| 686 | ✗ | dstpU[x + y_top * pitchUV] = u_val; | |
| 687 | ✗ | dstpV[x + y_top * pitchUV] = v_val; | |
| 688 | } | ||
| 689 | ✗ | if (y_bot >= 0 && y_bot < limit_showheight_uv) { | |
| 690 | ✗ | dstpU[x + y_bot * pitchUV] = u_val; | |
| 691 | ✗ | dstpV[x + y_bot * pitchUV] = v_val; | |
| 692 | } | ||
| 693 | } | ||
| 694 | |||
| 695 | // Draw vertical left/right edges (chroma) | ||
| 696 | ✗ | for (int y = cy_uv - half_h_uv; y <= cy_uv + half_h_uv; y++) { | |
| 697 | ✗ | if (y < 0 || y >= limit_showheight_uv) continue; | |
| 698 | ✗ | int x_l = cx_uv - half_w_uv; | |
| 699 | ✗ | int x_r = cx_uv + half_w_uv; | |
| 700 | ✗ | if (x_l >= 0 && x_l < limit_showwidth_uv) { | |
| 701 | ✗ | dstpU[x_l + y * pitchUV] = u_val; | |
| 702 | ✗ | dstpV[x_l + y * pitchUV] = v_val; | |
| 703 | } | ||
| 704 | ✗ | if (x_r >= 0 && x_r < limit_showwidth_uv) { | |
| 705 | ✗ | dstpU[x_r + y * pitchUV] = u_val; | |
| 706 | ✗ | dstpV[x_r + y * pitchUV] = v_val; | |
| 707 | } | ||
| 708 | } | ||
| 709 | ✗ | } | |
| 710 | |||
| 711 | |||
| 712 | // This draws only on luma | ||
| 713 | template<typename pixel_t> | ||
| 714 | ✗ | static void DrawRadialLine(pixel_t* dstp, int pitch, int limit, int show_bit_shift, | |
| 715 | double angle_deg, pixel_t val) | ||
| 716 | { | ||
| 717 | ✗ | double angle_rad = angle_deg * M_PI / 180.0; | |
| 718 | ✗ | double R = 124.9 * (1 << show_bit_shift); // same as innerF * scale | |
| 719 | // Step along the radius | ||
| 720 | ✗ | int steps = (int)(R * 1.5); | |
| 721 | ✗ | for (int s = 0; s < steps; s++) { | |
| 722 | ✗ | double t = (double)s / steps; | |
| 723 | ✗ | int x = (int)(limit + t * R * cos(angle_rad) + 0.5); | |
| 724 | ✗ | int y = (int)(limit - t * R * sin(angle_rad) + 0.5); // V is flipped | |
| 725 | ✗ | if (x >= 0 && x <= 2 * limit && y >= 0 && y <= 2 * limit) | |
| 726 | ✗ | dstp[x + y * pitch] = val; | |
| 727 | } | ||
| 728 | ✗ | } | |
| 729 | |||
| 730 | // Set to black, alpha to 0. | ||
| 731 | template<typename pixel_t> | ||
| 732 | 1 | static void ClearArea( | |
| 733 | uint8_t* dstp, uint8_t* dstp_u, uint8_t* dstp_v, uint8_t* dstp_a, | ||
| 734 | int width, int widthUV, | ||
| 735 | int pitch, int pitchUV, int pitchA, | ||
| 736 | int height, int heightUV, int heightA, | ||
| 737 | int bits_per_pixel, bool full_range) | ||
| 738 | { | ||
| 739 | pixel_t black, middle_chroma, alpha; | ||
| 740 | if constexpr (std::is_integral<pixel_t>::value) { | ||
| 741 |
1/4void ClearArea<unsigned char>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
void ClearArea<unsigned short>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
|
1 | black = full_range ? 0 : (pixel_t)(16 << (bits_per_pixel - 8)); |
| 742 | 1 | middle_chroma = (pixel_t)(128 << (bits_per_pixel - 8)); | |
| 743 | 1 | alpha = 0; | |
| 744 | } | ||
| 745 | else { | ||
| 746 | ✗ | black = full_range ? 0.0f : 16.0f / 255.0f; | |
| 747 | ✗ | middle_chroma = 0.0f; | |
| 748 | ✗ | alpha = 0.0f; | |
| 749 | } | ||
| 750 | |||
| 751 | // Y | ||
| 752 |
2/6void ClearArea<float>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 16 → 6 not taken.
✗ Branch 16 → 17 not taken.
void ClearArea<unsigned char>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✓ Branch 16 → 6 taken 256 times.
✓ Branch 16 → 17 taken 1 time.
void ClearArea<unsigned short>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 16 → 6 not taken.
✗ Branch 16 → 17 not taken.
|
257 | for (int y = 0; y < height; y++) { |
| 753 | 512 | std::fill_n((pixel_t*)(dstp + y * pitch), width, black); | |
| 754 | } | ||
| 755 | // UV | ||
| 756 |
2/6void ClearArea<float>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 37 → 18 not taken.
✗ Branch 37 → 38 not taken.
void ClearArea<unsigned char>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✓ Branch 37 → 18 taken 128 times.
✓ Branch 37 → 38 taken 1 time.
void ClearArea<unsigned short>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 37 → 18 not taken.
✗ Branch 37 → 38 not taken.
|
129 | for (int y = 0; y < heightUV; y++) { |
| 757 | 128 | std::fill_n((pixel_t*)(dstp_u + y * pitchUV), widthUV, middle_chroma); | |
| 758 | 256 | std::fill_n((pixel_t*)(dstp_v + y * pitchUV), widthUV, middle_chroma); | |
| 759 | } | ||
| 760 | // Alpha, dimensions same as luma | ||
| 761 | // heightA is zero if no alpha plane | ||
| 762 |
1/6void ClearArea<float>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 49 → 39 not taken.
✗ Branch 49 → 50 not taken.
void ClearArea<unsigned char>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 49 → 39 not taken.
✓ Branch 49 → 50 taken 1 time.
void ClearArea<unsigned short>(unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 49 → 39 not taken.
✗ Branch 49 → 50 not taken.
|
1 | for (int y = 0; y < heightA; y++) { |
| 763 | ✗ | std::fill_n((pixel_t*)(dstp_a + y * pitchA), width, alpha); | |
| 764 | } | ||
| 765 | 1 | } | |
| 766 | |||
| 767 | // Common prelude for Color and Color2 modes. | ||
| 768 | // Allocates dst, optionally clears the below-source area, copies source planes. | ||
| 769 | // Returns the allocated dst frame; populates panel pointer offsets.ű | ||
| 770 | // Full_range flag is filled in constructor, not per frame | ||
| 771 | 2 | PVideoFrame Histogram::VectorscopePrelude( | |
| 772 | int n, IScriptEnvironment* env, | ||
| 773 | PVideoFrame& src, | ||
| 774 | // outputs: | ||
| 775 | int& dst_pitch, int& dst_height, | ||
| 776 | int& dst_pitchUV, int& dst_heightUV, | ||
| 777 | int& dst_pitchA, int& dst_heightA, | ||
| 778 | BYTE*& panel, BYTE*& panelU, BYTE*& panelV, BYTE*& panelA) | ||
| 779 | { | ||
| 780 |
2/4✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 126 not taken.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 124 not taken.
|
2 | src = child->GetFrame(n, env); |
| 781 | 2 | PVideoFrame dst = env->NewVideoFrameP(vi, &src); | |
| 782 | |||
| 783 |
1/2✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 127 not taken.
|
2 | BYTE *pdst = dst->GetWritePtr(); |
| 784 |
1/2✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 127 not taken.
|
2 | BYTE *pdstU = dst->GetWritePtr(PLANAR_U); |
| 785 |
1/2✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 127 not taken.
|
2 | BYTE *pdstV = dst->GetWritePtr(PLANAR_V); |
| 786 |
1/2✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 127 not taken.
|
2 | BYTE *pdstA = dst->GetWritePtr(PLANAR_A); |
| 787 | |||
| 788 |
1/2✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 127 not taken.
|
2 | dst_pitch = dst->GetPitch(); |
| 789 |
1/2✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 127 not taken.
|
2 | dst_pitchUV = dst->GetPitch(PLANAR_U); |
| 790 |
1/2✓ Branch 20 → 21 taken 2 times.
✗ Branch 20 → 127 not taken.
|
2 | dst_pitchA = dst->GetPitch(PLANAR_A); |
| 791 |
1/2✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 127 not taken.
|
2 | dst_height = dst->GetHeight(); |
| 792 |
1/2✓ Branch 24 → 25 taken 2 times.
✗ Branch 24 → 127 not taken.
|
2 | dst_heightUV = dst->GetHeight(PLANAR_U); |
| 793 |
1/2✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 127 not taken.
|
2 | dst_heightA = dst->GetHeight(PLANAR_A); |
| 794 | |||
| 795 | 2 | const bool has_alpha = dst_heightA > 0; | |
| 796 | |||
| 797 |
1/2✓ Branch 28 → 29 taken 2 times.
✗ Branch 28 → 127 not taken.
|
2 | const int src_width = src->GetRowSize() / pixelsize; |
| 798 |
1/2✓ Branch 30 → 31 taken 2 times.
✗ Branch 30 → 127 not taken.
|
2 | const int src_widthUV = src->GetRowSize(PLANAR_U) / pixelsize; |
| 799 |
1/2✓ Branch 32 → 33 taken 2 times.
✗ Branch 32 → 127 not taken.
|
2 | const int src_height = src->GetHeight(); |
| 800 |
1/2✓ Branch 34 → 35 taken 2 times.
✗ Branch 34 → 127 not taken.
|
2 | const int src_heightUV = src->GetHeight(PLANAR_U); |
| 801 | |||
| 802 | 2 | const int show_size = 1 << show_bits; | |
| 803 |
1/2✓ Branch 35 → 36 taken 2 times.
✗ Branch 35 → 127 not taken.
|
2 | const int show_size_w_uv = show_size >> vi.GetPlaneWidthSubsampling(PLANAR_U); |
| 804 |
1/2✓ Branch 36 → 37 taken 2 times.
✗ Branch 36 → 127 not taken.
|
2 | const int show_size_h_uv = show_size >> vi.GetPlaneHeightSubsampling(PLANAR_U); |
| 805 | |||
| 806 |
1/2✗ Branch 37 → 38 not taken.
✓ Branch 37 → 84 taken 2 times.
|
2 | if (keepsource) { |
| 807 | |||
| 808 | ✗ | if (src_height < dst_height) { | |
| 809 | // in case of Histogram area is higher than source, clear the area below source copy to black + A=0 | ||
| 810 | ✗ | auto pdst_start = pdst + src_height * dst_pitch; | |
| 811 | ✗ | auto pdstU_start = pdstU + src_heightUV * dst_pitchUV; | |
| 812 | ✗ | auto pdstV_start = pdstV + src_heightUV * dst_pitchUV; | |
| 813 | ✗ | auto pdstA_start = pdstA + src_height * dst_pitchA; | |
| 814 | ✗ | const int new_height = dst_height - src_height; | |
| 815 | ✗ | const int new_height_uv = dst_heightUV - src_heightUV; | |
| 816 | ✗ | const int new_height_a = has_alpha ? new_height : 0; | |
| 817 | |||
| 818 | ✗ | if (bits_per_pixel == 8) | |
| 819 | ✗ | ClearArea<uint8_t>(pdst_start, pdstU_start, pdstV_start, pdstA_start, | |
| 820 | src_width, src_widthUV, | ||
| 821 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 822 | new_height, new_height_uv, new_height_a, | ||
| 823 | ✗ | bits_per_pixel, full_range); | |
| 824 | ✗ | else if (bits_per_pixel <= 16) | |
| 825 | ✗ | ClearArea<uint16_t>(pdst_start, pdstU_start, pdstV_start, pdstA_start, | |
| 826 | src_width, src_widthUV, | ||
| 827 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 828 | new_height, new_height_uv, new_height_a, | ||
| 829 | ✗ | bits_per_pixel, full_range); | |
| 830 | else | ||
| 831 | ✗ | ClearArea<float>(pdst_start, pdstU_start, pdstV_start, pdstA_start, | |
| 832 | src_width, src_widthUV, | ||
| 833 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 834 | new_height, new_height_uv, new_height_a, | ||
| 835 | ✗ | bits_per_pixel, full_range); | |
| 836 | } | ||
| 837 | // copy source | ||
| 838 | ✗ | env->BitBlt(pdst, dst_pitch, src->GetReadPtr(), src->GetPitch(), src->GetRowSize(), src->GetHeight()); | |
| 839 | ✗ | env->BitBlt(pdstU, dst_pitchUV, src->GetReadPtr(PLANAR_U), src->GetPitch(PLANAR_U), src->GetRowSize(PLANAR_U), src->GetHeight(PLANAR_U)); | |
| 840 | ✗ | env->BitBlt(pdstV, dst_pitchUV, src->GetReadPtr(PLANAR_V), src->GetPitch(PLANAR_V), src->GetRowSize(PLANAR_V), src->GetHeight(PLANAR_V)); | |
| 841 | ✗ | if (has_alpha) | |
| 842 | ✗ | env->BitBlt(pdstA, dst_pitchA, src->GetReadPtr(PLANAR_A), src->GetPitch(PLANAR_A), src->GetRowSize(PLANAR_A), src->GetHeight(PLANAR_A)); | |
| 843 | } | ||
| 844 | |||
| 845 | // panel is with the offset into the histogram panel area (past the source copy) | ||
| 846 |
1/4✗ Branch 84 → 85 not taken.
✓ Branch 84 → 88 taken 2 times.
✗ Branch 86 → 87 not taken.
✗ Branch 86 → 127 not taken.
|
2 | panel = pdst + (keepsource ? src->GetRowSize() : 0); |
| 847 |
1/4✗ Branch 89 → 90 not taken.
✓ Branch 89 → 93 taken 2 times.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 127 not taken.
|
2 | panelU = pdstU + (keepsource ? src->GetRowSize(PLANAR_U) : 0); |
| 848 |
1/4✗ Branch 94 → 95 not taken.
✓ Branch 94 → 98 taken 2 times.
✗ Branch 96 → 97 not taken.
✗ Branch 96 → 127 not taken.
|
2 | panelV = pdstV + (keepsource ? src->GetRowSize(PLANAR_V) : 0); |
| 849 |
4/10✓ Branch 99 → 100 taken 2 times.
✗ Branch 99 → 109 not taken.
✓ Branch 101 → 102 taken 2 times.
✗ Branch 101 → 127 not taken.
✓ Branch 102 → 103 taken 2 times.
✗ Branch 102 → 109 not taken.
✗ Branch 103 → 104 not taken.
✓ Branch 103 → 107 taken 2 times.
✗ Branch 105 → 106 not taken.
✗ Branch 105 → 127 not taken.
|
2 | panelA = (pdstA && src->GetReadPtr(PLANAR_A)) ? (pdstA + (keepsource ? src->GetRowSize(PLANAR_A) : 0)) : nullptr; |
| 850 | |||
| 851 | // Clear below the histogram area (bottom right), if source is higher than histogram area. | ||
| 852 |
1/2✗ Branch 110 → 111 not taken.
✓ Branch 110 → 122 taken 2 times.
|
2 | if (src_height > show_size) { |
| 853 | ✗ | auto pdst_start = panel + show_size * dst_pitch; | |
| 854 | ✗ | auto pdstU_start = panelU + show_size_h_uv * dst_pitchUV; | |
| 855 | ✗ | auto pdstV_start = panelV + show_size_h_uv * dst_pitchUV; | |
| 856 | ✗ | auto pdstA_start = has_alpha ? panelA + show_size * dst_pitchA : nullptr; | |
| 857 | ✗ | const int new_height = dst_height - show_size; | |
| 858 | ✗ | const int new_height_uv = dst_heightUV - show_size_h_uv; | |
| 859 | ✗ | const int new_height_a = has_alpha ? new_height : 0; | |
| 860 | |||
| 861 | ✗ | if (bits_per_pixel == 8) | |
| 862 | ✗ | ClearArea<uint8_t>(pdst_start, pdstU_start, pdstV_start, pdstA_start, | |
| 863 | show_size, show_size_w_uv, | ||
| 864 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 865 | new_height, new_height_uv, new_height_a, | ||
| 866 | ✗ | bits_per_pixel, full_range); | |
| 867 | ✗ | else if (bits_per_pixel <= 16) | |
| 868 | ✗ | ClearArea<uint16_t>(pdst_start, pdstU_start, pdstV_start, pdstA_start, | |
| 869 | show_size, show_size_w_uv, | ||
| 870 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 871 | new_height, new_height_uv, new_height_a, | ||
| 872 | ✗ | bits_per_pixel, full_range); | |
| 873 | else | ||
| 874 | ✗ | ClearArea<float>(pdst_start, pdstU_start, pdstV_start, pdstA_start, | |
| 875 | show_size, show_size_w_uv, | ||
| 876 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 877 | new_height, new_height_uv, new_height_a, | ||
| 878 | ✗ | bits_per_pixel, full_range); | |
| 879 | } | ||
| 880 | |||
| 881 | 2 | return dst; | |
| 882 | ✗ | } | |
| 883 | |||
| 884 | ✗ | static void GetYUVFromMatrix( | |
| 885 | int matrix, // AVS_MATRIX_* enum value | ||
| 886 | double R, double G, double B, | ||
| 887 | double& dY, double& dU, double& dV) | ||
| 888 | { | ||
| 889 | double Kr, Kb; | ||
| 890 | ✗ | if (!GetKrKb(matrix, Kr, Kb)) { | |
| 891 | // fallback to BT.601 | ||
| 892 | ✗ | Kr = 0.299; Kb = 0.114; | |
| 893 | } | ||
| 894 | ✗ | double Kg = 1.0 - Kr - Kb; | |
| 895 | ✗ | dY = Kr * R + Kg * G + Kb * B; | |
| 896 | ✗ | dU = (B - dY) / (2.0 * (1.0 - Kb)); | |
| 897 | ✗ | dV = (R - dY) / (2.0 * (1.0 - Kr)); | |
| 898 | ✗ | } | |
| 899 | |||
| 900 | template<typename pixel_t> | ||
| 901 | 1 | static void DrawModeColor2_ClearVectorscopeArea(int bits_per_pixel, | |
| 902 | uint8_t* dstp8, uint8_t* dstp8_u, uint8_t* dstp8_v, uint8_t* dstp8_a, | ||
| 903 | int pitch, int pitchUV, int pitchA, | ||
| 904 | int height, int heightUV, int heightA, | ||
| 905 | int show_bits, int swidth, int sheight, | ||
| 906 | bool full_range | ||
| 907 | ) | ||
| 908 | { | ||
| 909 | 1 | const int show_size = (1 << show_bits); | |
| 910 | 1 | const int show_size_w_uv = show_size >> swidth; | |
| 911 | 1 | const int show_size_h_uv = show_size >> sheight; | |
| 912 | 1 | const bool has_alpha = heightA > 0; | |
| 913 |
1/6void DrawModeColor2_ClearVectorscopeArea<float>(int, unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
void DrawModeColor2_ClearVectorscopeArea<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
void DrawModeColor2_ClearVectorscopeArea<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
|
1 | const int show_size_a = has_alpha ? show_size : 0; |
| 914 | |||
| 915 | // Clear vectorscope area | ||
| 916 | |||
| 917 |
1/6void DrawModeColor2_ClearVectorscopeArea<float>(int, unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 7 not taken.
void DrawModeColor2_ClearVectorscopeArea<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 7 not taken.
void DrawModeColor2_ClearVectorscopeArea<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, int, int, int, int, int, bool):
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 7 not taken.
|
1 | if (bits_per_pixel == 8) |
| 918 | 1 | ClearArea<uint8_t>(dstp8, dstp8_u, dstp8_v, dstp8_a, | |
| 919 | show_size, show_size_w_uv, // width | ||
| 920 | pitch, pitchUV, pitchA, | ||
| 921 | show_size, show_size_h_uv, show_size_a, // height | ||
| 922 | bits_per_pixel, full_range); | ||
| 923 | ✗ | else if (bits_per_pixel <= 16) | |
| 924 | ✗ | ClearArea<uint16_t>(dstp8, dstp8_u, dstp8_v, dstp8_a, | |
| 925 | show_size, show_size_w_uv, // width | ||
| 926 | pitch, pitchUV, pitchA, | ||
| 927 | show_size, show_size_h_uv, show_size_a, // height | ||
| 928 | bits_per_pixel, full_range); | ||
| 929 | else | ||
| 930 | ✗ | ClearArea<float>(dstp8, dstp8_u, dstp8_v, dstp8_a, | |
| 931 | show_size, show_size_w_uv, // width | ||
| 932 | pitch, pitchUV, pitchA, | ||
| 933 | show_size, show_size_h_uv, show_size_a, // height | ||
| 934 | bits_per_pixel, full_range); | ||
| 935 | 1 | } | |
| 936 | |||
| 937 | template<typename pixel_t> | ||
| 938 | 1 | static void DrawModeColor2_draw_graticule(int bits_per_pixel, uint8_t* dstp8, int pitch, int height, int show_bits) { | |
| 939 | |||
| 940 | 1 | pitch /= sizeof(pixel_t); | |
| 941 | 1 | pixel_t* dstp = reinterpret_cast<pixel_t*>(dstp8); | |
| 942 | |||
| 943 | pixel_t luma128; | ||
| 944 | |||
| 945 | if constexpr (std::is_integral<pixel_t>::value) { | ||
| 946 | 1 | luma128 = (pixel_t)(128 << (bits_per_pixel - 8)); | |
| 947 | } | ||
| 948 | else { | ||
| 949 | ✗ | luma128 = c8tof(128); | |
| 950 | } | ||
| 951 | |||
| 952 | 1 | const int show_bit_shift = show_bits - 8; | |
| 953 | |||
| 954 | // 16 240 | ||
| 955 | // 16 +---------+ | ||
| 956 | // 17 | | | ||
| 957 | // .. | | | ||
| 958 | // 239 | | | ||
| 959 | // 240 +---------+ | ||
| 960 | |||
| 961 | // plot valid grey ccir601 square | ||
| 962 | 1 | const int size = 1 + ((240 - 16) << show_bit_shift); // original 8 bit: 225 0+/-112 | |
| 963 | 1 | std::fill_n(&dstp[(16 << show_bit_shift) * pitch + (16 << show_bit_shift)], size, luma128); | |
| 964 | 1 | std::fill_n(&dstp[(240 << show_bit_shift) * pitch + (16 << show_bit_shift)], size, luma128); | |
| 965 | |||
| 966 | // vertical lines left and right side | ||
| 967 |
2/6void DrawModeColor2_draw_graticule<float>(int, unsigned char*, int, int, int):
✗ Branch 24 → 23 not taken.
✗ Branch 24 → 25 not taken.
void DrawModeColor2_draw_graticule<unsigned char>(int, unsigned char*, int, int, int):
✓ Branch 22 → 21 taken 223 times.
✓ Branch 22 → 23 taken 1 time.
void DrawModeColor2_draw_graticule<unsigned short>(int, unsigned char*, int, int, int):
✗ Branch 22 → 21 not taken.
✗ Branch 22 → 23 not taken.
|
224 | for (int y = 1 + (16 << show_bit_shift); y < 240 << show_bit_shift; y++) { |
| 968 | 223 | dstp[(16 << show_bit_shift) + y * pitch] = luma128; | |
| 969 | 223 | dstp[(240 << show_bit_shift) + y * pitch] = luma128; | |
| 970 | } | ||
| 971 | 1 | } | |
| 972 | |||
| 973 | template<typename pixel_t> | ||
| 974 | ✗ | static void DrawModeColor2_draw_circle(int bits_per_pixel, uint8_t* dstp8, uint8_t* dstp8_u, uint8_t* dstp8_v, | |
| 975 | int pitch, int pitchUV, int height, int heightUV, double innerF, | ||
| 976 | int show_bits, int swidth, int sheight, int* deg15c, int* deg15s // precalculated array | ||
| 977 | ) | ||
| 978 | { | ||
| 979 | |||
| 980 | ✗ | pitch /= sizeof(pixel_t); | |
| 981 | ✗ | pitchUV /= sizeof(pixel_t); | |
| 982 | ✗ | pixel_t* dstp = reinterpret_cast<pixel_t*>(dstp8); | |
| 983 | ✗ | pixel_t* dstp_u = reinterpret_cast<pixel_t*>(dstp8_u); | |
| 984 | ✗ | pixel_t* dstp_v = reinterpret_cast<pixel_t*>(dstp8_v); | |
| 985 | |||
| 986 | // possible to display >8 bit data stuffed into 8 bit size | ||
| 987 | ✗ | const int show_bit_shift = show_bits - 8; | |
| 988 | |||
| 989 | // plot circles | ||
| 990 | |||
| 991 | // here we do not bother with matrix-correct color representation. | ||
| 992 | |||
| 993 | // six hues in the color-wheel: | ||
| 994 | // LC[3j,3j+1,3j+2], RC[3j,3j+1,3j+2] in YRange[j]+1 and YRange[j+1] | ||
| 995 | ✗ | int YRange[8] = { -1, 26, 104, 127, 191, 197, 248, 256 }; | |
| 996 | // 2x green, 2x yellow, 3x red | ||
| 997 | ✗ | int LC[21] = { | |
| 998 | 145, 54, 34, | ||
| 999 | 145, 54, 34, | ||
| 1000 | 210, 16, 146, | ||
| 1001 | 210, 16, 146, | ||
| 1002 | 81, 90, 240, | ||
| 1003 | 81, 90, 240, | ||
| 1004 | 81, 90, 240 | ||
| 1005 | }; | ||
| 1006 | // cyan, 4x blue, magenta, red: | ||
| 1007 | ✗ | int RC[21] = { | |
| 1008 | 170, 166, 16, | ||
| 1009 | 41, 240, 110, | ||
| 1010 | 41, 240, 110, | ||
| 1011 | 41, 240, 110, | ||
| 1012 | 41, 240, 110, | ||
| 1013 | 106, 202, 222, | ||
| 1014 | 81, 90, 240 | ||
| 1015 | }; | ||
| 1016 | ✗ | float LC_f[21] = { | |
| 1017 | ✗ | c8tof(145), uv8tof(54), uv8tof(34), | |
| 1018 | ✗ | c8tof(145), uv8tof(54), uv8tof(34), | |
| 1019 | ✗ | c8tof(210), uv8tof(16), uv8tof(146), | |
| 1020 | ✗ | c8tof(210), uv8tof(16), uv8tof(146), | |
| 1021 | ✗ | c8tof(81), uv8tof(90), uv8tof(240), | |
| 1022 | ✗ | c8tof(81), uv8tof(90), uv8tof(240), | |
| 1023 | ✗ | c8tof(81), uv8tof(90), uv8tof(240) | |
| 1024 | }; | ||
| 1025 | // cyan, 4x blue, magenta, red: | ||
| 1026 | ✗ | float RC_f[21] = { | |
| 1027 | ✗ | c8tof(170), uv8tof(166), uv8tof(16), | |
| 1028 | ✗ | c8tof(41), uv8tof(240), uv8tof(110), | |
| 1029 | ✗ | c8tof(41), uv8tof(240), uv8tof(110), | |
| 1030 | ✗ | c8tof(41), uv8tof(240), uv8tof(110), | |
| 1031 | ✗ | c8tof(41), uv8tof(240), uv8tof(110), | |
| 1032 | ✗ | c8tof(106), uv8tof(202), uv8tof(222), | |
| 1033 | ✗ | c8tof(81), uv8tof(90), uv8tof(240) | |
| 1034 | }; | ||
| 1035 | |||
| 1036 | // example boundary of cyan and blue: | ||
| 1037 | // red = min(r,g,b), blue if g < 2/3 b, green if b < 2/3 g. | ||
| 1038 | // cyan between green and blue. | ||
| 1039 | // thus boundary of cyan and blue at (r,g,b) = (0,170,255), since 2/3*255 = 170. | ||
| 1040 | // => yuv = (127,190,47); hue = -52 degr; sat = 103 | ||
| 1041 | // => u'v' = (207,27) (same hue, sat=128) | ||
| 1042 | // similar for the other hues. | ||
| 1043 | // luma | ||
| 1044 | |||
| 1045 | // innerF is used for 15 degree markers as well | ||
| 1046 | ✗ | double thicknessF = 1.5; | |
| 1047 | ✗ | double oneOverThicknessF = 1.0 / thicknessF; | |
| 1048 | ✗ | double outerF = innerF + thicknessF * 2.0; | |
| 1049 | ✗ | double centerF = innerF + thicknessF; | |
| 1050 | ✗ | int64_t innerSq = (int64_t)(innerF * innerF * (1 << (show_bit_shift * 2))); | |
| 1051 | ✗ | int64_t outerSq = (int64_t)(outerF * outerF * (1 << (show_bit_shift * 2))); | |
| 1052 | ✗ | int activeY = 0; | |
| 1053 | ✗ | int xRounder = (1 << swidth) / 2; | |
| 1054 | ✗ | int yRounder = (1 << sheight) / 2; | |
| 1055 | |||
| 1056 | ✗ | const int limit = (1 << (show_bits - 1)) - 1; | |
| 1057 | ✗ | const int limit_showwidth = (1 << show_bits) - 1; | |
| 1058 | ✗ | for (int y = -limit; y < limit + 1; y++) { | |
| 1059 | ✗ | if (y + limit > YRange[activeY + 1] << show_bit_shift) | |
| 1060 | ✗ | activeY++; | |
| 1061 | ✗ | for (int x = -limit; x <= 0; x++) { | |
| 1062 | ✗ | int64_t distSq = x * x + y * y; | |
| 1063 | ✗ | if (distSq <= outerSq && distSq >= innerSq) { | |
| 1064 | |||
| 1065 | if constexpr (std::is_integral<pixel_t>::value) { | ||
| 1066 | ✗ | const int factorshift = (bits_per_pixel - 8); | |
| 1067 | ✗ | const int MAXINTERP = 256; | |
| 1068 | ✗ | double dist = fabs(sqrt((double)distSq * (1.0 / (1 << (2 * show_bit_shift)))) - centerF); | |
| 1069 | ✗ | int interp = (int)(256.0f - (255.9f * (oneOverThicknessF * dist))); | |
| 1070 | // 255.9 is to account for float inprecision, which could cause underflow. | ||
| 1071 | |||
| 1072 | ✗ | int xP = limit + x; | |
| 1073 | ✗ | int yP = limit + y; | |
| 1074 | |||
| 1075 | ✗ | dstp[xP + yP * pitch] = | |
| 1076 | ✗ | (pixel_t)((interp * (LC[3 * activeY] << factorshift)) >> 8); // left upper half | |
| 1077 | |||
| 1078 | ✗ | dstp[limit_showwidth - xP + yP * pitch] = | |
| 1079 | ✗ | (pixel_t)((interp * (RC[3 * activeY] << factorshift)) >> 8); // right upper half | |
| 1080 | |||
| 1081 | ✗ | xP = (xP + xRounder) >> swidth; | |
| 1082 | ✗ | yP = (yP + yRounder) >> sheight; | |
| 1083 | |||
| 1084 | ✗ | interp = min(MAXINTERP, interp); | |
| 1085 | ✗ | int invInt = (MAXINTERP - interp); | |
| 1086 | |||
| 1087 | int p_uv; | ||
| 1088 | ✗ | p_uv = xP + yP * pitchUV; | |
| 1089 | ✗ | dstp_u[p_uv] = (pixel_t)((dstp_u[p_uv] * invInt + interp * (LC[3 * activeY + 1] << factorshift)) >> 8); // left half | |
| 1090 | ✗ | dstp_v[p_uv] = (pixel_t)((dstp_v[p_uv] * invInt + interp * (LC[3 * activeY + 2] << factorshift)) >> 8); // left half | |
| 1091 | |||
| 1092 | ✗ | xP = ((limit_showwidth) >> swidth) - xP; | |
| 1093 | ✗ | p_uv = xP + yP * pitchUV; | |
| 1094 | |||
| 1095 | ✗ | dstp_u[p_uv] = (pixel_t)((dstp_u[p_uv] * invInt + interp * (RC[3 * activeY + 1] << factorshift)) >> 8); // right half | |
| 1096 | ✗ | dstp_v[p_uv] = (pixel_t)((dstp_v[p_uv] * invInt + interp * (RC[3 * activeY + 2] << factorshift)) >> 8); // right half | |
| 1097 | } | ||
| 1098 | else { | ||
| 1099 | // 32 bit float | ||
| 1100 | ✗ | const float MAXINTERP = 1.0f; | |
| 1101 | ✗ | double dist = fabs(sqrt((double)distSq * (1.0 / (1 << (2 * show_bit_shift)))) - centerF); | |
| 1102 | ✗ | float interp = (float)(1.0 - 0.9999 * (oneOverThicknessF * dist)); | |
| 1103 | // 255.9 is to account for float inprecision, which could cause underflow. | ||
| 1104 | |||
| 1105 | ✗ | int xP = limit + x; | |
| 1106 | ✗ | int yP = limit + y; | |
| 1107 | |||
| 1108 | ✗ | dstp[xP + yP * pitch] = | |
| 1109 | ✗ | (pixel_t)(interp * LC_f[3 * activeY]); // left upper half | |
| 1110 | |||
| 1111 | ✗ | dstp[limit_showwidth - xP + yP * pitch] = | |
| 1112 | ✗ | (pixel_t)(interp * RC_f[3 * activeY]); // right upper half | |
| 1113 | |||
| 1114 | ✗ | xP = (xP + xRounder) >> swidth; | |
| 1115 | ✗ | yP = (yP + yRounder) >> sheight; | |
| 1116 | |||
| 1117 | ✗ | interp = min(MAXINTERP, interp); | |
| 1118 | ✗ | float invInt = (MAXINTERP - interp); | |
| 1119 | |||
| 1120 | int p_uv; | ||
| 1121 | ✗ | p_uv = xP + yP * pitchUV; | |
| 1122 | ✗ | dstp_u[p_uv] = (pixel_t)(dstp_u[p_uv] * invInt + interp * LC_f[3 * activeY + 1]); // left half | |
| 1123 | ✗ | dstp_v[p_uv] = (pixel_t)(dstp_v[p_uv] * invInt + interp * LC_f[3 * activeY + 2]); // left half | |
| 1124 | |||
| 1125 | ✗ | xP = ((limit_showwidth) >> swidth) - xP; | |
| 1126 | |||
| 1127 | ✗ | p_uv = xP + yP * pitchUV; | |
| 1128 | ✗ | dstp_u[p_uv] = (pixel_t)(dstp_u[p_uv] * invInt + interp * RC_f[3 * activeY + 1]); // right half | |
| 1129 | ✗ | dstp_v[p_uv] = (pixel_t)(dstp_v[p_uv] * invInt + interp * RC_f[3 * activeY + 2]); // right half | |
| 1130 | } | ||
| 1131 | } | ||
| 1132 | } | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | // and the 15 degree markers (same as innerF) | ||
| 1136 | // plot white 15 degree marks | ||
| 1137 | ✗ | for (int i = 0; i < 24; i++) { | |
| 1138 | if constexpr (sizeof(pixel_t) == 1) | ||
| 1139 | ✗ | dstp[deg15c[i] + deg15s[i] * pitch] = 235; // 235: Y-maxluma | |
| 1140 | else if constexpr (sizeof(pixel_t) == 2) | ||
| 1141 | ✗ | dstp[deg15c[i] + deg15s[i] * pitch] = 235 << (bits_per_pixel - 8); // 235: Y-maxluma | |
| 1142 | else // if constexpr (sizeof(pixel_t) == 4) | ||
| 1143 | ✗ | dstp[deg15c[i] + deg15s[i] * pitch] = c8tof(235); // 235: Y-maxluma | |
| 1144 | } | ||
| 1145 | |||
| 1146 | ✗ | } | |
| 1147 | |||
| 1148 | |||
| 1149 | template<typename pixel_t> | ||
| 1150 | 1 | static void do_vectorscope_color2( | |
| 1151 | pixel_t* pdstb, pixel_t* pdstbU, pixel_t* pdstbV, | ||
| 1152 | const pixel_t* pY, const pixel_t* pU, const pixel_t* pV, | ||
| 1153 | int dst_pitch, int dst_pitchUV, | ||
| 1154 | int src_pitch, int src_pitchUV, | ||
| 1155 | int src_widthUV, int src_heightUV, | ||
| 1156 | int swidth, int sheight, | ||
| 1157 | int show_bits, | ||
| 1158 | int bits_per_pixel, | ||
| 1159 | bits_conv_constants& d_chroma, | ||
| 1160 | bool full_range | ||
| 1161 | ) | ||
| 1162 | { | ||
| 1163 | // 32 bit float Vectorscope is simulated after a 16 bit conversion | ||
| 1164 |
1/6void do_vectorscope_color2<float>(float*, float*, float*, float const*, float const*, float const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
void do_vectorscope_color2<unsigned char>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
void do_vectorscope_color2<unsigned short>(unsigned short*, unsigned short*, unsigned short*, unsigned short const*, unsigned short const*, unsigned short const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
|
1 | const int shift = bits_per_pixel == 32 ? (16 - show_bits) /*n/a*/ : (bits_per_pixel - show_bits); |
| 1165 | 1 | const int max_pos = (1 << show_bits) - 1; | |
| 1166 | 1 | auto src_pitchY_chromacorr = (src_pitch << sheight); | |
| 1167 | |||
| 1168 | if constexpr (sizeof(pixel_t) == 4) { | ||
| 1169 | // ===== FLOAT PATH ===== | ||
| 1170 | ✗ | const float mul_factor = d_chroma.mul_factor; | |
| 1171 | ✗ | const float dst_offset = d_chroma.dst_offset; | |
| 1172 | |||
| 1173 | ✗ | for (int y = 0; y < src_heightUV; y++) { | |
| 1174 | ✗ | for (int x = 0; x < src_widthUV; x++) { | |
| 1175 | ✗ | const float uval_f = max(-0.5f, min(0.5f, pU[x])); | |
| 1176 | ✗ | const float vval_f = max(-0.5f, min(0.5f, pV[x])); | |
| 1177 | |||
| 1178 | ✗ | int uval_posindex = (int)(uval_f * mul_factor + dst_offset + 0.5f); | |
| 1179 | ✗ | int vval_posindex = (int)(vval_f * mul_factor + dst_offset + 0.5f); | |
| 1180 | ✗ | uval_posindex = max(0, min(max_pos, uval_posindex)); | |
| 1181 | ✗ | vval_posindex = max(0, min(max_pos, vval_posindex)); | |
| 1182 | |||
| 1183 | ✗ | pdstb[uval_posindex + vval_posindex * dst_pitch] = pY[x << swidth]; | |
| 1184 | ✗ | pdstbU[(uval_posindex >> swidth) + (vval_posindex >> sheight) * dst_pitchUV] = uval_f; | |
| 1185 | ✗ | pdstbV[(uval_posindex >> swidth) + (vval_posindex >> sheight) * dst_pitchUV] = vval_f; | |
| 1186 | } | ||
| 1187 | ✗ | pY += src_pitchY_chromacorr; | |
| 1188 | ✗ | pU += src_pitchUV; | |
| 1189 | ✗ | pV += src_pitchUV; | |
| 1190 | } | ||
| 1191 | } | ||
| 1192 | else { | ||
| 1193 | // ===== INTEGER PATH ===== | ||
| 1194 | 1 | const int max_value = (1 << bits_per_pixel) - 1; | |
| 1195 | |||
| 1196 | // Split into 3 optimized paths based on shift and range | ||
| 1197 | // When shift != 0, that is the dispay bit depth is different from source bit depth, we do conversion | ||
| 1198 | // - full range: use conversion constants | ||
| 1199 | // - limited range: either by downshifting or upshifting. | ||
| 1200 | // E.g. displaying 10 bit data on a 8 bit grid, or displaying 8 bit data on a 10 bit grid. | ||
| 1201 | // We need to convert the chroma values to the display bit depth, taking into account the limited/full range and the shift. | ||
| 1202 | |||
| 1203 |
1/4void do_vectorscope_color2<unsigned char>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 16 not taken.
void do_vectorscope_color2<unsigned short>(unsigned short*, unsigned short*, unsigned short*, unsigned short const*, unsigned short const*, unsigned short const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 16 not taken.
|
1 | if (shift == 0) { |
| 1204 | // ===== FAST PATH: No scaling needed ===== | ||
| 1205 |
2/4void do_vectorscope_color2<unsigned char>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✓ Branch 15 → 7 taken 2 times.
✓ Branch 15 → 52 taken 1 time.
void do_vectorscope_color2<unsigned short>(unsigned short*, unsigned short*, unsigned short*, unsigned short const*, unsigned short const*, unsigned short const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✗ Branch 15 → 7 not taken.
✗ Branch 15 → 52 not taken.
|
3 | for (int y = 0; y < src_heightUV; y++) { |
| 1206 |
2/4void do_vectorscope_color2<unsigned char>(unsigned char*, unsigned char*, unsigned char*, unsigned char const*, unsigned char const*, unsigned char const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✓ Branch 13 → 8 taken 4 times.
✓ Branch 13 → 14 taken 2 times.
void do_vectorscope_color2<unsigned short>(unsigned short*, unsigned short*, unsigned short*, unsigned short const*, unsigned short const*, unsigned short const*, int, int, int, int, int, int, int, int, int, int, bits_conv_constants&, bool):
✗ Branch 13 → 8 not taken.
✗ Branch 13 → 14 not taken.
|
6 | for (int x = 0; x < src_widthUV; x++) { |
| 1207 | 4 | const int uval = max(0, min(max_value, (int)pU[x])); | |
| 1208 | 4 | const int vval = max(0, min(max_value, (int)pV[x])); | |
| 1209 | |||
| 1210 | 4 | pdstb[uval + vval * dst_pitch] = pY[x << swidth]; | |
| 1211 | 4 | pdstbU[(uval >> swidth) + (vval >> sheight) * dst_pitchUV] = (pixel_t)uval; | |
| 1212 | 4 | pdstbV[(uval >> swidth) + (vval >> sheight) * dst_pitchUV] = (pixel_t)vval; | |
| 1213 | } | ||
| 1214 | 2 | pY += src_pitchY_chromacorr; | |
| 1215 | 2 | pU += src_pitchUV; | |
| 1216 | 2 | pV += src_pitchUV; | |
| 1217 | } | ||
| 1218 | } | ||
| 1219 | ✗ | else if (full_range) { | |
| 1220 | // ===== FULL RANGE PATH: Use conversion constants ===== | ||
| 1221 | ✗ | const float mul_factor = d_chroma.mul_factor; | |
| 1222 | ✗ | const int src_offset_i = d_chroma.src_offset_i; | |
| 1223 | ✗ | const float dst_offset = d_chroma.dst_offset; | |
| 1224 | |||
| 1225 | ✗ | for (int y = 0; y < src_heightUV; y++) { | |
| 1226 | ✗ | for (int x = 0; x < src_widthUV; x++) { | |
| 1227 | ✗ | const int uval = max(0, min(max_value, (int)pU[x])); | |
| 1228 | ✗ | const int vval = max(0, min(max_value, (int)pV[x])); | |
| 1229 | |||
| 1230 | ✗ | int uval_posindex = (int)((uval - src_offset_i) * mul_factor + dst_offset + 0.5f); | |
| 1231 | ✗ | int vval_posindex = (int)((vval - src_offset_i) * mul_factor + dst_offset + 0.5f); | |
| 1232 | ✗ | uval_posindex = max(0, min(max_pos, uval_posindex)); | |
| 1233 | ✗ | vval_posindex = max(0, min(max_pos, vval_posindex)); | |
| 1234 | |||
| 1235 | ✗ | pdstb[uval_posindex + vval_posindex * dst_pitch] = pY[x << swidth]; | |
| 1236 | ✗ | pdstbU[(uval_posindex >> swidth) + (vval_posindex >> sheight) * dst_pitchUV] = (pixel_t)uval; | |
| 1237 | ✗ | pdstbV[(uval_posindex >> swidth) + (vval_posindex >> sheight) * dst_pitchUV] = (pixel_t)vval; | |
| 1238 | } | ||
| 1239 | ✗ | pY += src_pitchY_chromacorr; | |
| 1240 | ✗ | pU += src_pitchUV; | |
| 1241 | ✗ | pV += src_pitchUV; | |
| 1242 | } | ||
| 1243 | } | ||
| 1244 | else { | ||
| 1245 | // ===== LIMITED RANGE PATH: Simple bit shift ===== | ||
| 1246 | ✗ | if (shift > 0) { | |
| 1247 | // Downshift (e.g., 10-bit -> 8-bit display) | ||
| 1248 | ✗ | const int rounder = 1 << (shift - 1); | |
| 1249 | ✗ | for (int y = 0; y < src_heightUV; y++) { | |
| 1250 | ✗ | for (int x = 0; x < src_widthUV; x++) { | |
| 1251 | ✗ | const int uval = max(0, min(max_value, (int)pU[x])); | |
| 1252 | ✗ | const int vval = max(0, min(max_value, (int)pV[x])); | |
| 1253 | |||
| 1254 | ✗ | const int uval_posindex = (uval + rounder) >> shift; | |
| 1255 | ✗ | const int vval_posindex = (vval + rounder) >> shift; | |
| 1256 | |||
| 1257 | ✗ | pdstb[uval_posindex + vval_posindex * dst_pitch] = pY[x << swidth]; | |
| 1258 | ✗ | pdstbU[(uval_posindex >> swidth) + (vval_posindex >> sheight) * dst_pitchUV] = (pixel_t)uval; | |
| 1259 | ✗ | pdstbV[(uval_posindex >> swidth) + (vval_posindex >> sheight) * dst_pitchUV] = (pixel_t)vval; | |
| 1260 | } | ||
| 1261 | ✗ | pY += src_pitchY_chromacorr; | |
| 1262 | ✗ | pU += src_pitchUV; | |
| 1263 | ✗ | pV += src_pitchUV; | |
| 1264 | } | ||
| 1265 | } | ||
| 1266 | else { | ||
| 1267 | // Upshift (e.g., 8-bit -> 10-bit display) | ||
| 1268 | ✗ | const int neg_shift = -shift; | |
| 1269 | ✗ | for (int y = 0; y < src_heightUV; y++) { | |
| 1270 | ✗ | for (int x = 0; x < src_widthUV; x++) { | |
| 1271 | ✗ | const int uval = max(0, min(max_value, (int)pU[x])); | |
| 1272 | ✗ | const int vval = max(0, min(max_value, (int)pV[x])); | |
| 1273 | |||
| 1274 | ✗ | const int uval_posindex = uval << neg_shift; | |
| 1275 | ✗ | const int vval_posindex = vval << neg_shift; | |
| 1276 | |||
| 1277 | ✗ | pdstb[uval_posindex + vval_posindex * dst_pitch] = pY[x << swidth]; | |
| 1278 | ✗ | pdstbU[(uval_posindex >> swidth) + (vval_posindex >> sheight) * dst_pitchUV] = (pixel_t)uval; | |
| 1279 | ✗ | pdstbV[(uval_posindex >> swidth) + (vval_posindex >> sheight) * dst_pitchUV] = (pixel_t)vval; | |
| 1280 | } | ||
| 1281 | ✗ | pY += src_pitchY_chromacorr; | |
| 1282 | ✗ | pU += src_pitchUV; | |
| 1283 | ✗ | pV += src_pitchUV; | |
| 1284 | } | ||
| 1285 | } | ||
| 1286 | } | ||
| 1287 | } | ||
| 1288 | 1 | } | |
| 1289 | |||
| 1290 | template<typename pixel_t> | ||
| 1291 | 2 | static void Draw_VectorScope_circle_targets_axes(int bits_per_pixel, | |
| 1292 | uint8_t* dstp8, uint8_t* dstp8_u, uint8_t* dstp8_v, int pitch, int pitchUV, int height, int heightUV, | ||
| 1293 | double innerF, | ||
| 1294 | int show_bits, int swidth, int sheight, | ||
| 1295 | histogram_color2_params& params, | ||
| 1296 | ConversionMatrix& conv_matrix, | ||
| 1297 | int matrix, // AVS_MATRIX_* enum value | ||
| 1298 | bits_conv_constants& conv_consts, | ||
| 1299 | bool full_range, int* deg15c, int* deg15s) | ||
| 1300 | { | ||
| 1301 | |||
| 1302 |
1/6void Draw_VectorScope_circle_targets_axes<float>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
void Draw_VectorScope_circle_targets_axes<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
void Draw_VectorScope_circle_targets_axes<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
|
2 | if (params.circle) { |
| 1303 | // also the 15 deg marks points | ||
| 1304 | ✗ | DrawModeColor2_draw_circle<pixel_t>(bits_per_pixel, | |
| 1305 | dstp8, dstp8_u, dstp8_v, | ||
| 1306 | pitch, pitchUV, | ||
| 1307 | height, heightUV, | ||
| 1308 | innerF, | ||
| 1309 | show_bits, swidth, sheight, | ||
| 1310 | deg15c, deg15s | ||
| 1311 | ); | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | // Used for the colorUV square positions, calculated from linear RGB | ||
| 1315 | 2 | bits_conv_constants conv_consts_fullrange_float_origin; | |
| 1316 |
1/6void Draw_VectorScope_circle_targets_axes<float>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 26 not taken.
void Draw_VectorScope_circle_targets_axes<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 26 not taken.
void Draw_VectorScope_circle_targets_axes<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 26 not taken.
|
2 | get_bits_conv_constants(conv_consts_fullrange_float_origin, /*use_chroma=*/true, |
| 1317 | /*fulls=*/true, full_range, | ||
| 1318 | /*srcBitDepth=*/32, /*dstBitDepth=*/show_bits); | ||
| 1319 | |||
| 1320 | 2 | const int limit_showwidth = (1 << show_bits) - 1; | |
| 1321 | |||
| 1322 | 2 | pitch /= sizeof(pixel_t); | |
| 1323 | 2 | pitchUV /= sizeof(pixel_t); | |
| 1324 | 2 | pixel_t* dstp = reinterpret_cast<pixel_t*>(dstp8); | |
| 1325 | 2 | pixel_t* dstp_u = reinterpret_cast<pixel_t*>(dstp8_u); | |
| 1326 | 2 | pixel_t* dstp_v = reinterpret_cast<pixel_t*>(dstp8_v); | |
| 1327 | |||
| 1328 | // ===== -I AND +Q SIGNAL RGB VALUES FOR VECTORSCOPE GRATICULE ===== | ||
| 1329 | // These feed through the same matrix-aware make_yuv path as the color bar patches, | ||
| 1330 | // giving correct UV pixel coordinates for any matrix and any bit depth. | ||
| 1331 | // | ||
| 1332 | // Note: -I and +Q are analog NTSC test signals that don't map cleanly to digital RGB/YUV. | ||
| 1333 | // We maintain two separate specifications for backward compatibility: | ||
| 1334 | // | ||
| 1335 | // RGB-NATIVE: Lifted to studio black (code 16), broadcast-safe | ||
| 1336 | // Used when vectorscope processes RGB sources or when drawing RGB graticules | ||
| 1337 | // -I: RGB(16, 90, 130) at 8-bit → produces Y≈77 after matrix conversion | ||
| 1338 | // +Q: RGB(92, 16, 143) at 8-bit → produces Y≈63 after matrix conversion | ||
| 1339 | // | ||
| 1340 | // YUV-TARGETED: Zero-luma pure chroma definition | ||
| 1341 | // Used when vectorscope processes YUV sources | ||
| 1342 | // -I: Converts to Y=16, Cb=158, Cr=95 (legacy ColorBars YUV output) | ||
| 1343 | // +Q: Converts to Y=16, Cb=174, Cr=149 (legacy ColorBars YUV output) | ||
| 1344 | // Contains out-of-range RGB components (super-blacks) | ||
| 1345 | // | ||
| 1346 | // Note 2: These will not lay exactly on UV's 33° and 123° degree lines, since those | ||
| 1347 | // angles are defined in the original NTSC YIQ color space, which differs from the YUV | ||
| 1348 | // space produced by BT.601/BT.709 matrix conversions. | ||
| 1349 | |||
| 1350 | // this one is not used, this is YUV vectorscope, we cannot determine that the YUV was converted from | ||
| 1351 | // an RGB ColorBars. | ||
| 1352 | /* | ||
| 1353 | static const RGBEntry iq_rgb_native[] = { | ||
| 1354 | { "-I", MINUS_I_R, MINUS_I_G, MINUS_I_B }, // RGB-native (studio black lift) | ||
| 1355 | { "+Q", PLUS_Q_R, PLUS_Q_G, PLUS_Q_B }, // RGB-native (studio black lift) | ||
| 1356 | { "+I", PLUS_I_R, PLUS_I_G, PLUS_I_B }, // n/a ColorBarsHD only, which is YUV-only | ||
| 1357 | }; | ||
| 1358 | */ | ||
| 1359 | |||
| 1360 | // ColorBars ground truth linear RGB (0.75 amplitude, Rec. BT.801-1) | ||
| 1361 | // Top 2/3 bars: LtGrey, Yellow, Cyan, Green, Magenta, Red, Blue | ||
| 1362 | // (White/LtGrey sits at UV center, not a useful vectorscope target) | ||
| 1363 | struct RGBEntry { const char* name; double r, g, b; }; | ||
| 1364 | static const RGBEntry bar_rgb[] = { | ||
| 1365 | { "Yellow", 0.75, 0.75, 0.0 }, | ||
| 1366 | { "Cyan", 0.0, 0.75, 0.75 }, | ||
| 1367 | { "Green", 0.0, 0.75, 0.0 }, | ||
| 1368 | { "Magenta", 0.75, 0.0, 0.75 }, | ||
| 1369 | { "Red", 0.75, 0.0, 0.0 }, | ||
| 1370 | { "Blue", 0.0, 0.0, 0.75 }, | ||
| 1371 | }; | ||
| 1372 | static const RGBEntry bar100_rgb[] = { | ||
| 1373 | { "Yellow", 1.0, 1.0, 0.0 }, | ||
| 1374 | { "Cyan", 0.0, 1.0, 1.0 }, | ||
| 1375 | { "Green", 0.0, 1.0, 0.0 }, | ||
| 1376 | { "Magenta", 1.0, 0.0, 1.0 }, | ||
| 1377 | { "Red", 1.0, 0.0, 0.0 }, | ||
| 1378 | { "Blue", 0.0, 0.0, 1.0 }, | ||
| 1379 | }; | ||
| 1380 | |||
| 1381 | static const RGBEntry iq_rgb_yuv_targeted[] = { | ||
| 1382 | { "-I", MINUS_I_R_YUV, MINUS_I_G_YUV, MINUS_I_B_YUV }, // YUV-targeted (zero-luma) | ||
| 1383 | { "+Q", PLUS_Q_R_YUV, PLUS_Q_G_YUV, PLUS_Q_B_YUV }, // YUV-targeted (zero-luma) | ||
| 1384 | { "+I", PLUS_I_R_YUV, PLUS_I_G_YUV, PLUS_I_B_YUV }, // ColorBarsHD only (same for both) | ||
| 1385 | }; | ||
| 1386 | |||
| 1387 | 2 | const int half_box = 4 * (1 << (show_bits - 8)); | |
| 1388 | |||
| 1389 | // ---- Pixel position helper ---- | ||
| 1390 | // Converts normalised chroma [-0.5..0.5] to vectorscope pixel coordinate. | ||
| 1391 | // Always from full range float, since the YUV squares are obtained from the linear RGB values. | ||
| 1392 | // Target is limited/full range aware. | ||
| 1393 | 2 | auto uv_to_px_float = [&](double uv_norm) -> int { | |
| 1394 | ✗ | return clamp( | |
| 1395 | ✗ | (int)((float)uv_norm * conv_consts_fullrange_float_origin.mul_factor + conv_consts_fullrange_float_origin.dst_offset + 0.5f), | |
| 1396 | ✗ | 0, (1 << show_bits) - 1); | |
| 1397 | }; | ||
| 1398 | |||
| 1399 | // Box color (brownish, visible on the wheel background) ---- | ||
| 1400 | pixel_t box_luma, box_u, box_v; | ||
| 1401 | if constexpr (std::is_integral<pixel_t>::value) { | ||
| 1402 | // Tan/beige: Y=80, slightly orange/brown tint | ||
| 1403 | 2 | box_luma = (pixel_t)(80 << (bits_per_pixel - 8)); | |
| 1404 | 2 | box_u = (pixel_t)(140 << (bits_per_pixel - 8)); | |
| 1405 | 2 | box_v = (pixel_t)(120 << (bits_per_pixel - 8)); | |
| 1406 | } | ||
| 1407 | else { | ||
| 1408 | ✗ | box_luma = c8tof(80); | |
| 1409 | ✗ | box_u = uv8tof(140); | |
| 1410 | ✗ | box_v = uv8tof(120); | |
| 1411 | } | ||
| 1412 | |||
| 1413 |
1/6void Draw_VectorScope_circle_targets_axes<float>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 70 not taken.
void Draw_VectorScope_circle_targets_axes<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 56 → 57 not taken.
✓ Branch 56 → 64 taken 2 times.
void Draw_VectorScope_circle_targets_axes<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 56 → 57 not taken.
✗ Branch 56 → 64 not taken.
|
2 | if (params.targets) { |
| 1414 | |||
| 1415 | // ---- Draw colorbar target boxes ---- | ||
| 1416 | ✗ | for (auto& e : bar_rgb) { | |
| 1417 | double dY, dU, dV; | ||
| 1418 | ✗ | GetYUVFromMatrix(matrix, e.r, e.g, e.b, dY, dU, dV); | |
| 1419 | int cx; | ||
| 1420 | int cy; | ||
| 1421 | if constexpr (std::is_integral<pixel_t>::value) { | ||
| 1422 | ✗ | cx = uv_to_px_float(dU); | |
| 1423 | ✗ | cy = uv_to_px_float(dV); | |
| 1424 | } | ||
| 1425 | else { | ||
| 1426 | ✗ | cx = uv_to_px_float(dU); | |
| 1427 | ✗ | cy = uv_to_px_float(dV); | |
| 1428 | } | ||
| 1429 | |||
| 1430 | ✗ | DrawModeColor2_DrawRect<pixel_t>( | |
| 1431 | dstp, pitch, dstp_u, dstp_v, pitchUV, | ||
| 1432 | cx, cy, half_box, half_box, | ||
| 1433 | swidth, sheight, | ||
| 1434 | box_luma, box_u, box_v, | ||
| 1435 | limit_showwidth); | ||
| 1436 | |||
| 1437 | } | ||
| 1438 | } | ||
| 1439 | |||
| 1440 |
1/6void Draw_VectorScope_circle_targets_axes<float>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 70 → 71 not taken.
✗ Branch 70 → 78 not taken.
void Draw_VectorScope_circle_targets_axes<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 64 → 65 not taken.
✓ Branch 64 → 72 taken 2 times.
void Draw_VectorScope_circle_targets_axes<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 72 not taken.
|
2 | if (params.targets100) { |
| 1441 | |||
| 1442 | // ---- Draw colorbar target boxes ---- | ||
| 1443 | ✗ | for (auto& e : bar100_rgb) { | |
| 1444 | double dY, dU, dV; | ||
| 1445 | ✗ | GetYUVFromMatrix(matrix, e.r, e.g, e.b, dY, dU, dV); | |
| 1446 | int cx; | ||
| 1447 | int cy; | ||
| 1448 | if constexpr (std::is_integral<pixel_t>::value) { | ||
| 1449 | ✗ | cx = uv_to_px_float(dU); | |
| 1450 | ✗ | cy = uv_to_px_float(dV); | |
| 1451 | } | ||
| 1452 | else { | ||
| 1453 | ✗ | cx = uv_to_px_float(dU); | |
| 1454 | ✗ | cy = uv_to_px_float(dV); | |
| 1455 | } | ||
| 1456 | |||
| 1457 | ✗ | DrawModeColor2_DrawRect<pixel_t>( | |
| 1458 | dstp, pitch, dstp_u, dstp_v, pitchUV, | ||
| 1459 | cx, cy, half_box, half_box, | ||
| 1460 | swidth, sheight, | ||
| 1461 | box_luma, box_u, box_v, | ||
| 1462 | limit_showwidth); | ||
| 1463 | |||
| 1464 | } | ||
| 1465 | } | ||
| 1466 | |||
| 1467 |
1/6void Draw_VectorScope_circle_targets_axes<float>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 78 → 79 not taken.
✗ Branch 78 → 86 not taken.
void Draw_VectorScope_circle_targets_axes<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 72 → 73 not taken.
✓ Branch 72 → 80 taken 2 times.
void Draw_VectorScope_circle_targets_axes<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 72 → 73 not taken.
✗ Branch 72 → 80 not taken.
|
2 | if (params.iq) { |
| 1468 | // ---- Draw +Q and -I target boxes ---- | ||
| 1469 | // These are matrix-independent (they are phase references, not primaries), | ||
| 1470 | // but still need the same pixel-coordinate conversion. | ||
| 1471 | ✗ | for (auto& e : iq_rgb_yuv_targeted) { | |
| 1472 | double dY, dU, dV; | ||
| 1473 | ✗ | GetYUVFromMatrix(matrix, e.r, e.g, e.b, dY, dU, dV); | |
| 1474 | ✗ | int cx = uv_to_px_float(dU); | |
| 1475 | ✗ | int cy = uv_to_px_float(dV); | |
| 1476 | // yuv.u and yuv.v are already the correct pixel_t values at the virtual target | ||
| 1477 | // (show) bit depth. | ||
| 1478 | |||
| 1479 | ✗ | DrawModeColor2_DrawRect<pixel_t>( | |
| 1480 | dstp, pitch, dstp_u, dstp_v, pitchUV, | ||
| 1481 | cx, cy, half_box, half_box, | ||
| 1482 | swidth, sheight, | ||
| 1483 | box_luma, box_u, box_v, | ||
| 1484 | limit_showwidth); | ||
| 1485 | |||
| 1486 | } | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | // ---- Radial lines ---- | ||
| 1490 | pixel_t line_luma; | ||
| 1491 | if constexpr (std::is_integral<pixel_t>::value) | ||
| 1492 | 2 | line_luma = (pixel_t)(120 << (bits_per_pixel - 8)); | |
| 1493 | else | ||
| 1494 | ✗ | line_luma = c8tof(120); | |
| 1495 | |||
| 1496 | // Angles to draw(matching PPro vectorscope) : | ||
| 1497 | // 0°, 90°, 180°, 270° — the axis cross | ||
| 1498 | // 33°, 123°, 213°, 303° — the ±I/±Q diagonals | ||
| 1499 | // knowing that in UV space these are not exactly at 33° and 123° | ||
| 1500 | |||
| 1501 |
1/6void Draw_VectorScope_circle_targets_axes<float>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 88 → 89 not taken.
✗ Branch 88 → 94 not taken.
void Draw_VectorScope_circle_targets_axes<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 80 → 81 not taken.
✓ Branch 80 → 86 taken 2 times.
void Draw_VectorScope_circle_targets_axes<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 86 not taken.
|
2 | if (params.axes) { |
| 1502 | ✗ | const double angles90[] = { | |
| 1503 | 0.0, 90.0, 180.0, 270.0 | ||
| 1504 | }; | ||
| 1505 | ✗ | const int limit = (1 << (show_bits - 1)) - 1; | |
| 1506 | ✗ | const int show_bit_shift = show_bits - 8; | |
| 1507 | ✗ | for (double ang : angles90) | |
| 1508 | ✗ | DrawRadialLine<pixel_t>(dstp, pitch, | |
| 1509 | limit, show_bit_shift, ang, line_luma); | ||
| 1510 | } | ||
| 1511 | |||
| 1512 |
1/6void Draw_VectorScope_circle_targets_axes<float>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 94 → 95 not taken.
✗ Branch 94 → 100 not taken.
void Draw_VectorScope_circle_targets_axes<unsigned char>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 86 → 87 not taken.
✓ Branch 86 → 92 taken 2 times.
void Draw_VectorScope_circle_targets_axes<unsigned short>(int, unsigned char*, unsigned char*, unsigned char*, int, int, int, int, double, int, int, int, histogram_color2_params&, ConversionMatrix&, int, bits_conv_constants&, bool, int*, int*):
✗ Branch 86 → 87 not taken.
✗ Branch 86 → 92 not taken.
|
2 | if (params.iq_lines) { |
| 1513 | ✗ | const double anglesIQ[] = { | |
| 1514 | 33.0, 123.0, 213.0, 303.0 | ||
| 1515 | }; | ||
| 1516 | ✗ | const int limit = (1 << (show_bits - 1)) - 1; | |
| 1517 | ✗ | const int show_bit_shift = show_bits - 8; | |
| 1518 | ✗ | for (double ang : anglesIQ) | |
| 1519 | ✗ | DrawRadialLine<pixel_t>(dstp, pitch, | |
| 1520 | limit, show_bit_shift, ang, line_luma); | ||
| 1521 | } | ||
| 1522 | 2 | } | |
| 1523 | |||
| 1524 | |||
| 1525 | 1 | PVideoFrame Histogram::DrawModeColor2(int n, IScriptEnvironment* env) { | |
| 1526 | |||
| 1527 | // all these will get filled by VectorscopePrelude, common for color and color2 modes | ||
| 1528 |
1/2✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 105 not taken.
|
1 | PVideoFrame src; |
| 1529 | BYTE* panel, * panelU, * panelV, * panelA; | ||
| 1530 | int dst_pitch, dst_pitchUV, dst_pitchA, dst_height, dst_heightUV, dst_heightA; | ||
| 1531 | |||
| 1532 | PVideoFrame dst = VectorscopePrelude(n, env, | ||
| 1533 | // outputs | ||
| 1534 | src, | ||
| 1535 | dst_pitch, dst_height, | ||
| 1536 | dst_pitchUV, dst_heightUV, | ||
| 1537 | dst_pitchA, dst_heightA, | ||
| 1538 |
1/2✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 103 not taken.
|
1 | panel, panelU, panelV, panelA); |
| 1539 | |||
| 1540 | 1 | bits_conv_constants d_chroma; | |
| 1541 | 1 | get_bits_conv_constants(d_chroma, /*use_chroma=*/true, | |
| 1542 |
1/2✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 26 not taken.
|
1 | full_range, full_range, |
| 1543 | bits_per_pixel, /*dstBitDepth=*/show_bits); | ||
| 1544 | // d_chroma.mul_factor and d_chroma.dst_offset are now correct for | ||
| 1545 | // limited-limited or full-full depending on _ColorRange frame property. | ||
| 1546 | |||
| 1547 |
1/2✓ Branch 56 → 57 taken 1 time.
✗ Branch 56 → 101 not taken.
|
1 | int swidth = vi.GetPlaneWidthSubsampling(PLANAR_U); |
| 1548 |
1/2✓ Branch 57 → 58 taken 1 time.
✗ Branch 57 → 101 not taken.
|
1 | int sheight = vi.GetPlaneHeightSubsampling(PLANAR_U); |
| 1549 | |||
| 1550 | // Clear Vectorscope area (black background, init Alpha to 0 if present) | ||
| 1551 |
1/2✓ Branch 58 → 59 taken 1 time.
✗ Branch 58 → 60 not taken.
|
1 | if (bits_per_pixel == 8) |
| 1552 | 1 | DrawModeColor2_ClearVectorscopeArea<uint8_t>(bits_per_pixel, | |
| 1553 | panel, panelU, panelV, panelA, | ||
| 1554 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 1555 | dst_height, dst_heightUV, dst_heightA, | ||
| 1556 | show_bits, swidth, sheight, | ||
| 1557 |
1/2✓ Branch 59 → 63 taken 1 time.
✗ Branch 59 → 101 not taken.
|
1 | full_range |
| 1558 | ); | ||
| 1559 | ✗ | else if (bits_per_pixel <= 16) | |
| 1560 | ✗ | DrawModeColor2_ClearVectorscopeArea<uint16_t>(bits_per_pixel, | |
| 1561 | panel, panelU, panelV, panelA, | ||
| 1562 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 1563 | dst_height, dst_heightUV, dst_heightA, | ||
| 1564 | show_bits, swidth, sheight, | ||
| 1565 | ✗ | full_range | |
| 1566 | ); | ||
| 1567 | else | ||
| 1568 | ✗ | DrawModeColor2_ClearVectorscopeArea<float>(bits_per_pixel, | |
| 1569 | panel, panelU, panelV, panelA, | ||
| 1570 | dst_pitch, dst_pitchUV, dst_pitchA, | ||
| 1571 | dst_height, dst_heightUV, dst_heightA, | ||
| 1572 | show_bits, swidth, sheight, | ||
| 1573 | ✗ | full_range | |
| 1574 | ); | ||
| 1575 | |||
| 1576 | // graticule | ||
| 1577 | // Valid chroma boundary square | ||
| 1578 | // always/never/only-when-limited | ||
| 1579 | // "color" mode's graticule is used for highlight danger zone. | ||
| 1580 | // "color2" mode's graticule is used for drawing chroma boundary rectangle. | ||
| 1581 | // "on" or "auto"+limited range | ||
| 1582 |
1/2✗ Branch 63 → 64 not taken.
✓ Branch 63 → 66 taken 1 time.
|
1 | const bool need_graticule = color2_params.graticule_type == histogram_color2_params::GRATICULE_ON || |
| 1583 | ✗ | (color2_params.graticule_type == histogram_color2_params::GRATICULE_AUTO && !full_range); | |
| 1584 | |||
| 1585 |
1/2✓ Branch 68 → 69 taken 1 time.
✗ Branch 68 → 74 not taken.
|
1 | if (need_graticule) { |
| 1586 |
1/2✓ Branch 69 → 70 taken 1 time.
✗ Branch 69 → 71 not taken.
|
1 | if (bits_per_pixel == 8) |
| 1587 |
1/2✓ Branch 70 → 74 taken 1 time.
✗ Branch 70 → 101 not taken.
|
1 | DrawModeColor2_draw_graticule<uint8_t>(bits_per_pixel, panel, dst_pitch, dst_height, show_bits); |
| 1588 | ✗ | else if (bits_per_pixel <= 16) | |
| 1589 | ✗ | DrawModeColor2_draw_graticule<uint16_t>(bits_per_pixel, panel, dst_pitch, dst_height, show_bits); | |
| 1590 | else | ||
| 1591 | ✗ | DrawModeColor2_draw_graticule<float>(bits_per_pixel, panel, dst_pitch, dst_height, show_bits); | |
| 1592 | } | ||
| 1593 | |||
| 1594 | // others: 75% RGB and IQ targets, 15 degree marks, etc. | ||
| 1595 |
1/2✓ Branch 74 → 75 taken 1 time.
✗ Branch 74 → 76 not taken.
|
1 | if (bits_per_pixel == 8) |
| 1596 | 1 | Draw_VectorScope_circle_targets_axes<uint8_t>(bits_per_pixel, | |
| 1597 | panel, panelU, panelV, | ||
| 1598 | dst_pitch, dst_pitchUV, | ||
| 1599 | dst_height, dst_heightUV, | ||
| 1600 | color2_innerF, | ||
| 1601 | show_bits, swidth, sheight, | ||
| 1602 | 1 | color2_params, matrix, theMatrix, d_chroma, full_range, | |
| 1603 |
1/2✓ Branch 75 → 79 taken 1 time.
✗ Branch 75 → 101 not taken.
|
1 | deg15c, deg15s |
| 1604 | ); | ||
| 1605 | ✗ | else if (bits_per_pixel <= 16) | |
| 1606 | ✗ | Draw_VectorScope_circle_targets_axes<uint16_t>(bits_per_pixel, | |
| 1607 | panel, panelU, panelV, | ||
| 1608 | dst_pitch, dst_pitchUV, | ||
| 1609 | dst_height, dst_heightUV, | ||
| 1610 | color2_innerF, | ||
| 1611 | show_bits, swidth, sheight, | ||
| 1612 | ✗ | color2_params, matrix, theMatrix, d_chroma, full_range, | |
| 1613 | ✗ | deg15c, deg15s | |
| 1614 | ); | ||
| 1615 | else | ||
| 1616 | ✗ | Draw_VectorScope_circle_targets_axes<float>(bits_per_pixel, | |
| 1617 | panel, panelU, panelV, | ||
| 1618 | dst_pitch, dst_pitchUV, | ||
| 1619 | dst_height, dst_heightUV, | ||
| 1620 | color2_innerF, | ||
| 1621 | show_bits, swidth, sheight, | ||
| 1622 | ✗ | color2_params, matrix, theMatrix, d_chroma, full_range, | |
| 1623 | ✗ | deg15c, deg15s | |
| 1624 | ); | ||
| 1625 | |||
| 1626 | // plot vectorscope | ||
| 1627 |
1/2✓ Branch 80 → 81 taken 1 time.
✗ Branch 80 → 101 not taken.
|
1 | const int src_pitch = src->GetPitch(PLANAR_Y) / pixelsize; |
| 1628 |
1/2✓ Branch 82 → 83 taken 1 time.
✗ Branch 82 → 101 not taken.
|
1 | const int src_pitchUV = src->GetPitch(PLANAR_U) / pixelsize; |
| 1629 |
1/2✓ Branch 84 → 85 taken 1 time.
✗ Branch 84 → 101 not taken.
|
1 | const int src_widthUV = src->GetRowSize(PLANAR_U) / pixelsize; |
| 1630 |
1/2✓ Branch 86 → 87 taken 1 time.
✗ Branch 86 → 101 not taken.
|
1 | const int src_heightUV = src->GetHeight(PLANAR_U); |
| 1631 | |||
| 1632 |
1/2✓ Branch 88 → 89 taken 1 time.
✗ Branch 88 → 101 not taken.
|
1 | const BYTE* pY = src->GetReadPtr(PLANAR_Y); |
| 1633 |
1/2✓ Branch 90 → 91 taken 1 time.
✗ Branch 90 → 101 not taken.
|
1 | const BYTE* pU = src->GetReadPtr(PLANAR_U); |
| 1634 |
1/2✓ Branch 92 → 93 taken 1 time.
✗ Branch 92 → 101 not taken.
|
1 | const BYTE* pV = src->GetReadPtr(PLANAR_V); |
| 1635 | |||
| 1636 | 1 | dst_pitch /= pixelsize; | |
| 1637 | 1 | dst_pitchUV /= pixelsize; | |
| 1638 | |||
| 1639 |
1/2✓ Branch 93 → 94 taken 1 time.
✗ Branch 93 → 95 not taken.
|
1 | if(bits_per_pixel == 8) |
| 1640 | 1 | do_vectorscope_color2<uint8_t>( | |
| 1641 | panel, panelU, panelV, | ||
| 1642 | pY, pU, pV, | ||
| 1643 | dst_pitch, dst_pitchUV, | ||
| 1644 | src_pitch, src_pitchUV, | ||
| 1645 | src_widthUV, src_heightUV, | ||
| 1646 | swidth, sheight, | ||
| 1647 |
1/2✓ Branch 94 → 98 taken 1 time.
✗ Branch 94 → 101 not taken.
|
1 | show_bits, bits_per_pixel, d_chroma, full_range); |
| 1648 | ✗ | else if (bits_per_pixel <= 16) | |
| 1649 | ✗ | do_vectorscope_color2<uint16_t>( | |
| 1650 | (uint16_t *)panel, (uint16_t*)panelU, (uint16_t*)panelV, | ||
| 1651 | (uint16_t*)pY, (uint16_t*)pU, (uint16_t*)pV, | ||
| 1652 | dst_pitch, dst_pitchUV, | ||
| 1653 | src_pitch, src_pitchUV, | ||
| 1654 | src_widthUV, src_heightUV, | ||
| 1655 | swidth, sheight, | ||
| 1656 | ✗ | show_bits, bits_per_pixel, d_chroma, full_range); | |
| 1657 | else | ||
| 1658 | ✗ | do_vectorscope_color2<float>( | |
| 1659 | (float*)panel, (float*)panelU, (float*)panelV, | ||
| 1660 | (float*)pY, (float*)pU, (float*)pV, | ||
| 1661 | dst_pitch, dst_pitchUV, | ||
| 1662 | src_pitch, src_pitchUV, | ||
| 1663 | src_widthUV, src_heightUV, | ||
| 1664 | swidth, sheight, | ||
| 1665 | ✗ | show_bits, bits_per_pixel, d_chroma, full_range); | |
| 1666 | |||
| 1667 | 1 | return dst; | |
| 1668 | 1 | } | |
| 1669 | |||
| 1670 | template<typename pixel_t, bool chroma_danger> | ||
| 1671 | 1 | static void DrawModeColor_PlotHistogram_inner( | |
| 1672 | uint8_t* panel_y, int dstpitch, | ||
| 1673 | const int* histUV, | ||
| 1674 | int show_size, int show_bits, | ||
| 1675 | int bits_per_pixel, | ||
| 1676 | int maxval) | ||
| 1677 | { | ||
| 1678 | 1 | const int limit16 = 16 << (show_bits - 8); | |
| 1679 | 1 | const int limit240 = 240 << (show_bits - 8); | |
| 1680 | int limit16_pixel, luma235; | ||
| 1681 | if constexpr (std::is_same_v<pixel_t, float>) { | ||
| 1682 | ✗ | limit16_pixel = 16; | |
| 1683 | ✗ | luma235 = 235; | |
| 1684 | } | ||
| 1685 | else { | ||
| 1686 | 1 | limit16_pixel = 16 << (bits_per_pixel - 8); | |
| 1687 | 1 | luma235 = 235 << (bits_per_pixel - 8); | |
| 1688 | } | ||
| 1689 | 1 | const int scale = std::is_same_v<pixel_t, float> ? 1 : (1 << (bits_per_pixel - 8)); | |
| 1690 | |||
| 1691 |
2/12void DrawModeColor_PlotHistogram_inner<float, false>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 8 → 3 not taken.
✗ Branch 8 → 9 not taken.
void DrawModeColor_PlotHistogram_inner<float, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 16 → 3 not taken.
✗ Branch 16 → 17 not taken.
void DrawModeColor_PlotHistogram_inner<unsigned char, false>(unsigned char*, int, int const*, int, int, int, int):
✓ Branch 8 → 3 taken 256 times.
✓ Branch 8 → 9 taken 1 time.
void DrawModeColor_PlotHistogram_inner<unsigned char, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 16 → 3 not taken.
✗ Branch 16 → 17 not taken.
void DrawModeColor_PlotHistogram_inner<unsigned short, false>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 8 → 3 not taken.
✗ Branch 8 → 9 not taken.
void DrawModeColor_PlotHistogram_inner<unsigned short, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 16 → 3 not taken.
✗ Branch 16 → 17 not taken.
|
257 | for (int y = 0; y < show_size; y++) { |
| 1692 | // ylimited: compile-time eliminated when chroma_danger==false | ||
| 1693 |
0/12void DrawModeColor_PlotHistogram_inner<float, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
void DrawModeColor_PlotHistogram_inner<unsigned char, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
void DrawModeColor_PlotHistogram_inner<unsigned short, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
|
256 | const bool ylimited = chroma_danger && (y < limit16 || y > limit240); |
| 1694 | 256 | auto row = reinterpret_cast<pixel_t*>(panel_y); | |
| 1695 | 256 | const int* histRow = histUV + y * show_size; | |
| 1696 |
2/12void DrawModeColor_PlotHistogram_inner<float, false>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 6 → 4 not taken.
✗ Branch 6 → 7 not taken.
void DrawModeColor_PlotHistogram_inner<float, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 14 → 8 not taken.
✗ Branch 14 → 15 not taken.
void DrawModeColor_PlotHistogram_inner<unsigned char, false>(unsigned char*, int, int const*, int, int, int, int):
✓ Branch 6 → 4 taken 65536 times.
✓ Branch 6 → 7 taken 256 times.
void DrawModeColor_PlotHistogram_inner<unsigned char, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 14 → 8 not taken.
✗ Branch 14 → 15 not taken.
void DrawModeColor_PlotHistogram_inner<unsigned short, false>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 6 → 4 not taken.
✗ Branch 6 → 7 not taken.
void DrawModeColor_PlotHistogram_inner<unsigned short, true>(unsigned char*, int, int const*, int, int, int, int):
✗ Branch 14 → 8 not taken.
✗ Branch 14 → 15 not taken.
|
65792 | for (int x = 0; x < show_size; x++) { |
| 1697 | 65536 | int disp_val = (histRow[x] * scale) / maxval; | |
| 1698 | // x danger check: compile-time eliminated when chroma_danger==false | ||
| 1699 | if constexpr (chroma_danger) { | ||
| 1700 | ✗ | if (ylimited || x < limit16 || x > limit240) | |
| 1701 | ✗ | disp_val -= limit16_pixel; | |
| 1702 | } | ||
| 1703 | 65536 | int out = min(luma235, limit16_pixel + disp_val); | |
| 1704 | if constexpr (std::is_same_v<pixel_t, float>) | ||
| 1705 | ✗ | row[x] = (float)out / 255.0f; | |
| 1706 | else | ||
| 1707 | 65536 | row[x] = (pixel_t)out; | |
| 1708 | } | ||
| 1709 | 256 | panel_y += dstpitch; | |
| 1710 | } | ||
| 1711 | 1 | } | |
| 1712 | |||
| 1713 | template<typename pixel_t> | ||
| 1714 | 1 | static void DrawModeColor_PlotHistogram_dispatch( | |
| 1715 | bool show_chroma_danger_zone, | ||
| 1716 | uint8_t* panel_y, int dstpitch, | ||
| 1717 | const int* histUV, | ||
| 1718 | int show_size, int show_bits, | ||
| 1719 | int bits_per_pixel, | ||
| 1720 | int maxval) | ||
| 1721 | { | ||
| 1722 |
1/6void DrawModeColor_PlotHistogram_dispatch<float>(bool, unsigned char*, int, int const*, int, int, int, int):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
void DrawModeColor_PlotHistogram_dispatch<unsigned char>(bool, unsigned char*, int, int const*, int, int, int, int):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
void DrawModeColor_PlotHistogram_dispatch<unsigned short>(bool, unsigned char*, int, int const*, int, int, int, int):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
|
1 | if (show_chroma_danger_zone) |
| 1723 | ✗ | DrawModeColor_PlotHistogram_inner<pixel_t, true>(panel_y, dstpitch, histUV, show_size, show_bits, bits_per_pixel, maxval); | |
| 1724 | else | ||
| 1725 | 1 | DrawModeColor_PlotHistogram_inner<pixel_t, false>(panel_y, dstpitch, histUV, show_size, show_bits, bits_per_pixel, maxval); | |
| 1726 | 1 | } | |
| 1727 | |||
| 1728 | |||
| 1729 | |||
| 1730 | 1 | PVideoFrame Histogram::DrawModeColor(int n, IScriptEnvironment* env) { | |
| 1731 | |||
| 1732 | // all these will get filled by VectorscopePrelude, common for color and color2 modes | ||
| 1733 |
1/2✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 255 not taken.
|
1 | PVideoFrame src; |
| 1734 | BYTE* panel, * panelU, * panelV, * panelA; | ||
| 1735 | int dst_pitch, dst_pitchUV, dst_pitchA, dst_height, dst_heightUV, dst_heightA; | ||
| 1736 | |||
| 1737 | PVideoFrame dst = VectorscopePrelude(n, env, | ||
| 1738 | // outputs | ||
| 1739 | src, | ||
| 1740 | dst_pitch, dst_height, | ||
| 1741 | dst_pitchUV, dst_heightUV, | ||
| 1742 | dst_pitchA, dst_heightA, | ||
| 1743 |
1/2✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 253 not taken.
|
1 | panel, panelU, panelV, panelA); |
| 1744 | |||
| 1745 | // always planar | ||
| 1746 | |||
| 1747 | 1 | int show_size = 1 << show_bits; // 256 for 8 bits, max 1024x1024 (10 bit resolution) found | |
| 1748 | |||
| 1749 | 1 | bits_conv_constants d_chroma; | |
| 1750 | 1 | get_bits_conv_constants(d_chroma, /*use_chroma=*/true, | |
| 1751 |
1/2✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 26 not taken.
|
1 | full_range, full_range, |
| 1752 | bits_per_pixel, /*dstBitDepth=*/show_bits); | ||
| 1753 | // d_chroma.mul_factor and d_chroma.dst_offset are now correct for | ||
| 1754 | // limited-limited or full-full depending on _ColorRange frame property. | ||
| 1755 | |||
| 1756 | // Allocate histogram array, can be huge for 12 bits (4096x4096 = 16 million ints), so use nothrow and check for failure. | ||
| 1757 |
1/2✓ Branch 56 → 57 taken 1 time.
✗ Branch 56 → 58 not taken.
|
1 | int* histUV = new(std::nothrow) int[show_size * show_size]; |
| 1758 |
1/2✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 1 time.
|
1 | if (!histUV) |
| 1759 | ✗ | env->ThrowError("Histogram: malloc failure!"); | |
| 1760 | |||
| 1761 | 1 | memset(histUV, 0, sizeof(int) * show_size * show_size); | |
| 1762 | |||
| 1763 | // Create histogram from the original src frame's U and V planes. | ||
| 1764 | // We need to take into account the bit depth and the show_bits, as well as the limited/full range | ||
| 1765 | // for scaling to show_bits correctly. | ||
| 1766 |
1/2✓ Branch 63 → 64 taken 1 time.
✗ Branch 63 → 251 not taken.
|
1 | const BYTE* pU = src->GetReadPtr(PLANAR_U); |
| 1767 |
1/2✓ Branch 65 → 66 taken 1 time.
✗ Branch 65 → 251 not taken.
|
1 | const BYTE* pV = src->GetReadPtr(PLANAR_V); |
| 1768 | |||
| 1769 |
1/2✓ Branch 66 → 67 taken 1 time.
✗ Branch 66 → 251 not taken.
|
1 | int w = origwidth >> vi.GetPlaneWidthSubsampling(PLANAR_U); |
| 1770 |
1/2✓ Branch 68 → 69 taken 1 time.
✗ Branch 68 → 251 not taken.
|
1 | int h = src->GetHeight(PLANAR_U); |
| 1771 |
1/2✓ Branch 70 → 71 taken 1 time.
✗ Branch 70 → 251 not taken.
|
1 | int p = src->GetPitch(PLANAR_U) / pixelsize; |
| 1772 | |||
| 1773 | 1 | const int max_pos = (1 << show_bits) - 1; | |
| 1774 | 1 | const float mul_factor = d_chroma.mul_factor; | |
| 1775 | 1 | const float dst_offset = d_chroma.dst_offset; | |
| 1776 | 1 | const int src_offset_i = d_chroma.src_offset_i; | |
| 1777 | |||
| 1778 |
1/2✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 89 not taken.
|
1 | if (pixelsize == 1) { |
| 1779 |
1/2✓ Branch 72 → 73 taken 1 time.
✗ Branch 72 → 79 not taken.
|
1 | if (show_bits == bits_per_pixel) { |
| 1780 | // quick case: no bit depth conversion needed | ||
| 1781 |
2/2✓ Branch 78 → 74 taken 2 times.
✓ Branch 78 → 121 taken 1 time.
|
3 | for (int y = 0; y < h; y++) { |
| 1782 |
2/2✓ Branch 76 → 75 taken 4 times.
✓ Branch 76 → 77 taken 2 times.
|
6 | for (int x = 0; x < w; x++) { |
| 1783 | 4 | int u = pU[y * p + x]; | |
| 1784 | 4 | int v = pV[y * p + x]; | |
| 1785 | 4 | histUV[(v << 8) + u]++; | |
| 1786 | } | ||
| 1787 | } | ||
| 1788 | } | ||
| 1789 | else { | ||
| 1790 | // 8 bit data on 10 bit sized screen | ||
| 1791 | // works for both limited and full range, since the conversion is the same for 8 bit source | ||
| 1792 | // (10 bit limited case: mul_factor = 4, dst_offset = 0 for full, dst_offset = 16 for limited) | ||
| 1793 | ✗ | for (int y = 0; y < h; y++) { | |
| 1794 | ✗ | for (int x = 0; x < w; x++) { | |
| 1795 | ✗ | const int uval = reinterpret_cast<const uint8_t*>(pU)[y * p + x]; | |
| 1796 | ✗ | const int vval = reinterpret_cast<const uint8_t*>(pV)[y * p + x]; | |
| 1797 | ✗ | int uval_posindex = (int)((uval - src_offset_i) * mul_factor + dst_offset + 0.5f); | |
| 1798 | ✗ | int vval_posindex = (int)((vval - src_offset_i) * mul_factor + dst_offset + 0.5f); | |
| 1799 | ✗ | uval_posindex = max(0, min(max_pos, uval_posindex)); | |
| 1800 | ✗ | vval_posindex = max(0, min(max_pos, vval_posindex)); | |
| 1801 | ✗ | histUV[(vval_posindex << show_bits) + uval_posindex]++; | |
| 1802 | } | ||
| 1803 | } | ||
| 1804 | } | ||
| 1805 | } | ||
| 1806 | ✗ | else if (pixelsize == 2) { | |
| 1807 | ✗ | if (show_bits == bits_per_pixel) { | |
| 1808 | // quick case: no bit depth conversion needed | ||
| 1809 | ✗ | for (int y = 0; y < h; y++) { | |
| 1810 | ✗ | for (int x = 0; x < w; x++) { | |
| 1811 | ✗ | int u = reinterpret_cast<const uint16_t*>(pU)[y * p + x]; | |
| 1812 | ✗ | int v = reinterpret_cast<const uint16_t*>(pV)[y * p + x]; | |
| 1813 | ✗ | histUV[(v << show_bits) + u]++; | |
| 1814 | } | ||
| 1815 | } | ||
| 1816 | } | ||
| 1817 | else { | ||
| 1818 | // works for both limited and full range, since the conversion is the same for 16 bit source (mul_factor = 4, dst_offset = 0 for full, dst_offset = 16 for limited) | ||
| 1819 | ✗ | for (int y = 0; y < h; y++) { | |
| 1820 | ✗ | for (int x = 0; x < w; x++) { | |
| 1821 | ✗ | const int uval = reinterpret_cast<const uint16_t*>(pU)[y * p + x]; | |
| 1822 | ✗ | const int vval = reinterpret_cast<const uint16_t*>(pV)[y * p + x]; | |
| 1823 | ✗ | int uval_posindex = (int)((uval - src_offset_i) * mul_factor + dst_offset + 0.5f); | |
| 1824 | ✗ | int vval_posindex = (int)((vval - src_offset_i) * mul_factor + dst_offset + 0.5f); | |
| 1825 | ✗ | uval_posindex = max(0, min(max_pos, uval_posindex)); | |
| 1826 | ✗ | vval_posindex = max(0, min(max_pos, vval_posindex)); | |
| 1827 | ✗ | histUV[(vval_posindex << show_bits) + uval_posindex]++; | |
| 1828 | } | ||
| 1829 | } | ||
| 1830 | } | ||
| 1831 | } | ||
| 1832 | else { // float | ||
| 1833 | // 32 bit data on show_bits bit sized screen | ||
| 1834 | ✗ | for (int y = 0; y < h; y++) { | |
| 1835 | ✗ | for (int x = 0; x < w; x++) { | |
| 1836 | ✗ | const float uval_f = max(-0.5f, min(0.5f, reinterpret_cast<const float*>(pU)[y * p + x])); | |
| 1837 | ✗ | const float vval_f = max(-0.5f, min(0.5f, reinterpret_cast<const float*>(pV)[y * p + x])); | |
| 1838 | ✗ | int uval_posindex = (int)(uval_f * mul_factor + dst_offset + 0.5f); | |
| 1839 | ✗ | int vval_posindex = (int)(vval_f * mul_factor + dst_offset + 0.5f); | |
| 1840 | ✗ | uval_posindex = max(0, min(max_pos, uval_posindex)); | |
| 1841 | ✗ | vval_posindex = max(0, min(max_pos, vval_posindex)); | |
| 1842 | ✗ | histUV[(vval_posindex << show_bits) + uval_posindex]++; | |
| 1843 | } | ||
| 1844 | } | ||
| 1845 | } | ||
| 1846 | // End of histogram creation. | ||
| 1847 | |||
| 1848 |
1/2✓ Branch 121 → 122 taken 1 time.
✗ Branch 121 → 124 not taken.
|
2 | const bool show_chroma_danger_zone = color2_params.graticule_type == histogram_color2_params::GRATICULE_ON || |
| 1849 |
1/4✗ Branch 122 → 123 not taken.
✓ Branch 122 → 125 taken 1 time.
✗ Branch 123 → 124 not taken.
✗ Branch 123 → 125 not taken.
|
1 | (color2_params.graticule_type == histogram_color2_params::GRATICULE_AUTO && !full_range); |
| 1850 | |||
| 1851 | // Plot Histogram on Y. | ||
| 1852 | 1 | int maxval = 1; | |
| 1853 | // Should we adjust the divisor (maxval)?? | ||
| 1854 |
1/2✓ Branch 126 → 127 taken 1 time.
✗ Branch 126 → 128 not taken.
|
1 | if (pixelsize == 1) |
| 1855 |
1/2✓ Branch 127 → 131 taken 1 time.
✗ Branch 127 → 251 not taken.
|
1 | DrawModeColor_PlotHistogram_dispatch<uint8_t>(show_chroma_danger_zone, panel, dst_pitch, histUV, show_size, show_bits, bits_per_pixel, maxval); |
| 1856 | ✗ | else if (pixelsize == 2) | |
| 1857 | ✗ | DrawModeColor_PlotHistogram_dispatch<uint16_t>(show_chroma_danger_zone, panel, dst_pitch, histUV, show_size, show_bits, bits_per_pixel, maxval); | |
| 1858 | else | ||
| 1859 | ✗ | DrawModeColor_PlotHistogram_dispatch<float>(show_chroma_danger_zone, panel, dst_pitch, histUV, show_size, show_bits, bits_per_pixel, maxval); | |
| 1860 | |||
| 1861 | // Draw colors - U gradient (x-driven) and V gradient (y-driven) | ||
| 1862 |
1/2✓ Branch 131 → 132 taken 1 time.
✗ Branch 131 → 251 not taken.
|
1 | const int swidth = vi.GetPlaneWidthSubsampling(PLANAR_U); |
| 1863 |
1/2✓ Branch 132 → 133 taken 1 time.
✗ Branch 132 → 251 not taken.
|
1 | const int sheight = vi.GetPlaneHeightSubsampling(PLANAR_U); |
| 1864 | 1 | const int uvWidth = show_size >> swidth; | |
| 1865 | 1 | const int uvHeight = show_size >> sheight; | |
| 1866 | 1 | const int shiftCount = show_bits - bits_per_pixel; // for int types | |
| 1867 |
1/2✗ Branch 133 → 134 not taken.
✓ Branch 133 → 135 taken 1 time.
|
1 | const int rounder = shiftCount > 0 ? (1 << (shiftCount - 1)) : 0; // for int types when downshifting |
| 1868 | 1 | const int shiftCount_f = show_bits - 8; // ? Why | |
| 1869 | |||
| 1870 | // U: value depends only on x -> precompute one row, memcpy for all y | ||
| 1871 | // V: value depends only on y -> compute once per row, fill entire row | ||
| 1872 | |||
| 1873 |
1/2✓ Branch 136 → 137 taken 1 time.
✗ Branch 136 → 154 not taken.
|
1 | if (pixelsize == 1) { |
| 1874 | // --- U --- | ||
| 1875 | // Precompute one row | ||
| 1876 |
1/2✓ Branch 139 → 140 taken 1 time.
✗ Branch 139 → 239 not taken.
|
1 | std::vector<uint8_t> uRow(uvWidth); |
| 1877 |
2/2✓ Branch 144 → 142 taken 128 times.
✓ Branch 144 → 145 taken 1 time.
|
129 | for (int x = 0; x < uvWidth; x++) |
| 1878 | 128 | uRow[x] = (uint8_t)((x << swidth) >> shiftCount); | |
| 1879 | 1 | auto p = panelU; | |
| 1880 |
2/2✓ Branch 148 → 146 taken 128 times.
✓ Branch 148 → 149 taken 1 time.
|
129 | for (int y = 0; y < uvHeight; y++, p += dst_pitchUV) |
| 1881 | 128 | memcpy(p, uRow.data(), uvWidth); | |
| 1882 | // --- V --- | ||
| 1883 | 1 | p = panelV; | |
| 1884 |
2/2✓ Branch 151 → 150 taken 128 times.
✓ Branch 151 → 152 taken 1 time.
|
129 | for (int y = 0; y < uvHeight; y++, p += dst_pitchUV) { |
| 1885 | 128 | uint8_t vval = (uint8_t)(((y << sheight) + rounder) >> shiftCount); | |
| 1886 | 128 | memset(p, vval, uvWidth); | |
| 1887 | } | ||
| 1888 | 1 | } | |
| 1889 | ✗ | else if (pixelsize == 2) { | |
| 1890 | // --- U --- | ||
| 1891 | ✗ | std::vector<uint16_t> uRow(uvWidth); | |
| 1892 | ✗ | if (shiftCount >= 0) { | |
| 1893 | ✗ | for (int x = 0; x < uvWidth; x++) | |
| 1894 | ✗ | uRow[x] = (uint16_t)(((x << swidth) + rounder) >> shiftCount); | |
| 1895 | } | ||
| 1896 | else { | ||
| 1897 | ✗ | for (int x = 0; x < uvWidth; x++) | |
| 1898 | ✗ | uRow[x] = (uint16_t)((x << swidth) << -shiftCount); | |
| 1899 | } | ||
| 1900 | ✗ | auto p = panelU; | |
| 1901 | ✗ | for (int y = 0; y < uvHeight; y++, p += dst_pitchUV) | |
| 1902 | ✗ | memcpy(p, uRow.data(), uvWidth * sizeof(uint16_t)); | |
| 1903 | |||
| 1904 | // --- V --- | ||
| 1905 | ✗ | p = panelV; | |
| 1906 | ✗ | if (shiftCount >= 0) { | |
| 1907 | ✗ | for (int y = 0; y < uvHeight; y++, p += dst_pitchUV) { | |
| 1908 | ✗ | uint16_t vval = (uint16_t)(((y << sheight) + rounder) >> shiftCount); | |
| 1909 | ✗ | std::fill_n(reinterpret_cast<uint16_t*>(p), uvWidth, vval); | |
| 1910 | } | ||
| 1911 | } | ||
| 1912 | else { | ||
| 1913 | ✗ | for (int y = 0; y < uvHeight; y++, p += dst_pitchUV) { | |
| 1914 | ✗ | uint16_t vval = (uint16_t)((y << sheight) << -shiftCount); | |
| 1915 | ✗ | std::fill_n(reinterpret_cast<uint16_t*>(p), uvWidth, vval); | |
| 1916 | } | ||
| 1917 | } | ||
| 1918 | ✗ | } | |
| 1919 | else { // float | ||
| 1920 | // --- U --- | ||
| 1921 | ✗ | std::vector<float> uRow(uvWidth); | |
| 1922 | ✗ | for (int x = 0; x < uvWidth; x++) | |
| 1923 | ✗ | uRow[x] = uv8tof((x << swidth) >> shiftCount_f); | |
| 1924 | ✗ | auto p = panelU; | |
| 1925 | ✗ | for (int y = 0; y < uvHeight; y++, p += dst_pitchUV) | |
| 1926 | ✗ | memcpy(p, uRow.data(), uvWidth * sizeof(float)); | |
| 1927 | // --- V --- | ||
| 1928 | ✗ | p = panelV; | |
| 1929 | ✗ | for (int y = 0; y < uvHeight; y++, p += dst_pitchUV) { | |
| 1930 | ✗ | float vval = uv8tof((y << sheight) >> shiftCount_f); | |
| 1931 | ✗ | std::fill_n(reinterpret_cast<float*>(p), uvWidth, vval); | |
| 1932 | } | ||
| 1933 | ✗ | } | |
| 1934 | |||
| 1935 |
1/2✓ Branch 229 → 230 taken 1 time.
✗ Branch 229 → 231 not taken.
|
1 | delete[] histUV; |
| 1936 | |||
| 1937 | // others: RGB and IQ targets, 15 degree marks, etc | ||
| 1938 |
1/2✓ Branch 231 → 232 taken 1 time.
✗ Branch 231 → 233 not taken.
|
1 | if (bits_per_pixel == 8) |
| 1939 | 1 | Draw_VectorScope_circle_targets_axes<uint8_t>(bits_per_pixel, | |
| 1940 | panel, panelU, panelV, | ||
| 1941 | dst_pitch, dst_pitchUV, | ||
| 1942 | dst_height, dst_heightUV, | ||
| 1943 | color2_innerF, | ||
| 1944 | show_bits, swidth, sheight, | ||
| 1945 | 1 | color2_params, matrix, theMatrix, d_chroma, full_range, | |
| 1946 |
1/2✓ Branch 232 → 236 taken 1 time.
✗ Branch 232 → 251 not taken.
|
1 | deg15c, deg15s |
| 1947 | ); | ||
| 1948 | ✗ | else if (bits_per_pixel <= 16) | |
| 1949 | ✗ | Draw_VectorScope_circle_targets_axes<uint16_t>(bits_per_pixel, | |
| 1950 | panel, panelU, panelV, | ||
| 1951 | dst_pitch, dst_pitchUV, | ||
| 1952 | dst_height, dst_heightUV, | ||
| 1953 | color2_innerF, | ||
| 1954 | show_bits, swidth, sheight, | ||
| 1955 | ✗ | color2_params, matrix, theMatrix, d_chroma, full_range, | |
| 1956 | ✗ | deg15c, deg15s | |
| 1957 | ); | ||
| 1958 | else | ||
| 1959 | ✗ | Draw_VectorScope_circle_targets_axes<float>(bits_per_pixel, | |
| 1960 | panel, panelU, panelV, | ||
| 1961 | dst_pitch, dst_pitchUV, | ||
| 1962 | dst_height, dst_heightUV, | ||
| 1963 | color2_innerF, | ||
| 1964 | show_bits, swidth, sheight, | ||
| 1965 | ✗ | color2_params, matrix, theMatrix, d_chroma, full_range, | |
| 1966 | ✗ | deg15c, deg15s | |
| 1967 | ); | ||
| 1968 | |||
| 1969 | 1 | return dst; | |
| 1970 | 1 | } | |
| 1971 | |||
| 1972 | |||
| 1973 | 1 | PVideoFrame Histogram::DrawModeLevels(int n, IScriptEnvironment* env) { | |
| 1974 |
1/2✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 604 not taken.
|
1 | PVideoFrame src = child->GetFrame(n, env); |
| 1975 |
1/2✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 602 not taken.
|
1 | PVideoFrame dst = env->NewVideoFrameP(vi, &src); |
| 1976 |
1/2✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 600 not taken.
|
1 | BYTE* dstp = dst->GetWritePtr(); |
| 1977 | |||
| 1978 | // Note: drawing colors are of limited range independently from clip range | ||
| 1979 | // bool full_range is filled in ctor. | ||
| 1980 | |||
| 1981 | 1 | int show_size = 1 << show_bits; | |
| 1982 | |||
| 1983 |
1/2✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 600 not taken.
|
1 | const bool isGrey = vi.IsY(); |
| 1984 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1 time.
|
1 | const int planecount = isGrey ? 1 : 3; |
| 1985 |
1/2✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 600 not taken.
|
1 | const bool RGB = vi.IsRGB(); |
| 1986 | 1 | const bool isFloat = (bits_per_pixel == 32); | |
| 1987 |
1/2✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 1 time.
|
1 | const int color_shift = isFloat ? 0 : (bits_per_pixel - 8); |
| 1988 |
1/2✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 17 not taken.
|
1 | const int max_pixel_value = bits_per_pixel <= 16 ? (1 << bits_per_pixel) - 1 : 0; // float: n/a |
| 1989 |
1/2✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 1 time.
|
1 | const float color_shift_factor = isFloat ? 1.0f / 255.0f : max_pixel_value / 255.0f; |
| 1990 | |||
| 1991 | int plane_default_black[3] = { | ||
| 1992 |
1/2✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 1 time.
|
1 | RGB ? 0 : (16 << color_shift), |
| 1993 | 1 | RGB ? 0 : (128 << color_shift), | |
| 1994 | 1 | RGB ? 0 : (128 << color_shift) | |
| 1995 |
2/4✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 1 time.
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 1 time.
|
2 | }; |
| 1996 | 1 | float plane_default_black_f[3] = { | |
| 1997 |
1/2✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 1 time.
|
1 | RGB ? 0 : 16 / 255.0f, |
| 1998 | RGB ? 0 : 0.0f, | ||
| 1999 | RGB ? 0 : 0.0f | ||
| 2000 | 1 | }; | |
| 2001 | |||
| 2002 | 1 | const int planesYUV[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A}; | |
| 2003 | 1 | const int planesRGB[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A}; | |
| 2004 |
2/8✓ Branch 33 → 34 taken 1 time.
✗ Branch 33 → 600 not taken.
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 37 taken 1 time.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 600 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 38 not taken.
|
1 | const int *planes = vi.IsYUV() || vi.IsYUVA() ? planesYUV : planesRGB; |
| 2005 | |||
| 2006 |
1/2✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 117 not taken.
|
1 | if (keepsource) { |
| 2007 |
3/6✓ Branch 41 → 42 taken 1 time.
✗ Branch 41 → 600 not taken.
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 600 not taken.
✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 117 not taken.
|
1 | if (src->GetHeight() < dst->GetHeight()) { |
| 2008 | // fill empty area in the right bottom part | ||
| 2009 |
3/6✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 600 not taken.
✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 600 not taken.
✓ Branch 50 → 51 taken 1 time.
✗ Branch 50 → 600 not taken.
|
1 | const int fillSize = (dst->GetHeight() - src->GetHeight()) * dst->GetPitch(); |
| 2010 |
2/4✓ Branch 52 → 53 taken 1 time.
✗ Branch 52 → 600 not taken.
✓ Branch 54 → 55 taken 1 time.
✗ Branch 54 → 600 not taken.
|
1 | const int fillStart = src->GetHeight() * dst->GetPitch(); |
| 2011 | |||
| 2012 |
1/4✓ Branch 55 → 56 taken 1 time.
✗ Branch 55 → 57 not taken.
✗ Branch 55 → 67 not taken.
✗ Branch 55 → 77 not taken.
|
1 | switch (pixelsize) { |
| 2013 | 1 | case 1: memset(dstp + fillStart, plane_default_black[0], fillSize); break; | |
| 2014 | ✗ | case 2: std::fill_n((uint16_t *)(dstp + fillStart), fillSize / sizeof(uint16_t), plane_default_black[0]); break; | |
| 2015 | ✗ | case 4: std::fill_n((float *)(dstp + fillStart), fillSize / sizeof(float), plane_default_black_f[0]); break; | |
| 2016 | } | ||
| 2017 | |||
| 2018 | // first plane is already processed | ||
| 2019 | // dont't touch Alpha | ||
| 2020 |
2/2✓ Branch 116 → 78 taken 2 times.
✓ Branch 116 → 117 taken 1 time.
|
3 | for (int p = 1; p < planecount; p++) { |
| 2021 | 2 | const int plane = planes[p]; | |
| 2022 |
1/2✓ Branch 79 → 80 taken 2 times.
✗ Branch 79 → 600 not taken.
|
2 | BYTE* ptr = dst->GetWritePtr(plane); |
| 2023 | |||
| 2024 |
3/6✓ Branch 81 → 82 taken 2 times.
✗ Branch 81 → 600 not taken.
✓ Branch 83 → 84 taken 2 times.
✗ Branch 83 → 600 not taken.
✓ Branch 85 → 86 taken 2 times.
✗ Branch 85 → 600 not taken.
|
2 | const int fillSize = (dst->GetHeight(plane) - src->GetHeight(plane)) * dst->GetPitch(plane); |
| 2025 |
2/4✓ Branch 87 → 88 taken 2 times.
✗ Branch 87 → 600 not taken.
✓ Branch 89 → 90 taken 2 times.
✗ Branch 89 → 600 not taken.
|
2 | const int fillStart = src->GetHeight(plane) * dst->GetPitch(plane); |
| 2026 |
1/4✓ Branch 90 → 91 taken 2 times.
✗ Branch 90 → 95 not taken.
✗ Branch 90 → 105 not taken.
✗ Branch 90 → 115 not taken.
|
2 | switch (pixelsize) { |
| 2027 |
1/2✗ Branch 91 → 92 not taken.
✓ Branch 91 → 93 taken 2 times.
|
2 | case 1: memset(ptr + fillStart, RGB ? 0 : plane_default_black[p], fillSize); break; |
| 2028 | ✗ | case 2: std::fill_n((uint16_t*)(ptr + fillStart), fillSize / sizeof(uint16_t), plane_default_black[p]); break; | |
| 2029 | ✗ | case 4: std::fill_n((float*)(ptr + fillStart), fillSize / sizeof(float), plane_default_black_f[p]); break; | |
| 2030 | } | ||
| 2031 | } | ||
| 2032 | } | ||
| 2033 | } | ||
| 2034 | |||
| 2035 | // counters | ||
| 2036 | 1 | int bufsize = sizeof(uint32_t)*show_size; | |
| 2037 |
1/2✓ Branch 117 → 118 taken 1 time.
✗ Branch 117 → 600 not taken.
|
1 | uint32_t *histPlane1 = static_cast<uint32_t*>(env->Allocate(bufsize * planecount, 16, AVS_NORMAL_ALLOC)); |
| 2038 |
1/2✗ Branch 118 → 119 not taken.
✓ Branch 118 → 120 taken 1 time.
|
1 | if (!histPlane1) |
| 2039 | ✗ | env->ThrowError("Histogram: Could not reserve memory."); | |
| 2040 | uint32_t *histPlanes[3] = { | ||
| 2041 | histPlane1, | ||
| 2042 | 1 | planecount == 1 ? nullptr : histPlane1 + show_size, | |
| 2043 | 1 | planecount == 1 ? nullptr : histPlane1 + 2 * show_size | |
| 2044 |
2/4✓ Branch 120 → 121 taken 1 time.
✗ Branch 120 → 122 not taken.
✓ Branch 123 → 124 taken 1 time.
✗ Branch 123 → 125 not taken.
|
2 | }; |
| 2045 | 1 | std::fill_n(histPlane1, show_size * planecount, 0); | |
| 2046 | |||
| 2047 |
1/2✓ Branch 135 → 136 taken 1 time.
✗ Branch 135 → 137 not taken.
|
1 | const int xstart = keepsource ? origwidth : 0; // drawing starts at this column |
| 2048 | |||
| 2049 | // copy planes | ||
| 2050 | // luma or G | ||
| 2051 |
1/2✓ Branch 138 → 139 taken 1 time.
✗ Branch 138 → 150 not taken.
|
1 | if (keepsource) { |
| 2052 |
6/12✓ Branch 140 → 141 taken 1 time.
✗ Branch 140 → 600 not taken.
✓ Branch 142 → 143 taken 1 time.
✗ Branch 142 → 600 not taken.
✓ Branch 144 → 145 taken 1 time.
✗ Branch 144 → 600 not taken.
✓ Branch 146 → 147 taken 1 time.
✗ Branch 146 → 600 not taken.
✓ Branch 148 → 149 taken 1 time.
✗ Branch 148 → 600 not taken.
✓ Branch 149 → 150 taken 1 time.
✗ Branch 149 → 600 not taken.
|
1 | env->BitBlt(dstp, dst->GetPitch(), src->GetReadPtr(), src->GetPitch(), src->GetRowSize(), src->GetHeight()); |
| 2053 | } | ||
| 2054 |
2/4✓ Branch 150 → 151 taken 1 time.
✗ Branch 150 → 600 not taken.
✓ Branch 151 → 152 taken 1 time.
✗ Branch 151 → 595 not taken.
|
1 | if (vi.IsPlanar()) { |
| 2055 | // copy rest planes | ||
| 2056 |
1/2✓ Branch 152 → 153 taken 1 time.
✗ Branch 152 → 170 not taken.
|
1 | if (keepsource) { |
| 2057 |
3/4✓ Branch 168 → 169 taken 3 times.
✗ Branch 168 → 600 not taken.
✓ Branch 169 → 154 taken 2 times.
✓ Branch 169 → 170 taken 1 time.
|
3 | for (int p = 1; p < vi.NumComponents(); p++) { |
| 2058 | 2 | const int plane = planes[p]; | |
| 2059 |
7/14✓ Branch 155 → 156 taken 2 times.
✗ Branch 155 → 600 not taken.
✓ Branch 157 → 158 taken 2 times.
✗ Branch 157 → 600 not taken.
✓ Branch 159 → 160 taken 2 times.
✗ Branch 159 → 600 not taken.
✓ Branch 161 → 162 taken 2 times.
✗ Branch 161 → 600 not taken.
✓ Branch 163 → 164 taken 2 times.
✗ Branch 163 → 600 not taken.
✓ Branch 165 → 166 taken 2 times.
✗ Branch 165 → 600 not taken.
✓ Branch 166 → 167 taken 2 times.
✗ Branch 166 → 600 not taken.
|
2 | env->BitBlt(dst->GetWritePtr(plane), dst->GetPitch(plane), src->GetReadPtr(plane), src->GetPitch(plane), src->GetRowSize(plane), src->GetHeight(plane)); |
| 2060 | } | ||
| 2061 | } | ||
| 2062 | |||
| 2063 | 1 | const int max_show_pixel_value = show_size - 1; | |
| 2064 | |||
| 2065 | // --------------------------------------------------- | ||
| 2066 | // accumulate population: fill histogram array from pixels | ||
| 2067 |
2/2✓ Branch 313 → 171 taken 3 times.
✓ Branch 313 → 314 taken 1 time.
|
4 | for (int p = 0; p < planecount; p++) { |
| 2068 | 3 | const int plane = planes[p]; | |
| 2069 |
4/4✓ Branch 171 → 172 taken 2 times.
✓ Branch 171 → 173 taken 1 time.
✓ Branch 172 → 173 taken 1 time.
✓ Branch 172 → 174 taken 1 time.
|
3 | const bool chroma = (plane == PLANAR_U || plane == PLANAR_V); |
| 2070 |
1/2✓ Branch 176 → 177 taken 3 times.
✗ Branch 176 → 599 not taken.
|
3 | const BYTE* srcp = src->GetReadPtr(plane); |
| 2071 | |||
| 2072 |
1/2✓ Branch 178 → 179 taken 3 times.
✗ Branch 178 → 599 not taken.
|
3 | const int w = src->GetRowSize(plane) / pixelsize; |
| 2073 |
1/2✓ Branch 180 → 181 taken 3 times.
✗ Branch 180 → 599 not taken.
|
3 | const int h = src->GetHeight(plane); |
| 2074 |
1/2✓ Branch 182 → 183 taken 3 times.
✗ Branch 182 → 599 not taken.
|
3 | const int pitch = src->GetPitch(plane) / pixelsize; |
| 2075 | |||
| 2076 | // accumulator of current plane | ||
| 2077 | // size: show_size (256 or 1024) | ||
| 2078 | 3 | uint32_t *hist = histPlanes[p]; | |
| 2079 | |||
| 2080 | 3 | bits_conv_constants d; | |
| 2081 |
2/2✓ Branch 183 → 184 taken 2 times.
✓ Branch 183 → 205 taken 1 time.
|
3 | get_bits_conv_constants(d, chroma, full_range, full_range, bits_per_pixel/*source_bitdepth*/, show_bits /*target_bitdepth*/); |
| 2082 | |||
| 2083 |
1/2✓ Branch 235 → 236 taken 3 times.
✗ Branch 235 → 265 not taken.
|
3 | if(pixelsize==1) { |
| 2084 | 3 | const uint8_t *srcp8 = reinterpret_cast<const uint8_t *>(srcp); | |
| 2085 |
1/2✓ Branch 236 → 237 taken 3 times.
✗ Branch 236 → 243 not taken.
|
3 | if (show_bits == bits_per_pixel) { |
| 2086 | // Exact. 8 bit clip into 8 bit histogram | ||
| 2087 |
2/2✓ Branch 242 → 238 taken 6 times.
✓ Branch 242 → 312 taken 3 times.
|
9 | for (int y = 0; y < h; y++) { |
| 2088 |
2/2✓ Branch 240 → 239 taken 24 times.
✓ Branch 240 → 241 taken 6 times.
|
30 | for (int x = 0; x < w; x++) { |
| 2089 | 24 | hist[srcp8[x]]++; | |
| 2090 | } | ||
| 2091 | 6 | srcp8 += pitch; | |
| 2092 | } | ||
| 2093 | } | ||
| 2094 | else { | ||
| 2095 | // 8 bit clip into 8,9,... bit histogram | ||
| 2096 | ✗ | if (full_range) { | |
| 2097 | // full range: stretch | ||
| 2098 | ✗ | if (chroma) { | |
| 2099 | ✗ | const float dst_offset_plus_round = d.dst_offset + 0.5f; | |
| 2100 | ✗ | for (int y = 0; y < h; y++) { | |
| 2101 | ✗ | for (int x = 0; x < w; x++) { | |
| 2102 | ✗ | hist[clamp((int)((srcp8[x] - d.src_offset_i) * d.mul_factor + dst_offset_plus_round), 0, max_show_pixel_value)]++; | |
| 2103 | } | ||
| 2104 | ✗ | srcp8 += pitch; | |
| 2105 | } | ||
| 2106 | } | ||
| 2107 | else { | ||
| 2108 | // src_offset and dst_offset is 0 | ||
| 2109 | ✗ | for (int y = 0; y < h; y++) { | |
| 2110 | ✗ | for (int x = 0; x < w; x++) { | |
| 2111 | ✗ | hist[min((int)(srcp8[x] * d.mul_factor + 0.5f), max_show_pixel_value)]++; | |
| 2112 | } | ||
| 2113 | ✗ | srcp8 += pitch; | |
| 2114 | } | ||
| 2115 | } | ||
| 2116 | } | ||
| 2117 | else { | ||
| 2118 | ✗ | const int invshift = show_bits - bits_per_pixel; | |
| 2119 | // limited range: shift | ||
| 2120 | ✗ | for (int y = 0; y < h; y++) { | |
| 2121 | ✗ | for (int x = 0; x < w; x++) { | |
| 2122 | ✗ | hist[(int)srcp8[x] << invshift]++; | |
| 2123 | } | ||
| 2124 | ✗ | srcp8 += pitch; | |
| 2125 | } | ||
| 2126 | } | ||
| 2127 | } | ||
| 2128 | } | ||
| 2129 | ✗ | else if (pixelsize == 2) { | |
| 2130 | ✗ | const uint16_t* srcp16 = reinterpret_cast<const uint16_t*>(srcp); | |
| 2131 | ✗ | if (show_bits == bits_per_pixel) { | |
| 2132 | // Exact. e.g. 10 bit clip into 10 bit histogram | ||
| 2133 | ✗ | for (int y = 0; y < h; y++) { | |
| 2134 | ✗ | for (int x = 0; x < w; x++) { | |
| 2135 | ✗ | hist[min((int)srcp16[x], max_show_pixel_value)]++; | |
| 2136 | } | ||
| 2137 | ✗ | srcp16 += pitch; | |
| 2138 | } | ||
| 2139 | } | ||
| 2140 | else { | ||
| 2141 | // 10 bit clip into 8,9,10,11,12,... bit histogram | ||
| 2142 | ✗ | if (full_range) { | |
| 2143 | // full range: stretch | ||
| 2144 | ✗ | if (chroma) { | |
| 2145 | ✗ | const float dst_offset_plus_round = d.dst_offset + 0.5f; | |
| 2146 | ✗ | for (int y = 0; y < h; y++) { | |
| 2147 | ✗ | for (int x = 0; x < w; x++) { | |
| 2148 | ✗ | hist[clamp((int)((srcp16[x] - d.src_offset_i) * d.mul_factor + dst_offset_plus_round), 0, max_show_pixel_value)]++; | |
| 2149 | } | ||
| 2150 | ✗ | srcp16 += pitch; | |
| 2151 | } | ||
| 2152 | } | ||
| 2153 | else { | ||
| 2154 | // src_offset and dst_offset is 0 | ||
| 2155 | ✗ | for (int y = 0; y < h; y++) { | |
| 2156 | ✗ | for (int x = 0; x < w; x++) { | |
| 2157 | ✗ | hist[min((int)(srcp16[x] * d.mul_factor + 0.5f), max_show_pixel_value)]++; | |
| 2158 | } | ||
| 2159 | ✗ | srcp16 += pitch; | |
| 2160 | } | ||
| 2161 | } | ||
| 2162 | } | ||
| 2163 | else { | ||
| 2164 | // limited range: shift. Up or down | ||
| 2165 | ✗ | const int shift = bits_per_pixel - show_bits; | |
| 2166 | ✗ | if (shift < 0) { | |
| 2167 | // 10 bit clip into 11 bit histogram | ||
| 2168 | ✗ | int invshift = -shift; | |
| 2169 | ✗ | for (int y = 0; y < h; y++) { | |
| 2170 | ✗ | for (int x = 0; x < w; x++) { | |
| 2171 | ✗ | hist[min(srcp16[x] << invshift, max_show_pixel_value)]++; | |
| 2172 | } | ||
| 2173 | ✗ | srcp16 += pitch; | |
| 2174 | } | ||
| 2175 | } | ||
| 2176 | else { | ||
| 2177 | // e.g.10 bit clip into 8-9 bit histogram | ||
| 2178 | ✗ | const int round = 1 << (shift - 1); | |
| 2179 | ✗ | for (int y = 0; y < h; y++) { | |
| 2180 | ✗ | for (int x = 0; x < w; x++) { | |
| 2181 | ✗ | hist[min((srcp16[x] + round) >> shift, max_show_pixel_value)]++; | |
| 2182 | } | ||
| 2183 | ✗ | srcp16 += pitch; | |
| 2184 | } | ||
| 2185 | } | ||
| 2186 | } | ||
| 2187 | } | ||
| 2188 | } | ||
| 2189 | else { | ||
| 2190 | // create fake Histogram 32 bit float | ||
| 2191 | ✗ | const float *srcp32 = reinterpret_cast<const float *>(srcp); | |
| 2192 | ✗ | const float dst_offset_plus_round = d.dst_offset + 0.5f; | |
| 2193 | ✗ | for (int y = 0; y < h; y++) { | |
| 2194 | ✗ | for (int x = 0; x < w; x++) { | |
| 2195 | ✗ | hist[clamp((int)(srcp32[x] * d.mul_factor + dst_offset_plus_round), 0, max_show_pixel_value)]++; | |
| 2196 | } | ||
| 2197 | ✗ | srcp32 += pitch; | |
| 2198 | } | ||
| 2199 | } | ||
| 2200 | } | ||
| 2201 | // accumulate end | ||
| 2202 | // --------------------------------------------------- | ||
| 2203 | |||
| 2204 | 1 | int pos_shift = (show_bits - 8); | |
| 2205 | 1 | int show_middle_pos = (128 << pos_shift); | |
| 2206 | // draw planes | ||
| 2207 |
2/2✓ Branch 516 → 315 taken 3 times.
✓ Branch 516 → 517 taken 1 time.
|
4 | for (int p = 0; p < planecount; p++) { |
| 2208 | 3 | const int plane = planes[p]; | |
| 2209 | |||
| 2210 |
1/2✓ Branch 315 → 316 taken 3 times.
✗ Branch 315 → 600 not taken.
|
3 | int swidth = vi.GetPlaneWidthSubsampling(plane); |
| 2211 |
1/2✓ Branch 316 → 317 taken 3 times.
✗ Branch 316 → 600 not taken.
|
3 | int sheight = vi.GetPlaneHeightSubsampling(plane); |
| 2212 | |||
| 2213 | // Draw Unsafe zone (UV-graph) | ||
| 2214 | |||
| 2215 |
1/2✓ Branch 318 → 319 taken 3 times.
✗ Branch 318 → 600 not taken.
|
3 | unsigned char* pdstb = dst->GetWritePtr(plane); |
| 2216 | 3 | pdstb += (xstart*pixelsize) >> swidth; // next to the source image if kept | |
| 2217 | |||
| 2218 |
1/2✓ Branch 320 → 321 taken 3 times.
✗ Branch 320 → 600 not taken.
|
3 | const int dstPitch = dst->GetPitch(plane); |
| 2219 | |||
| 2220 | // Clear Y/U/V or B, R G | ||
| 2221 | 3 | BYTE *ptr = pdstb; | |
| 2222 |
3/4✓ Branch 346 → 347 taken 771 times.
✗ Branch 346 → 600 not taken.
✓ Branch 347 → 322 taken 768 times.
✓ Branch 347 → 348 taken 3 times.
|
771 | for (int y = 0; y < dst->GetHeight() >> sheight; y++) { |
| 2223 |
1/4✓ Branch 322 → 323 taken 768 times.
✗ Branch 322 → 324 not taken.
✗ Branch 322 → 334 not taken.
✗ Branch 322 → 344 not taken.
|
768 | switch (pixelsize) { |
| 2224 | 768 | case 1: memset(ptr, plane_default_black[p], show_size >> swidth); break; | |
| 2225 | ✗ | case 2: std::fill_n((uint16_t *)(ptr), show_size >> swidth, plane_default_black[p]); break; | |
| 2226 | ✗ | case 4: std::fill_n((float *)(ptr), show_size >> swidth, plane_default_black_f[p]); break; | |
| 2227 | } | ||
| 2228 | 768 | ptr += dstPitch; | |
| 2229 | } | ||
| 2230 | |||
| 2231 |
2/4✓ Branch 348 → 349 taken 3 times.
✗ Branch 348 → 376 not taken.
✗ Branch 349 → 350 not taken.
✓ Branch 349 → 376 taken 3 times.
|
3 | if (!RGB && markers) { |
| 2232 | // Draw Unsafe zone (Y-graph) | ||
| 2233 | ✗ | const int color_unsafeZones[3] = { 32, 16, 160 }; | |
| 2234 | ✗ | const float color_unsafeZones_f[3] = { c8tof(32), uv8tof(16), uv8tof(160) }; | |
| 2235 | ✗ | int color_usz = color_unsafeZones[p]; | |
| 2236 | ✗ | int color_i = color_usz << color_shift; | |
| 2237 | ✗ | float color_f = color_unsafeZones_f[p]; | |
| 2238 | ✗ | ptr = pdstb + 0 * dstPitch;; | |
| 2239 | |||
| 2240 | ✗ | for (int y = 0; y <= 64 >> sheight; y++) { | |
| 2241 | ✗ | int x = 0; | |
| 2242 | ✗ | for (; x < (16 << pos_shift) >> swidth; x++) { | |
| 2243 | ✗ | if (pixelsize == 1) | |
| 2244 | ✗ | ptr[x] = color_i; | |
| 2245 | ✗ | else if (pixelsize == 2) | |
| 2246 | ✗ | reinterpret_cast<uint16_t *>(ptr)[x] = color_i; | |
| 2247 | else | ||
| 2248 | ✗ | reinterpret_cast<float *>(ptr)[x] = color_f; | |
| 2249 | } | ||
| 2250 | ✗ | for (x = (236 << pos_shift) >> swidth; x < (show_size >> swidth); x++) { // or (235 << pos_shift) + 1? | |
| 2251 | ✗ | if (pixelsize == 1) | |
| 2252 | ✗ | ptr[x] = color_i; | |
| 2253 | ✗ | else if (pixelsize == 2) | |
| 2254 | ✗ | reinterpret_cast<uint16_t *>(ptr)[x] = color_i; | |
| 2255 | else | ||
| 2256 | ✗ | reinterpret_cast<float *>(ptr)[x] = color_f; | |
| 2257 | } | ||
| 2258 | ✗ | ptr += dstPitch; | |
| 2259 | } | ||
| 2260 | } | ||
| 2261 | |||
| 2262 |
1/2✗ Branch 376 → 377 not taken.
✓ Branch 376 → 515 taken 3 times.
|
3 | if (markers) { |
| 2263 | ✗ | if (RGB) { | |
| 2264 | // nice gradients | ||
| 2265 | int StartY; | ||
| 2266 | ✗ | switch (plane) { | |
| 2267 | ✗ | case PLANAR_R: StartY = 0 + 0; break; | |
| 2268 | ✗ | case PLANAR_G: StartY = 64 + 16; break; | |
| 2269 | ✗ | case PLANAR_B: StartY = 64 + 16 + 64 + 16; break; | |
| 2270 | } | ||
| 2271 | ✗ | ptr = pdstb + ((StartY) >> sheight) * dstPitch; | |
| 2272 | ✗ | for (int y = (StartY) >> sheight; y <= (StartY + 64) >> sheight; y++) { | |
| 2273 | ✗ | if (pixelsize == 1) { | |
| 2274 | ✗ | for (int x = 0; x < (show_size >> swidth); x++) { | |
| 2275 | ✗ | int color = x >> pos_shift; | |
| 2276 | ✗ | int color_i = color << color_shift; | |
| 2277 | ✗ | ptr[x] = color_i; | |
| 2278 | } | ||
| 2279 | } | ||
| 2280 | ✗ | else if (pixelsize == 2) { | |
| 2281 | ✗ | for (int x = 0; x < (show_size >> swidth); x++) { | |
| 2282 | ✗ | int color = x >> pos_shift; | |
| 2283 | ✗ | int color_i = color << color_shift; | |
| 2284 | ✗ | reinterpret_cast<uint16_t *>(ptr)[x] = color_i; | |
| 2285 | } | ||
| 2286 | } | ||
| 2287 | else { // pixelsize == 4 float | ||
| 2288 | ✗ | for (int x = 0; x < (show_size >> swidth); x++) { | |
| 2289 | ✗ | int color = x >> pos_shift; | |
| 2290 | ✗ | float color_f = color / 255.0f; | |
| 2291 | ✗ | reinterpret_cast<float *>(ptr)[x] = color_f; | |
| 2292 | } | ||
| 2293 | } | ||
| 2294 | ✗ | ptr += dstPitch; | |
| 2295 | } | ||
| 2296 | } | ||
| 2297 | else { | ||
| 2298 | ✗ | if (!isGrey) { | |
| 2299 | // UV gradients plus danger zones | ||
| 2300 | ✗ | for (int gradient_upper_lower = 0; gradient_upper_lower < 2; gradient_upper_lower++) | |
| 2301 | { | ||
| 2302 | // Draw upper and lower gradient | ||
| 2303 | // upper: x=0-16, R=G=255, B=0; x=128, R=G=B=0; x=240-255, R=G=0, B=255 | ||
| 2304 | // lower: x=0-16, R=0, G=B=255; x=128, R=G=B=0; x=240-255, R=255, G=B=0 | ||
| 2305 | ✗ | const int color1_upper_lower_gradient[2][3] = { { 210 / 2, 16 + 112 / 2, 128 },{ 170 / 2, 128, 16 + 112 / 2 } }; | |
| 2306 | ✗ | const int color2_upper_lower_gradient[2][3] = { { 41 / 2, 240 - 112 / 2, 128 },{ 81 / 2, 128, 240 - 112 / 2 } }; | |
| 2307 | ✗ | float color1_upper_lower_gradient_f[2][3] = { { c8tof(210 / 2), uv8tof(16 + 112 / 2), uv8tof(128) },{ c8tof(170 / 2), uv8tof(128), uv8tof(16 + 112 / 2) } }; | |
| 2308 | ✗ | float color2_upper_lower_gradient_f[2][3] = { { c8tof(41 / 2), uv8tof(240 - 112 / 2), uv8tof(128) },{ c8tof(81 / 2), uv8tof(128), uv8tof(240 - 112 / 2) } }; | |
| 2309 | ✗ | int color = color1_upper_lower_gradient[gradient_upper_lower][p]; | |
| 2310 | ✗ | int color_i = color << color_shift; | |
| 2311 | ✗ | float color_f = color1_upper_lower_gradient_f[gradient_upper_lower][p]; | |
| 2312 | |||
| 2313 | ✗ | int color2 = color2_upper_lower_gradient[gradient_upper_lower][p]; | |
| 2314 | ✗ | int color2_i = color2 << color_shift; | |
| 2315 | ✗ | float color2_f = color2_upper_lower_gradient_f[gradient_upper_lower][p];; | |
| 2316 | |||
| 2317 | // upper only for planar U and Y | ||
| 2318 | ✗ | if (plane == PLANAR_V && gradient_upper_lower == 0) | |
| 2319 | ✗ | continue; | |
| 2320 | // lower only for planar V and Y | ||
| 2321 | ✗ | if (plane == PLANAR_U && gradient_upper_lower == 1) | |
| 2322 | ✗ | continue; | |
| 2323 | ✗ | int StartY = gradient_upper_lower == 0 ? 64 + 16 : 128 + 32; | |
| 2324 | ✗ | ptr = pdstb + ((StartY) >> sheight) * dstPitch; | |
| 2325 | // we are drawing at the 64th relative line as well. | ||
| 2326 | ✗ | for (int y = (StartY) >> sheight; y <= (StartY + 64) >> sheight; y++) { | |
| 2327 | ✗ | int x = 0; | |
| 2328 | // 0..15, (scaled) left danger area | ||
| 2329 | ✗ | const int left_limit = ((16 << pos_shift) >> swidth) - 1; | |
| 2330 | ✗ | if (pixelsize == 1) { | |
| 2331 | ✗ | for (; x < left_limit; x++) | |
| 2332 | ✗ | ptr[x] = color_i; | |
| 2333 | } | ||
| 2334 | ✗ | else if (pixelsize == 2) { | |
| 2335 | ✗ | for (; x < left_limit; x++) | |
| 2336 | ✗ | reinterpret_cast<uint16_t*>(ptr)[x] = color_i; | |
| 2337 | } | ||
| 2338 | else { // float | ||
| 2339 | ✗ | for (; x < left_limit; x++) | |
| 2340 | ✗ | reinterpret_cast<float*>(ptr)[x] = color_f; | |
| 2341 | } | ||
| 2342 | |||
| 2343 | ✗ | if (plane == PLANAR_Y) { | |
| 2344 | // from 16 to middle point | ||
| 2345 | ✗ | if (pixelsize == 1) { | |
| 2346 | ✗ | for (; x <= show_middle_pos; x++) { | |
| 2347 | ✗ | int color3 = | |
| 2348 | ✗ | (gradient_upper_lower == 0) ? | |
| 2349 | ✗ | (((show_middle_pos - x) * 15) >> 3) >> pos_shift : // *1.875 | |
| 2350 | ✗ | ((show_middle_pos - x) * 99515) >> 16 >> pos_shift; // *1.518 | |
| 2351 | ✗ | int color3_i = color3 << color_shift; | |
| 2352 | ✗ | ptr[x] = color3_i; | |
| 2353 | } | ||
| 2354 | } | ||
| 2355 | ✗ | else if (pixelsize == 2) { | |
| 2356 | ✗ | for (; x <= show_middle_pos; x++) { | |
| 2357 | ✗ | int color3 = | |
| 2358 | ✗ | (gradient_upper_lower == 0) ? | |
| 2359 | ✗ | (((show_middle_pos - x) * 15) >> 3) >> pos_shift : // *1.875 | |
| 2360 | ✗ | ((show_middle_pos - x) * 99515) >> 16 >> pos_shift; // *1.518 | |
| 2361 | ✗ | int color3_i = color3 << color_shift; | |
| 2362 | ✗ | reinterpret_cast<uint16_t*>(ptr)[x] = color3_i; | |
| 2363 | } | ||
| 2364 | } | ||
| 2365 | else { // float | ||
| 2366 | ✗ | for (; x <= show_middle_pos; x++) { | |
| 2367 | ✗ | int color3 = | |
| 2368 | ✗ | (gradient_upper_lower == 0) ? | |
| 2369 | ✗ | (((show_middle_pos - x) * 15) >> 3) >> pos_shift : // *1.875 | |
| 2370 | ✗ | ((show_middle_pos - x) * 99515) >> 16 >> pos_shift; // *1.518 | |
| 2371 | ✗ | float color3_f = color3 / 255.0f; // no shift this is Y | |
| 2372 | ✗ | reinterpret_cast<float*>(ptr)[x] = color3_f; | |
| 2373 | } | ||
| 2374 | } | ||
| 2375 | } | ||
| 2376 | |||
| 2377 | // Y: from middle point to white point | ||
| 2378 | // other plane: gradient | ||
| 2379 | ✗ | if (plane == PLANAR_Y) { | |
| 2380 | ✗ | if (pixelsize == 1) { | |
| 2381 | ✗ | for (; x <= (240 << pos_shift) >> swidth; x++) { | |
| 2382 | ✗ | int color4 = | |
| 2383 | ✗ | (gradient_upper_lower == 0) ? | |
| 2384 | ✗ | ((x - show_middle_pos) * 24001) >> 16 >> pos_shift : // *0.366 | |
| 2385 | ✗ | ((x - show_middle_pos) * 47397) >> 16 >> pos_shift; // *0.723 | |
| 2386 | ✗ | int color4_i = color4 << color_shift; | |
| 2387 | ✗ | ptr[x] = color4_i; | |
| 2388 | } | ||
| 2389 | } | ||
| 2390 | ✗ | else if (pixelsize == 2) { | |
| 2391 | ✗ | for (; x <= (240 << pos_shift) >> swidth; x++) { | |
| 2392 | ✗ | int color4 = | |
| 2393 | ✗ | (gradient_upper_lower == 0) ? | |
| 2394 | ✗ | ((x - show_middle_pos) * 24001) >> 16 >> pos_shift : // *0.366 | |
| 2395 | ✗ | ((x - show_middle_pos) * 47397) >> 16 >> pos_shift; // *0.723 | |
| 2396 | ✗ | int color4_i = color4 << color_shift; | |
| 2397 | ✗ | reinterpret_cast<uint16_t*>(ptr)[x] = color4_i; | |
| 2398 | } | ||
| 2399 | } | ||
| 2400 | else { // float | ||
| 2401 | ✗ | for (; x <= (240 << pos_shift) >> swidth; x++) { | |
| 2402 | ✗ | int color4 = | |
| 2403 | ✗ | (gradient_upper_lower == 0) ? | |
| 2404 | ✗ | ((x - show_middle_pos) * 24001) >> 16 >> pos_shift : // *0.366 | |
| 2405 | ✗ | ((x - show_middle_pos) * 47397) >> 16 >> pos_shift; // *0.723 | |
| 2406 | ✗ | float color4_f = color4 / 255.0f; // no shift, this is Y | |
| 2407 | ✗ | reinterpret_cast<float*>(ptr)[x] = color4_f; | |
| 2408 | } | ||
| 2409 | } | ||
| 2410 | } | ||
| 2411 | else { | ||
| 2412 | // plane == U or V | ||
| 2413 | ✗ | if (pixelsize == 1) { | |
| 2414 | ✗ | for (; x <= (240 << pos_shift) >> swidth; x++) { | |
| 2415 | ✗ | int color4 = (x << swidth) >> pos_shift; | |
| 2416 | ✗ | int color4_i = color4 << color_shift; | |
| 2417 | ✗ | ptr[x] = color4_i; | |
| 2418 | } | ||
| 2419 | } | ||
| 2420 | ✗ | else if (pixelsize == 2) { | |
| 2421 | ✗ | for (; x <= (240 << pos_shift) >> swidth; x++) { | |
| 2422 | ✗ | int color4 = (x << swidth) >> pos_shift; | |
| 2423 | ✗ | int color4_i = color4 << color_shift; | |
| 2424 | ✗ | reinterpret_cast<uint16_t*>(ptr)[x] = color4_i; | |
| 2425 | } | ||
| 2426 | } | ||
| 2427 | else { // float | ||
| 2428 | ✗ | for (; x <= (240 << pos_shift) >> swidth; x++) { | |
| 2429 | ✗ | int color4 = (x << swidth) >> pos_shift; | |
| 2430 | ✗ | reinterpret_cast<float*>(ptr)[x] = uv8tof(color4); | |
| 2431 | } | ||
| 2432 | } | ||
| 2433 | } | ||
| 2434 | |||
| 2435 | ✗ | if (pixelsize == 1) { | |
| 2436 | ✗ | for (; x < (show_size >> swidth); x++) | |
| 2437 | ✗ | ptr[x] = color2_i; | |
| 2438 | } | ||
| 2439 | ✗ | else if (pixelsize == 2) { | |
| 2440 | ✗ | for (; x < (show_size >> swidth); x++) | |
| 2441 | ✗ | reinterpret_cast<uint16_t*>(ptr)[x] = color2_i; | |
| 2442 | } | ||
| 2443 | else { // float | ||
| 2444 | ✗ | for (; x < (show_size >> swidth); x++) | |
| 2445 | ✗ | reinterpret_cast<float*>(ptr)[x] = color2_f; | |
| 2446 | } | ||
| 2447 | |||
| 2448 | ✗ | ptr += dstPitch; | |
| 2449 | } // for y gradient draw | ||
| 2450 | } // gradient for upper lower | ||
| 2451 | } | ||
| 2452 | } // gradients for RGB/UV | ||
| 2453 | } // if markers | ||
| 2454 | } // planes for | ||
| 2455 | |||
| 2456 | // Draw dotted centerline | ||
| 2457 | // YUV: only 1 plane (PLANAR_Y) | ||
| 2458 |
3/4✗ Branch 533 → 534 not taken.
✓ Branch 533 → 535 taken 2 times.
✓ Branch 536 → 518 taken 1 time.
✓ Branch 536 → 537 taken 1 time.
|
2 | for (int p = 0; p < (RGB ? 3 : 1); p++) { |
| 2459 | 1 | const int plane = planes[p]; | |
| 2460 | |||
| 2461 | 1 | int color = 128; // also good for RGB | |
| 2462 | 1 | int color_i = color << color_shift; | |
| 2463 | 1 | float color_f = 0.5f; | |
| 2464 | |||
| 2465 |
1/2✓ Branch 519 → 520 taken 1 time.
✗ Branch 519 → 600 not taken.
|
1 | const int dstPitch = dst->GetPitch(plane); |
| 2466 | |||
| 2467 |
1/2✓ Branch 521 → 522 taken 1 time.
✗ Branch 521 → 600 not taken.
|
1 | unsigned char* pdstb = dst->GetWritePtr(plane); |
| 2468 | 1 | pdstb += (xstart * pixelsize); // next to the original clip (if kept), working only on Y plane: no ">> swidth" needed | |
| 2469 | 1 | BYTE* ptr = pdstb; | |
| 2470 | |||
| 2471 |
1/2✗ Branch 522 → 523 not taken.
✓ Branch 522 → 532 taken 1 time.
|
1 | if (markers) { |
| 2472 | // omit centerline if markers == false | ||
| 2473 | // height of 64, 16 pixels between | ||
| 2474 | // we are drawing at the 64th/224th relative line as well. | ||
| 2475 | ✗ | for (int y = 0; y <= 64 + (planecount - 1) * (16 + 64); y++) { | |
| 2476 | ✗ | if ((y & 3) > 1) { | |
| 2477 | ✗ | if (pixelsize == 1) ptr[show_middle_pos] = color_i; | |
| 2478 | ✗ | else if (pixelsize == 2) reinterpret_cast<uint16_t*>(ptr)[show_middle_pos] = color_i; | |
| 2479 | ✗ | else reinterpret_cast<float*>(ptr)[show_middle_pos] = color_f; | |
| 2480 | |||
| 2481 | } | ||
| 2482 | ✗ | ptr += dstPitch; | |
| 2483 | } | ||
| 2484 | } | ||
| 2485 | } | ||
| 2486 | |||
| 2487 |
3/4✗ Branch 591 → 592 not taken.
✓ Branch 591 → 593 taken 2 times.
✓ Branch 594 → 538 taken 1 time.
✓ Branch 594 → 595 taken 1 time.
|
2 | for (int p = 0; p < (RGB ? 3 : 1); p++) { |
| 2488 | 1 | const int plane = planes[p]; | |
| 2489 | |||
| 2490 |
1/2✓ Branch 539 → 540 taken 1 time.
✗ Branch 539 → 600 not taken.
|
1 | const int dstPitch = dst->GetPitch(plane); |
| 2491 | |||
| 2492 |
1/2✓ Branch 541 → 542 taken 1 time.
✗ Branch 541 → 600 not taken.
|
1 | unsigned char* pdstb = dst->GetWritePtr(plane); |
| 2493 | 1 | pdstb += (xstart * pixelsize); // next to the original clip (if kept), working only on Y plane: no ">> swidth" needed | |
| 2494 | |||
| 2495 | // have to draw up to three parts: Y or Y,U,V or R,G,B | ||
| 2496 |
2/2✓ Branch 589 → 543 taken 3 times.
✓ Branch 589 → 590 taken 1 time.
|
4 | for (int n = 0; n < planecount; n++) { |
| 2497 | |||
| 2498 | // Draw histograms | ||
| 2499 | |||
| 2500 | // total pixel count must be divided by subsampling factors for U and V | ||
| 2501 |
1/2✓ Branch 544 → 545 taken 3 times.
✗ Branch 544 → 600 not taken.
|
3 | int src_width = src->GetRowSize(planes[n]) / pixelsize; |
| 2502 |
1/2✓ Branch 546 → 547 taken 3 times.
✗ Branch 546 → 600 not taken.
|
3 | int src_height = src->GetHeight(planes[n]); |
| 2503 | |||
| 2504 |
1/2✓ Branch 547 → 548 taken 3 times.
✗ Branch 547 → 600 not taken.
|
3 | const uint32_t clampval = (int)((src_width*src_height)*option.AsDblDef(100.0) / 100.0); // Population limit % factor |
| 2505 | 3 | uint32_t maxval = 0; | |
| 2506 | uint32_t *hist; | ||
| 2507 | |||
| 2508 | 3 | hist = histPlanes[n]; | |
| 2509 |
2/2✓ Branch 553 → 549 taken 768 times.
✓ Branch 553 → 554 taken 3 times.
|
771 | for (int i = 0; i < show_size; i++) { |
| 2510 |
1/2✗ Branch 549 → 550 not taken.
✓ Branch 549 → 551 taken 768 times.
|
768 | if (hist[i] > clampval) hist[i] = clampval; |
| 2511 | 768 | maxval = max(hist[i], maxval); | |
| 2512 | } | ||
| 2513 | |||
| 2514 | // factor 0%: maxval may stay at 0. | ||
| 2515 |
1/2✓ Branch 554 → 555 taken 3 times.
✗ Branch 554 → 556 not taken.
|
3 | float scale = maxval == 0 ? 64.0f : float(64.0 / maxval); |
| 2516 | |||
| 2517 |
1/2✗ Branch 557 → 558 not taken.
✓ Branch 557 → 559 taken 3 times.
|
3 | int color = RGB ? 255 : 235; // also good for RGB |
| 2518 |
1/2✗ Branch 560 → 561 not taken.
✓ Branch 560 → 562 taken 3 times.
|
3 | int color_i = RGB ? (int)(color * color_shift_factor + 0.5f) : color << color_shift; |
| 2519 | 3 | float color_f = color / 255.0f; | |
| 2520 | |||
| 2521 | int Y_pos; | ||
| 2522 |
3/4✓ Branch 563 → 564 taken 1 time.
✓ Branch 563 → 568 taken 1 time.
✓ Branch 563 → 572 taken 1 time.
✗ Branch 563 → 576 not taken.
|
3 | switch (n) { // n: YUV 012, GBR 012 |
| 2523 |
1/2✗ Branch 564 → 565 not taken.
✓ Branch 564 → 566 taken 1 time.
|
1 | case 0: Y_pos = RGB ? 128 + 16 : 64 + 0; break; // Y or G |
| 2524 |
1/2✗ Branch 568 → 569 not taken.
✓ Branch 568 → 570 taken 1 time.
|
1 | case 1: Y_pos = RGB ? 192 + 32 : 128 + 16; break; // U or B |
| 2525 |
1/2✗ Branch 572 → 573 not taken.
✓ Branch 572 → 574 taken 1 time.
|
1 | case 2: Y_pos = RGB ? 64 + 0 : 192 + 32; break; // V or R |
| 2526 | } | ||
| 2527 | |||
| 2528 |
2/2✓ Branch 587 → 577 taken 768 times.
✓ Branch 587 → 588 taken 3 times.
|
771 | for (int x = 0; x < show_size; x++) { |
| 2529 | 768 | float scaled_h = (float)hist[x] * scale; | |
| 2530 | 768 | int h = Y_pos - min((int)scaled_h, 64) + 1; | |
| 2531 | |||
| 2532 | 768 | uint8_t *ptr = pdstb + (Y_pos + 1) * dstPitch; | |
| 2533 | |||
| 2534 | // Start from below the baseline | ||
| 2535 |
2/2✓ Branch 585 → 579 taken 768 times.
✓ Branch 585 → 586 taken 768 times.
|
1536 | for (int y = Y_pos + 1; y > h; y--) { |
| 2536 |
1/2✓ Branch 579 → 580 taken 768 times.
✗ Branch 579 → 581 not taken.
|
768 | if (pixelsize == 1) ptr[x] = color_i; |
| 2537 | ✗ | else if (pixelsize == 2) reinterpret_cast<uint16_t *>(ptr)[x] = color_i; | |
| 2538 | ✗ | else reinterpret_cast<float *>(ptr)[x] = color_f; | |
| 2539 | 768 | ptr -= dstPitch; | |
| 2540 | } | ||
| 2541 | |||
| 2542 | } | ||
| 2543 | } | ||
| 2544 | } | ||
| 2545 | } | ||
| 2546 | |||
| 2547 |
1/2✓ Branch 595 → 596 taken 1 time.
✗ Branch 595 → 600 not taken.
|
1 | env->Free(histPlane1); |
| 2548 | |||
| 2549 | 1 | return dst; | |
| 2550 | 1 | } | |
| 2551 | |||
| 2552 | |||
| 2553 | 2 | void Histogram::ClassicLUTInit() | |
| 2554 | { | ||
| 2555 |
1/2✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 4 not taken.
|
2 | int internal_bits_per_pixel = (pixelsize == 4) ? 16 : bits_per_pixel; // 16bit histogram simulation for float |
| 2556 | |||
| 2557 | 2 | int tv_range_low = 16 << (internal_bits_per_pixel - 8); // 16 | |
| 2558 | 2 | int tv_range_hi_luma = 235 << (internal_bits_per_pixel - 8); // 16-235 | |
| 2559 | 2 | int range_luma = tv_range_hi_luma - tv_range_low; // 219 | |
| 2560 | // exptab: population count within a line -> brigtness mapping | ||
| 2561 | // exptab index (population) is maximized at 255 during the actual drawing | ||
| 2562 | 2 | exptab.resize(256); | |
| 2563 | 2 | const double K = log(0.5 / 219) / 255.0; // approx -1/42 | |
| 2564 | 2 | const int limit68 = 68 << (internal_bits_per_pixel - 8); | |
| 2565 | // exptab: pixel values for final drawing | ||
| 2566 | 2 | exptab[0] = tv_range_low; | |
| 2567 |
2/2✓ Branch 13 → 8 taken 508 times.
✓ Branch 13 → 14 taken 2 times.
|
510 | for (int i = 1; i < 255; i++) { |
| 2568 | 508 | exptab[i] = uint16_t(tv_range_low + 0.5 + range_luma * (1 - exp(i*K))); // 16.5 + 219* | |
| 2569 |
2/2✓ Branch 10 → 11 taken 98 times.
✓ Branch 10 → 12 taken 410 times.
|
508 | if (exptab[i] <= tv_range_hi_luma - limit68) |
| 2570 | 98 | E167 = i; // index of last value less than... for drawing lower extremes | |
| 2571 | } | ||
| 2572 | 2 | exptab[255] = tv_range_hi_luma; | |
| 2573 | 2 | } | |
| 2574 | |||
| 2575 | 3 | PVideoFrame Histogram::DrawModeClassic(int n, IScriptEnvironment* env) | |
| 2576 | { | ||
| 2577 | |||
| 2578 | 3 | int show_size = 1 << show_bits; | |
| 2579 | |||
| 2580 | 3 | int hist_tv_range_low = 16 << (show_bits - 8); // 16 | |
| 2581 | 3 | int hist_tv_range_hi_luma = 235 << (show_bits - 8); // 16-235 | |
| 2582 | 3 | int hist_range_luma = hist_tv_range_hi_luma - hist_tv_range_low; // 219 | |
| 2583 | 3 | int hist_mid_range_luma = (hist_range_luma + 1) / 2 + hist_tv_range_low - 1; // in Classic Avisynth somehow 124 was fixed for this | |
| 2584 | // 235-16 = 219 / 2 => 110; 110 + 16 - 1 = 125.0 | ||
| 2585 | |||
| 2586 |
1/2✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 4 not taken.
|
3 | int internal_bits_per_pixel = (pixelsize == 4) ? 16 : bits_per_pixel; // 16bit histogram simulation for float |
| 2587 | |||
| 2588 | 3 | int middle_chroma = 1 << (internal_bits_per_pixel - 1); // 128 | |
| 2589 | |||
| 2590 | 3 | const int source_width = origwidth; | |
| 2591 |
2/2✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 2 times.
|
3 | const int xstart = keepsource ? origwidth : 0; // drawing starts at this column |
| 2592 | |||
| 2593 |
1/2✓ Branch 9 → 10 taken 3 times.
✗ Branch 9 → 276 not taken.
|
3 | PVideoFrame src = child->GetFrame(n, env); |
| 2594 |
1/2✓ Branch 11 → 12 taken 3 times.
✗ Branch 11 → 274 not taken.
|
3 | const BYTE* srcp = src->GetReadPtr(); |
| 2595 |
1/2✓ Branch 13 → 14 taken 3 times.
✗ Branch 13 → 274 not taken.
|
3 | const int srcpitch = src->GetPitch(); |
| 2596 | |||
| 2597 |
1/2✓ Branch 14 → 15 taken 3 times.
✗ Branch 14 → 274 not taken.
|
3 | PVideoFrame dst = env->NewVideoFrameP(vi, &src); |
| 2598 |
1/2✓ Branch 16 → 17 taken 3 times.
✗ Branch 16 → 272 not taken.
|
3 | BYTE* pdst = dst->GetWritePtr(); |
| 2599 |
1/2✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 272 not taken.
|
3 | const int dstpitch = dst->GetPitch(); |
| 2600 | |||
| 2601 |
2/2✓ Branch 19 → 20 taken 1 time.
✓ Branch 19 → 31 taken 2 times.
|
3 | if (keepsource) { |
| 2602 |
6/12✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 272 not taken.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 272 not taken.
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 272 not taken.
✓ Branch 27 → 28 taken 1 time.
✗ Branch 27 → 272 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 272 not taken.
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 272 not taken.
|
1 | env->BitBlt(pdst, dst->GetPitch(), src->GetReadPtr(), src->GetPitch(), src->GetRowSize(), src->GetHeight()); |
| 2603 | } | ||
| 2604 |
2/4✓ Branch 31 → 32 taken 3 times.
✗ Branch 31 → 272 not taken.
✓ Branch 32 → 33 taken 3 times.
✗ Branch 32 → 227 not taken.
|
3 | if (vi.IsPlanar()) { |
| 2605 |
2/2✓ Branch 33 → 34 taken 1 time.
✓ Branch 33 → 60 taken 2 times.
|
3 | if (keepsource) { |
| 2606 |
7/14✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 271 not taken.
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 271 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 271 not taken.
✓ Branch 41 → 42 taken 1 time.
✗ Branch 41 → 271 not taken.
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 271 not taken.
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 271 not taken.
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 271 not taken.
|
1 | env->BitBlt(dst->GetWritePtr(PLANAR_U), dst->GetPitch(PLANAR_U), src->GetReadPtr(PLANAR_U), src->GetPitch(PLANAR_U), src->GetRowSize(PLANAR_U), src->GetHeight(PLANAR_U)); |
| 2607 |
7/14✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 271 not taken.
✓ Branch 50 → 51 taken 1 time.
✗ Branch 50 → 271 not taken.
✓ Branch 52 → 53 taken 1 time.
✗ Branch 52 → 271 not taken.
✓ Branch 54 → 55 taken 1 time.
✗ Branch 54 → 271 not taken.
✓ Branch 56 → 57 taken 1 time.
✗ Branch 56 → 271 not taken.
✓ Branch 58 → 59 taken 1 time.
✗ Branch 58 → 271 not taken.
✓ Branch 59 → 60 taken 1 time.
✗ Branch 59 → 271 not taken.
|
1 | env->BitBlt(dst->GetWritePtr(PLANAR_V), dst->GetPitch(PLANAR_V), src->GetReadPtr(PLANAR_V), src->GetPitch(PLANAR_V), src->GetRowSize(PLANAR_V), src->GetHeight(PLANAR_V)); |
| 2608 | } | ||
| 2609 | |||
| 2610 | // luma | ||
| 2611 |
1/2✓ Branch 61 → 62 taken 3 times.
✗ Branch 61 → 271 not taken.
|
3 | const int height = src->GetHeight(PLANAR_Y); |
| 2612 | |||
| 2613 | 3 | std::vector<int> hist; | |
| 2614 |
1/2✓ Branch 63 → 64 taken 3 times.
✗ Branch 63 → 269 not taken.
|
3 | hist.resize(1ULL << show_bits); |
| 2615 | |||
| 2616 |
2/2✓ Branch 160 → 65 taken 6 times.
✓ Branch 160 → 161 taken 3 times.
|
9 | for (int y = 0; y<height; ++y) { |
| 2617 | 6 | std::fill(hist.begin(), hist.end(), 0); | |
| 2618 | // accumulate line population | ||
| 2619 |
1/2✓ Branch 74 → 75 taken 6 times.
✗ Branch 74 → 79 not taken.
|
6 | if(pixelsize==1) { |
| 2620 | // 8 bit clip into 8,9,... bit histogram | ||
| 2621 | 6 | int invshift = show_bits - 8; | |
| 2622 |
2/2✓ Branch 78 → 76 taken 48 times.
✓ Branch 78 → 96 taken 6 times.
|
54 | for (int x = 0; x<source_width; ++x) { |
| 2623 | 48 | hist[srcp[x] << invshift]++; | |
| 2624 | } | ||
| 2625 | } | ||
| 2626 | ✗ | else if (pixelsize == 2) { | |
| 2627 | ✗ | const uint16_t *srcp16 = reinterpret_cast<const uint16_t *>(srcp); | |
| 2628 | ✗ | int shift = bits_per_pixel - show_bits; | |
| 2629 | ✗ | int max_show_pixel_value = show_size - 1; | |
| 2630 | ✗ | if (shift < 0) { | |
| 2631 | // 10 bit clip into 11 bit histogram | ||
| 2632 | ✗ | int invshift = -shift; | |
| 2633 | ✗ | for (int x = 0; x < source_width; x++) { | |
| 2634 | ✗ | hist[min(srcp16[x] << invshift, max_show_pixel_value)]++; | |
| 2635 | } | ||
| 2636 | } else { | ||
| 2637 | // e.g.10 bit clip into 8-9-10 bit histogram | ||
| 2638 | ✗ | for (int x = 0; x < source_width; x++) { | |
| 2639 | ✗ | hist[min(srcp16[x] >> shift, max_show_pixel_value)]++; | |
| 2640 | } | ||
| 2641 | } | ||
| 2642 | } | ||
| 2643 | else // pixelsize == 4 | ||
| 2644 | { | ||
| 2645 | // float | ||
| 2646 | ✗ | const float *srcp32 = reinterpret_cast<const float *>(srcp); | |
| 2647 | ✗ | const float multiplier = (float)(show_size - 1); | |
| 2648 | ✗ | for (int x = 0; x < source_width; x++) { | |
| 2649 | ✗ | hist[(intptr_t)(clamp(srcp32[x], 0.0f, 1.0f)*multiplier + 0.5f)]++; // luma, no shift needed | |
| 2650 | } | ||
| 2651 | } | ||
| 2652 | // accumulate end | ||
| 2653 | 6 | BYTE* const q = pdst + xstart * pixelsize; // write to frame | |
| 2654 |
1/2✗ Branch 96 → 97 not taken.
✓ Branch 96 → 139 taken 6 times.
|
6 | if (markers) { |
| 2655 | ✗ | if (pixelsize == 1) { | |
| 2656 | ✗ | for (int x = 0; x < show_size; ++x) { | |
| 2657 | ✗ | if (x<hist_tv_range_low || x == hist_mid_range_luma || x>hist_tv_range_hi_luma) { | |
| 2658 | ✗ | q[x] = (BYTE)exptab[min(E167, hist[x])] + 68; // brighter danger zone | |
| 2659 | } | ||
| 2660 | else { | ||
| 2661 | ✗ | q[x] = (BYTE)exptab[min(255, hist[x])]; | |
| 2662 | } | ||
| 2663 | } | ||
| 2664 | } | ||
| 2665 | ✗ | else if (pixelsize == 2) { | |
| 2666 | ✗ | uint16_t *dstp16 = reinterpret_cast<uint16_t *>(q); | |
| 2667 | ✗ | for (int x = 0; x < show_size; ++x) { | |
| 2668 | ✗ | int h = hist[x]; | |
| 2669 | ✗ | if (x<hist_tv_range_low || x == hist_mid_range_luma || x>hist_tv_range_hi_luma) { | |
| 2670 | ✗ | dstp16[x] = exptab[min(E167, h)] + (68 << (bits_per_pixel - 8)); | |
| 2671 | } | ||
| 2672 | else { | ||
| 2673 | ✗ | dstp16[x] = exptab[min(255, h)]; | |
| 2674 | } | ||
| 2675 | } | ||
| 2676 | } | ||
| 2677 | else { // pixelsize == 4 | ||
| 2678 | ✗ | float *dstp32 = reinterpret_cast<float *>(q); | |
| 2679 | ✗ | for (int x = 0; x < show_size; ++x) { | |
| 2680 | ✗ | int h = hist[x]; | |
| 2681 | ✗ | if (x<hist_tv_range_low || x == hist_mid_range_luma || x>hist_tv_range_hi_luma) { | |
| 2682 | ✗ | dstp32[x] = (exptab[min(E167, h)] + (68 << (internal_bits_per_pixel - 8))) / 65535.0f; // fake 0..65535 to 0..1.0 | |
| 2683 | } | ||
| 2684 | else { | ||
| 2685 | ✗ | dstp32[x] = exptab[min(255, h)] / 65535.0f; | |
| 2686 | } | ||
| 2687 | } | ||
| 2688 | } | ||
| 2689 | } | ||
| 2690 | else { | ||
| 2691 |
1/2✓ Branch 139 → 140 taken 6 times.
✗ Branch 139 → 146 not taken.
|
6 | if (pixelsize == 1) { |
| 2692 |
2/2✓ Branch 145 → 141 taken 1536 times.
✓ Branch 145 → 159 taken 6 times.
|
1542 | for (int x = 0; x < show_size; ++x) |
| 2693 | 1536 | q[x] = (BYTE)exptab[min(255, hist[x])]; | |
| 2694 | } | ||
| 2695 | ✗ | else if (pixelsize == 2) { | |
| 2696 | ✗ | uint16_t *dstp16 = reinterpret_cast<uint16_t *>(q); | |
| 2697 | ✗ | for (int x = 0; x < show_size; ++x) { | |
| 2698 | ✗ | int h = hist[x]; | |
| 2699 | ✗ | dstp16[x] = exptab[min(255, h)]; | |
| 2700 | } | ||
| 2701 | } | ||
| 2702 | else { // pixelsize == 4 | ||
| 2703 | ✗ | float *dstp32 = reinterpret_cast<float *>(q); | |
| 2704 | ✗ | for (int x = 0; x < show_size; ++x) { | |
| 2705 | ✗ | int h = hist[x]; | |
| 2706 | ✗ | dstp32[x] = exptab[min(255, h)] / 65535.0f; // fake 0..65535 to 0..1.0 | |
| 2707 | } | ||
| 2708 | } | ||
| 2709 | } | ||
| 2710 | 6 | srcp += srcpitch; | |
| 2711 | 6 | pdst += dstpitch; | |
| 2712 | } // end of pixel accumulation + luma | ||
| 2713 | |||
| 2714 | // chroma | ||
| 2715 |
1/2✓ Branch 162 → 163 taken 3 times.
✗ Branch 162 → 269 not taken.
|
3 | const int pitchUV = dst->GetPitch(PLANAR_U); |
| 2716 | |||
| 2717 |
1/2✗ Branch 163 → 164 not taken.
✓ Branch 163 → 225 taken 3 times.
|
3 | if (pitchUV != 0) { |
| 2718 | ✗ | const int subs = vi.GetPlaneWidthSubsampling(PLANAR_U); | |
| 2719 | ✗ | const int fact = 1<<subs; | |
| 2720 | |||
| 2721 | ✗ | BYTE* p2 = dst->GetWritePtr(PLANAR_U) + ((xstart*pixelsize) >> subs); // put it on the right | |
| 2722 | ✗ | BYTE* p3 = dst->GetWritePtr(PLANAR_V) + ((xstart*pixelsize) >> subs); // put it on the right | |
| 2723 | |||
| 2724 | // if markers==false parameter, keep neutral coloring | ||
| 2725 | ✗ | const uint16_t color_u_offlimit8 = markers ? 16 : 128; | |
| 2726 | ✗ | const uint16_t color_v_offlimit8 = markers ? 160 : 128; | |
| 2727 | ✗ | const uint16_t color_u_centermark8 = markers ? 160 : 128; | |
| 2728 | ✗ | const uint16_t color_v_centermark8 = markers ? 16 : 128; | |
| 2729 | |||
| 2730 | ✗ | const uint16_t color_u_offlimit = color_u_offlimit8 << (internal_bits_per_pixel - 8); | |
| 2731 | ✗ | const uint16_t color_v_offlimit = color_v_offlimit8 << (internal_bits_per_pixel - 8); | |
| 2732 | ✗ | const uint16_t color_u_centermark = color_u_centermark8 << (internal_bits_per_pixel - 8); | |
| 2733 | ✗ | const uint16_t color_v_centermark = color_v_centermark8 << (internal_bits_per_pixel - 8); | |
| 2734 | |||
| 2735 | ✗ | const float color_u_offlimit_f = uv8tof(color_u_offlimit8); | |
| 2736 | ✗ | const float color_v_offlimit_f = uv8tof(color_v_offlimit8); | |
| 2737 | ✗ | const float color_u_centermark_f = uv8tof(color_u_centermark8); | |
| 2738 | ✗ | const float color_v_centermark_f = uv8tof(color_v_centermark8); | |
| 2739 | ✗ | const float middle_chroma_f = uv8tof(128); | |
| 2740 | |||
| 2741 | ✗ | const int height = src->GetHeight(PLANAR_U); | |
| 2742 | ✗ | for (int y2 = 0; y2<height; ++y2) { | |
| 2743 | ✗ | if(pixelsize==1) { | |
| 2744 | ✗ | for (int x = 0; x<show_size; x += fact) { | |
| 2745 | ✗ | if (x<hist_tv_range_low || x>hist_tv_range_hi_luma) { | |
| 2746 | ✗ | p2[x >> subs] = (BYTE)color_u_offlimit8; | |
| 2747 | ✗ | p3[x >> subs] = (BYTE)color_v_offlimit8; | |
| 2748 | ✗ | } else if (x==hist_mid_range_luma) { | |
| 2749 | ✗ | p2[x >> subs] = (BYTE)color_u_centermark8; | |
| 2750 | ✗ | p3[x >> subs] = (BYTE)color_v_centermark8; | |
| 2751 | } else { | ||
| 2752 | ✗ | p2[x >> subs] = 128; | |
| 2753 | ✗ | p3[x >> subs] = 128; | |
| 2754 | } | ||
| 2755 | } | ||
| 2756 | } | ||
| 2757 | ✗ | else if (pixelsize == 2) { | |
| 2758 | ✗ | for (int x = 0; x<show_size; x += fact) { | |
| 2759 | ✗ | if (x<hist_tv_range_low || x>hist_tv_range_hi_luma) { | |
| 2760 | ✗ | reinterpret_cast<uint16_t *>(p2)[x >> subs] = color_u_offlimit; | |
| 2761 | ✗ | reinterpret_cast<uint16_t *>(p3)[x >> subs] = color_v_offlimit; | |
| 2762 | ✗ | } else if (x==hist_mid_range_luma) { | |
| 2763 | ✗ | reinterpret_cast<uint16_t *>(p2)[x >> subs] = color_u_centermark; | |
| 2764 | ✗ | reinterpret_cast<uint16_t *>(p3)[x >> subs] = color_v_centermark; | |
| 2765 | } else { | ||
| 2766 | ✗ | reinterpret_cast<uint16_t *>(p2)[x >> subs] = middle_chroma; | |
| 2767 | ✗ | reinterpret_cast<uint16_t *>(p3)[x >> subs] = middle_chroma; | |
| 2768 | } | ||
| 2769 | } | ||
| 2770 | } else { // pixelsize==4 | ||
| 2771 | ✗ | for (int x = 0; x<show_size; x += fact) { | |
| 2772 | ✗ | if (x<hist_tv_range_low || x>hist_tv_range_hi_luma) { | |
| 2773 | ✗ | reinterpret_cast<float *>(p2)[x >> subs] = color_u_offlimit_f; | |
| 2774 | ✗ | reinterpret_cast<float *>(p3)[x >> subs] = color_v_offlimit_f; | |
| 2775 | ✗ | } else if (x==hist_mid_range_luma) { | |
| 2776 | ✗ | reinterpret_cast<float *>(p2)[x >> subs] = color_u_centermark_f; | |
| 2777 | ✗ | reinterpret_cast<float *>(p3)[x >> subs] = color_v_centermark_f; | |
| 2778 | } else { | ||
| 2779 | ✗ | reinterpret_cast<float *>(p2)[x >> subs] = middle_chroma_f; | |
| 2780 | ✗ | reinterpret_cast<float *>(p3)[x >> subs] = middle_chroma_f; | |
| 2781 | } | ||
| 2782 | } | ||
| 2783 | |||
| 2784 | } | ||
| 2785 | ✗ | p2 += pitchUV; | |
| 2786 | ✗ | p3 += pitchUV; | |
| 2787 | } | ||
| 2788 | } | ||
| 2789 | 3 | } else { | |
| 2790 | ✗ | const int pitch = dst->GetPitch(); | |
| 2791 | ✗ | for (int y = 0; y<src->GetHeight(); ++y) { // YUY2 | |
| 2792 | ✗ | int hist[256] = { 0 }; | |
| 2793 | ✗ | for (int x = 0; x<source_width; ++x) { | |
| 2794 | ✗ | hist[srcp[x*2]]++; | |
| 2795 | } | ||
| 2796 | ✗ | BYTE* const q = pdst + xstart*2; | |
| 2797 | ✗ | if (markers) { | |
| 2798 | ✗ | for (int x = 0; x < 256; x += 2) { | |
| 2799 | ✗ | if (x < 16 || x>235) { | |
| 2800 | ✗ | q[x * 2 + 0] = (BYTE)exptab[min(E167, hist[x])] + 68; | |
| 2801 | ✗ | q[x * 2 + 1] = 16; | |
| 2802 | ✗ | q[x * 2 + 2] = (BYTE)exptab[min(E167, hist[x + 1])] + 68; | |
| 2803 | ✗ | q[x * 2 + 3] = 160; | |
| 2804 | } | ||
| 2805 | ✗ | else if (x == 124) { | |
| 2806 | ✗ | q[x * 2 + 0] = (BYTE)exptab[min(E167, hist[x])] + 68; | |
| 2807 | ✗ | q[x * 2 + 1] = 160; | |
| 2808 | ✗ | q[x * 2 + 2] = (BYTE)exptab[min(255, hist[x + 1])]; | |
| 2809 | ✗ | q[x * 2 + 3] = 16; | |
| 2810 | } | ||
| 2811 | else { | ||
| 2812 | ✗ | q[x * 2 + 0] = (BYTE)exptab[min(255, hist[x])]; | |
| 2813 | ✗ | q[x * 2 + 1] = 128; | |
| 2814 | ✗ | q[x * 2 + 2] = (BYTE)exptab[min(255, hist[x + 1])]; | |
| 2815 | ✗ | q[x * 2 + 3] = 128; | |
| 2816 | } | ||
| 2817 | } | ||
| 2818 | } | ||
| 2819 | else { | ||
| 2820 | ✗ | for (int x = 0; x < 256; x += 2) { | |
| 2821 | ✗ | q[x * 2 + 0] = (BYTE)exptab[min(255, hist[x])]; | |
| 2822 | ✗ | q[x * 2 + 1] = 128; | |
| 2823 | ✗ | q[x * 2 + 2] = (BYTE)exptab[min(255, hist[x + 1])]; | |
| 2824 | ✗ | q[x * 2 + 3] = 128; | |
| 2825 | } | ||
| 2826 | } | ||
| 2827 | ✗ | pdst += pitch; | |
| 2828 | ✗ | srcp += srcpitch; | |
| 2829 | } | ||
| 2830 | } | ||
| 2831 | 3 | return dst; | |
| 2832 | 3 | } | |
| 2833 | |||
| 2834 | |||
| 2835 | 1 | AVSValue __cdecl Histogram::Create(AVSValue args, void*, IScriptEnvironment* env) | |
| 2836 | { | ||
| 2837 |
2/4✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 293 not taken.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 293 not taken.
|
1 | const char* st_m = args[1].AsString("classic"); |
| 2838 | |||
| 2839 | 1 | Mode mode = ModeClassic; | |
| 2840 | |||
| 2841 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
|
1 | if (!lstrcmpi(st_m, "classic")) |
| 2842 | ✗ | mode = ModeClassic; | |
| 2843 | |||
| 2844 |
1/2✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 8 not taken.
|
1 | if (!lstrcmpi(st_m, "levels")) |
| 2845 | 1 | mode = ModeLevels; | |
| 2846 | |||
| 2847 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1 time.
|
1 | if (!lstrcmpi(st_m, "color")) |
| 2848 | ✗ | mode = ModeColor; | |
| 2849 | |||
| 2850 |
1/2✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 1 time.
|
1 | if (!lstrcmpi(st_m, "color2")) |
| 2851 | ✗ | mode = ModeColor2; | |
| 2852 | |||
| 2853 |
1/2✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 1 time.
|
1 | if (!lstrcmpi(st_m, "luma")) |
| 2854 | ✗ | mode = ModeLuma; | |
| 2855 | |||
| 2856 |
1/2✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 1 time.
|
1 | if (!lstrcmpi(st_m, "stereoY8")) |
| 2857 | ✗ | mode = ModeStereoY8; | |
| 2858 | |||
| 2859 |
1/2✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 1 time.
|
1 | if (!lstrcmpi(st_m, "stereo")) |
| 2860 | ✗ | mode = ModeStereo; | |
| 2861 | |||
| 2862 |
1/2✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 1 time.
|
1 | if (!lstrcmpi(st_m, "stereooverlay")) |
| 2863 | ✗ | mode = ModeOverlay; | |
| 2864 | |||
| 2865 |
1/2✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 1 time.
|
1 | if (!lstrcmpi(st_m, "audiolevels")) |
| 2866 | ✗ | mode = ModeAudioLevels; | |
| 2867 | |||
| 2868 |
3/6✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 190 not taken.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 190 not taken.
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 188 not taken.
|
1 | const VideoInfo& vi_orig = args[0].AsClip()->GetVideoInfo(); |
| 2869 | |||
| 2870 | histogram_color2_params color2_params; | ||
| 2871 |
2/4✓ Branch 27 → 28 taken 1 time.
✗ Branch 27 → 293 not taken.
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 293 not taken.
|
1 | const char *graticule_str = args[7].AsString("on"); // ON: old vectorscopes always drew limits/danger zones |
| 2872 | |||
| 2873 | // Use the lstrcmpi macro from your compatibility header | ||
| 2874 |
1/2✗ Branch 29 → 30 not taken.
✓ Branch 29 → 31 taken 1 time.
|
1 | if (lstrcmpi(graticule_str, "auto") == 0) { |
| 2875 | ✗ | color2_params.graticule_type = histogram_color2_params::GRATICULE_AUTO; | |
| 2876 | } | ||
| 2877 |
1/2✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 33 not taken.
|
1 | else if (lstrcmpi(graticule_str, "on") == 0) { |
| 2878 | 1 | color2_params.graticule_type = histogram_color2_params::GRATICULE_ON; | |
| 2879 | } | ||
| 2880 | ✗ | else if (lstrcmpi(graticule_str, "off") == 0) { | |
| 2881 | ✗ | color2_params.graticule_type = histogram_color2_params::GRATICULE_OFF; | |
| 2882 | } | ||
| 2883 | else { | ||
| 2884 | ✗ | env->ThrowError("Histogram: 'graticule' must be \"on\", \"off\", or \"auto\"."); | |
| 2885 | } | ||
| 2886 | |||
| 2887 |
2/4✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 293 not taken.
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 293 not taken.
|
1 | color2_params.targets = args[8].AsBool(false); // The 6 75% RGB squares |
| 2888 |
2/4✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 293 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 293 not taken.
|
1 | color2_params.axes = args[9].AsBool(false); // horizontal and vertical axes |
| 2889 |
2/4✓ Branch 40 → 41 taken 1 time.
✗ Branch 40 → 293 not taken.
✓ Branch 41 → 42 taken 1 time.
✗ Branch 41 → 293 not taken.
|
1 | color2_params.iq = args[10].AsBool(false); // +/-I and +Q targets |
| 2890 |
2/4✓ Branch 42 → 43 taken 1 time.
✗ Branch 42 → 293 not taken.
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 293 not taken.
|
1 | color2_params.iq_lines = args[11].AsBool(false); // 33 and 123 degree lines in the color2 mode |
| 2891 |
2/4✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 293 not taken.
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 293 not taken.
|
1 | color2_params.circle = args[12].AsBool(mode == ModeColor2 ? true : false); // circle in the color2 mode default |
| 2892 |
2/4✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 293 not taken.
✓ Branch 47 → 48 taken 1 time.
✗ Branch 47 → 293 not taken.
|
1 | color2_params.targets100 = args[13].AsBool(false); // The 6 100% RGB squares |
| 2893 | |||
| 2894 |
4/12✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 54 not taken.
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 293 not taken.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 54 taken 1 time.
✗ Branch 51 → 52 not taken.
✗ Branch 51 → 293 not taken.
✗ Branch 52 → 53 not taken.
✗ Branch 52 → 54 not taken.
✗ Branch 55 → 56 not taken.
✓ Branch 55 → 165 taken 1 time.
|
1 | if (mode == ModeLevels && vi_orig.IsRGB() && !vi_orig.IsPlanar()) { |
| 2895 | // as Levels can work for PlanarRGB, convert packed RGB to planar, then back | ||
| 2896 | // better that nothing | ||
| 2897 | ✗ | AVSValue new_args[1] = { args[0].AsClip() }; | |
| 2898 | ✗ | PClip clip; | |
| 2899 | ✗ | if (vi_orig.IsRGB24() || vi_orig.IsRGB48()) { | |
| 2900 | ✗ | clip = env->Invoke("ConvertToPlanarRGB", AVSValue(new_args, 1)).AsClip(); | |
| 2901 | } | ||
| 2902 | ✗ | else if (vi_orig.IsRGB32() || vi_orig.IsRGB64()) { | |
| 2903 | ✗ | clip = env->Invoke("ConvertToPlanarRGBA", AVSValue(new_args, 1)).AsClip(); | |
| 2904 | } | ||
| 2905 | |||
| 2906 | ✗ | Histogram* Result = new Histogram(clip, mode, args[2], args[3].AsInt(8), args[4].AsBool(true), | |
| 2907 | ✗ | args[5].AsBool(true), | |
| 2908 | ✗ | args[6].AsString(""), // matrix_name | |
| 2909 | color2_params, | ||
| 2910 | ✗ | env); | |
| 2911 | |||
| 2912 | ✗ | AVSValue new_args2[1] = { Result }; | |
| 2913 | ✗ | if (vi_orig.IsRGB24()) { | |
| 2914 | ✗ | return env->Invoke("ConvertToRGB24", AVSValue(new_args2, 1)).AsClip(); | |
| 2915 | } | ||
| 2916 | ✗ | else if (vi_orig.IsRGB48()) { | |
| 2917 | ✗ | return env->Invoke("ConvertToRGB48", AVSValue(new_args2, 1)).AsClip(); | |
| 2918 | } | ||
| 2919 | ✗ | else if (vi_orig.IsRGB32()) { | |
| 2920 | ✗ | return env->Invoke("ConvertToRGB32", AVSValue(new_args2, 1)).AsClip(); | |
| 2921 | } | ||
| 2922 | else { // if (vi_orig.IsRGB64()) | ||
| 2923 | ✗ | return env->Invoke("ConvertToRGB64", AVSValue(new_args2, 1)).AsClip(); | |
| 2924 | } | ||
| 2925 | ✗ | } | |
| 2926 | else { | ||
| 2927 |
3/6✓ Branch 171 → 172 taken 1 time.
✗ Branch 171 → 290 not taken.
✓ Branch 176 → 177 taken 1 time.
✗ Branch 176 → 286 not taken.
✓ Branch 177 → 178 taken 1 time.
✗ Branch 177 → 286 not taken.
|
3 | return new Histogram(args[0].AsClip(), mode, args[2], args[3].AsInt(8), args[4].AsBool(true), |
| 2928 |
1/2✓ Branch 169 → 170 taken 1 time.
✗ Branch 169 → 290 not taken.
|
1 | args[5].AsBool(true), // markers |
| 2929 | 2 | args[6].AsString(""), // matrix_name | |
| 2930 | color2_params, | ||
| 2931 |
12/26✓ Branch 165 → 166 taken 1 time.
✗ Branch 165 → 293 not taken.
✓ Branch 166 → 167 taken 1 time.
✗ Branch 166 → 290 not taken.
✓ Branch 167 → 168 taken 1 time.
✗ Branch 167 → 290 not taken.
✓ Branch 168 → 169 taken 1 time.
✗ Branch 168 → 290 not taken.
✓ Branch 170 → 171 taken 1 time.
✗ Branch 170 → 290 not taken.
✓ Branch 172 → 173 taken 1 time.
✗ Branch 172 → 290 not taken.
✓ Branch 173 → 174 taken 1 time.
✗ Branch 173 → 290 not taken.
✓ Branch 174 → 175 taken 1 time.
✗ Branch 174 → 289 not taken.
✓ Branch 175 → 176 taken 1 time.
✗ Branch 175 → 289 not taken.
✓ Branch 178 → 179 taken 1 time.
✗ Branch 178 → 284 not taken.
✓ Branch 179 → 180 taken 1 time.
✗ Branch 179 → 284 not taken.
✗ Branch 183 → 184 not taken.
✓ Branch 183 → 185 taken 1 time.
✗ Branch 290 → 291 not taken.
✗ Branch 290 → 292 not taken.
|
5 | env); |
| 2932 | } | ||
| 2933 | } | ||
| 2934 |