GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 30.1% 103 / 0 / 342
Functions: 66.7% 4 / 0 / 6
Branches: 17.5% 14 / 0 / 80

filters/overlay/OF_difference.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 // Overlay (c) 2003, 2004 by Klaus Post
36
37 #include "overlayfunctions.h"
38 #include <cmath>
39 #include <avs/minmax.h>
40
41 #include <stdint.h>
42 #include <type_traits>
43
44 1 void OL_DifferenceImage::DoBlendImageMask(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) {
45
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
1 if (bits_per_pixel == 8)
46 1 BlendImageMask<uint8_t, true>(base, overlay, mask);
47 else if(bits_per_pixel <= 16)
48 BlendImageMask<uint16_t, true>(base, overlay, mask);
49 //else if(bits_per_pixel == 32)
50 // BlendImageMask<float>(base, overlay, mask);
51 1 }
52
53 1 void OL_DifferenceImage::DoBlendImage(ImageOverlayInternal* base, ImageOverlayInternal* overlay) {
54
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
1 if (bits_per_pixel == 8)
55 1 BlendImageMask<uint8_t, false>(base, overlay, nullptr);
56 else if(bits_per_pixel <= 16)
57 BlendImageMask<uint16_t, false>(base, overlay, nullptr);
58 //else if(bits_per_pixel == 32)
59 // BlendImage<float>(base, overlay);
60 1 }
61
62 // no float support
63 template<typename pixel_t, bool maskMode>
64 2 void OL_DifferenceImage::BlendImageMask(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) {
65 2 pixel_t* baseY = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_Y));
66 2 pixel_t* baseU = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_U));
67 2 pixel_t* baseV = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_V));
68
69 2 pixel_t* ovY = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_Y));
70 2 pixel_t* ovU = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_U));
71 2 pixel_t* ovV = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_V));
72
73 2 pixel_t* maskY = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_Y)) : nullptr;
74 2 pixel_t* maskU = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_U)) : nullptr;
75 2 pixel_t* maskV = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_V)) : nullptr;
76
77 2 const int half_pixel_value = (sizeof(pixel_t) == 1) ? 128 : (1 << (bits_per_pixel - 1));
78 2 const int max_pixel_value = (sizeof(pixel_t) == 1) ? 255 : (1 << bits_per_pixel) - 1;
79 2 const int pixel_range = max_pixel_value + 1;
80 2 const int SHIFT = (sizeof(pixel_t) == 1) ? 5 : 5 + (bits_per_pixel - 8);
81 2 const int MASK_CORR_SHIFT = (sizeof(pixel_t) == 1) ? 8 : bits_per_pixel;
82 2 const int OPACITY_SHIFT = 8; // opacity always max 0..256
83 2 const int over32 = (1 << SHIFT); // 32
84 2 const int basepitch = (base->pitch) / sizeof(pixel_t);
85 2 const int overlaypitch = (overlay->pitch) / sizeof(pixel_t);
86 2 const int maskpitch = maskMode ? (mask->pitch) / sizeof(pixel_t) : 0;
87
88 // avoid "uint16*uint16 can't get into int32" overflows
89 using result_t = typename std::conditional<sizeof(pixel_t) == 1, int, int64_t>::type;
90
91 2 int w = base->w();
92 2 int h = base->h();
93
94
2/8
void OL_DifferenceImage::BlendImageMask<unsigned char, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 25 not taken.
void OL_DifferenceImage::BlendImageMask<unsigned char, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 28 not taken.
void OL_DifferenceImage::BlendImageMask<unsigned short, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 25 not taken.
void OL_DifferenceImage::BlendImageMask<unsigned short, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 28 not taken.
2 if (opacity == 256) {
95
4/8
void OL_DifferenceImage::BlendImageMask<unsigned char, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 24 → 12 taken 2 times.
✓ Branch 24 → 39 taken 1 time.
void OL_DifferenceImage::BlendImageMask<unsigned char, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 27 → 15 taken 2 times.
✓ Branch 27 → 42 taken 1 time.
void OL_DifferenceImage::BlendImageMask<unsigned short, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 24 → 12 not taken.
✗ Branch 24 → 39 not taken.
void OL_DifferenceImage::BlendImageMask<unsigned short, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 27 → 15 not taken.
✗ Branch 27 → 42 not taken.
6 for (int y = 0; y < h; y++) {
96
4/8
void OL_DifferenceImage::BlendImageMask<unsigned char, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 22 → 13 taken 8 times.
✓ Branch 22 → 23 taken 2 times.
void OL_DifferenceImage::BlendImageMask<unsigned char, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 25 → 16 taken 8 times.
✓ Branch 25 → 26 taken 2 times.
void OL_DifferenceImage::BlendImageMask<unsigned short, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 22 → 13 not taken.
✗ Branch 22 → 23 not taken.
void OL_DifferenceImage::BlendImageMask<unsigned short, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 25 → 16 not taken.
✗ Branch 25 → 26 not taken.
20 for (int x = 0; x < w; x++) {
97 16 int Y = abs((int)baseY[x] - (int)ovY[x]) + half_pixel_value;
98 16 int U = abs((int)baseU[x] - (int)ovU[x]) + half_pixel_value;
99 16 int V = abs((int)baseV[x] - (int)ovV[x]) + half_pixel_value;
100 if constexpr (maskMode) {
101 8 result_t mY = maskY[x];
102 8 result_t mU = maskU[x];
103 8 result_t mV = maskV[x];
104 8 Y = (int)(((Y*mY) + ((pixel_range - mY)*baseY[x])) >> MASK_CORR_SHIFT);
105 8 U = (int)(((U*mU) + ((pixel_range - mU)*baseU[x])) >> MASK_CORR_SHIFT);
106 8 V = (int)(((V*mV) + ((pixel_range - mV)*baseV[x])) >> MASK_CORR_SHIFT);
107 }
108
2/8
void OL_DifferenceImage::BlendImageMask<unsigned char, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 13 → 14 taken 8 times.
✗ Branch 13 → 16 not taken.
void OL_DifferenceImage::BlendImageMask<unsigned char, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 16 → 17 taken 8 times.
✗ Branch 16 → 19 not taken.
void OL_DifferenceImage::BlendImageMask<unsigned short, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 16 not taken.
void OL_DifferenceImage::BlendImageMask<unsigned short, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 19 not taken.
16 if (Y>max_pixel_value) { // Apply overbrightness to UV
109 16 int multiplier = max(0,pixel_range + over32 -Y); // 0 to 32
110 16 U = ((U*( multiplier)) + (half_pixel_value*(over32-multiplier)))>>SHIFT;
111 16 V = ((V*( multiplier)) + (half_pixel_value*(over32-multiplier)))>>SHIFT;
112 16 Y = max_pixel_value;
113 } else if (Y<0) { // Apply superdark to UV
114 int multiplier = min(-Y,over32); // 0 to 32
115 U = ((U*(over32 - multiplier)) + (half_pixel_value*( multiplier)))>>SHIFT;
116 V = ((V*(over32 - multiplier)) + (half_pixel_value*( multiplier)))>>SHIFT;
117 Y = 0;
118 }
119 16 baseY[x] = (pixel_t)Y;
120 16 baseU[x] = (pixel_t)clamp(U, 0, max_pixel_value);
121 16 baseV[x] = (pixel_t)clamp(V, 0, max_pixel_value);
122 }
123 4 baseY += basepitch;
124 4 baseU += basepitch;
125 4 baseV += basepitch;
126
127 4 ovY += overlaypitch;
128 4 ovU += overlaypitch;
129 4 ovV += overlaypitch;
130
131 if constexpr (maskMode) {
132 2 maskY += maskpitch;
133 2 maskU += maskpitch;
134 2 maskV += maskpitch;
135 }
136 } // for y
137 } else {
138 for (int y = 0; y < h; y++) {
139 for (int x = 0; x < w; x++) {
140 int Y = abs((int)baseY[x] - (int)ovY[x]) + half_pixel_value;
141 int U = abs((int)baseU[x] - (int)ovU[x]) + half_pixel_value;
142 int V = abs((int)baseV[x] - (int)ovV[x]) + half_pixel_value;
143 if constexpr (maskMode) {
144 result_t mY = (maskY[x] * opacity) >> OPACITY_SHIFT;
145 result_t mU = (maskU[x] * opacity) >> OPACITY_SHIFT;
146 result_t mV = (maskV[x] * opacity) >> OPACITY_SHIFT;
147 Y = (int)(((Y*mY) + ((pixel_range - mY)*baseY[x])) >> MASK_CORR_SHIFT);
148 U = (int)(((U*mU) + ((pixel_range - mU)*baseU[x])) >> MASK_CORR_SHIFT);
149 V = (int)(((V*mV) + ((pixel_range - mV)*baseV[x])) >> MASK_CORR_SHIFT);
150 }
151 else {
152 Y = ((Y*opacity) + (inv_opacity*baseY[x])) >> OPACITY_SHIFT;
153 U = ((U*opacity) + (inv_opacity*baseU[x])) >> OPACITY_SHIFT;
154 V = ((V*opacity) + (inv_opacity*baseV[x])) >> OPACITY_SHIFT;
155 }
156 if (Y>max_pixel_value) { // Apply overbrightness to UV
157 int multiplier = max(0,pixel_range + over32 -Y); // 0 to 32
158 U = ((U*( multiplier)) + (half_pixel_value*(over32-multiplier)))>>SHIFT;
159 V = ((V*( multiplier)) + (half_pixel_value*(over32-multiplier)))>>SHIFT;
160 Y = max_pixel_value;
161 } else if (Y<0) { // Apply superdark to UV
162 int multiplier = min(-Y,over32); // 0 to 32
163 U = ((U*(over32 - multiplier)) + (half_pixel_value*( multiplier)))>>SHIFT;
164 V = ((V*(over32 - multiplier)) + (half_pixel_value*( multiplier)))>>SHIFT;
165 Y = 0;
166 }
167 baseY[x] = (pixel_t)Y;
168 baseU[x] = (pixel_t)clamp(U, 0, max_pixel_value);
169 baseV[x] = (pixel_t)clamp(V, 0, max_pixel_value);
170 }
171 baseY += basepitch;
172 baseU += basepitch;
173 baseV += basepitch;
174
175 ovY += overlaypitch;
176 ovU += overlaypitch;
177 ovV += overlaypitch;
178
179 if constexpr (maskMode) {
180 maskY += maskpitch;
181 maskU += maskpitch;
182 maskV += maskpitch;
183 }
184 } // for x
185 } // for y
186 2 }
187
188