GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 36.2% 406 / 0 / 1120
Functions: 42.3% 11 / 0 / 26
Branches: 37.0% 111 / 0 / 300

filters/overlay/OF_add.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
39 #include <stdint.h>
40 #include <type_traits>
41
42 1 void OL_AddImage::DoBlendImageMask(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) {
43
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 17 taken 1 time.
1 if (rgb) {
44 if (of_mode == OF_Add) {
45 if (bits_per_pixel == 8)
46 BlendImageMask_RGB<uint8_t, true, true>(base, overlay, mask);
47 else if (bits_per_pixel <= 16)
48 BlendImageMask_RGB<uint16_t, true, true>(base, overlay, mask);
49 else if (bits_per_pixel == 32)
50 BlendImageMask_RGB_float<true, true>(base, overlay, mask);
51 } else {
52 // OF_Subtract
53 if (bits_per_pixel == 8)
54 BlendImageMask_RGB<uint8_t, true, false>(base, overlay, mask);
55 else if (bits_per_pixel <= 16)
56 BlendImageMask_RGB<uint16_t, true, false>(base, overlay, mask);
57 else if (bits_per_pixel == 32)
58 BlendImageMask_RGB_float<true, false>(base, overlay, mask);
59 }
60 return;
61 }
62 // existing YUV logic
63
1/2
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 24 not taken.
1 if(of_mode == OF_Add) {
64
1/2
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 20 not taken.
1 if (bits_per_pixel == 8)
65 1 BlendImageMask<uint8_t, true, true>(base, overlay, mask);
66 else if(bits_per_pixel <= 16)
67 BlendImageMask<uint16_t, true, true>(base, overlay, mask);
68 else if(bits_per_pixel == 32)
69 BlendImageMask_float<true, true>(base, overlay, mask);
70 }
71 else {
72 // OF_Subtract
73 if (bits_per_pixel == 8)
74 BlendImageMask<uint8_t, true, false>(base, overlay, mask);
75 else if(bits_per_pixel <= 16)
76 BlendImageMask<uint16_t, true, false>(base, overlay, mask);
77 else if(bits_per_pixel == 32)
78 BlendImageMask_float<true, false>(base, overlay, mask);
79 }
80 }
81
82 17 void OL_AddImage::DoBlendImage(ImageOverlayInternal* base, ImageOverlayInternal* overlay) {
83
2/2
✓ Branch 2 → 3 taken 8 times.
✓ Branch 2 → 17 taken 9 times.
17 if (rgb) {
84
2/2
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 10 taken 4 times.
8 if (of_mode == OF_Add) {
85
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 4 times.
4 if (bits_per_pixel == 8)
86 BlendImageMask_RGB<uint8_t, false, true>(base, overlay, nullptr);
87
2/2
✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 8 taken 2 times.
4 else if (bits_per_pixel <= 16)
88 2 BlendImageMask_RGB<uint16_t, false, true>(base, overlay, nullptr);
89
1/2
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 16 not taken.
2 else if (bits_per_pixel == 32)
90 2 BlendImageMask_RGB_float<false, true>(base, overlay, nullptr);
91 }
92 else {
93 // OF_Subtract
94
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 4 times.
4 if (bits_per_pixel == 8)
95 BlendImageMask_RGB<uint8_t, false, false>(base, overlay, nullptr);
96
2/2
✓ Branch 12 → 13 taken 2 times.
✓ Branch 12 → 14 taken 2 times.
4 else if (bits_per_pixel <= 16)
97 2 BlendImageMask_RGB<uint16_t, false, false>(base, overlay, nullptr);
98
1/2
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 16 not taken.
2 else if (bits_per_pixel == 32)
99 2 BlendImageMask_RGB_float<false, false>(base, overlay, nullptr);
100 }
101 8 return;
102 }
103 // existing YUV logic
104
2/2
✓ Branch 17 → 18 taken 5 times.
✓ Branch 17 → 24 taken 4 times.
9 if(of_mode == OF_Add) {
105
2/2
✓ Branch 18 → 19 taken 3 times.
✓ Branch 18 → 20 taken 2 times.
5 if (bits_per_pixel == 8)
106 3 BlendImageMask<uint8_t, false, true>(base, overlay, nullptr);
107
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 2 times.
2 else if(bits_per_pixel <= 16)
108 BlendImageMask<uint16_t, false, true>(base, overlay, nullptr);
109
1/2
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 30 not taken.
2 else if(bits_per_pixel == 32)
110 2 BlendImageMask_float<false, true>(base, overlay, nullptr);
111 }
112 else {
113 // OF_Subtract
114
2/2
✓ Branch 24 → 25 taken 2 times.
✓ Branch 24 → 26 taken 2 times.
4 if (bits_per_pixel == 8)
115 2 BlendImageMask<uint8_t, false, false>(base, overlay, nullptr);
116
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 2 times.
2 else if(bits_per_pixel <= 16)
117 BlendImageMask<uint16_t, false, false>(base, overlay, nullptr);
118
1/2
✓ Branch 28 → 29 taken 2 times.
✗ Branch 28 → 30 not taken.
2 else if(bits_per_pixel == 32)
119 2 BlendImageMask_float<false, false>(base, overlay, nullptr);
120 }
121 }
122
123 // integer 8-16 bit add/subtract with YUV overshoot handling
124 template<typename pixel_t, bool maskMode, bool of_add>
125 6 void OL_AddImage::BlendImageMask(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) {
126
127 6 pixel_t* baseY = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_Y));
128 6 pixel_t* baseU = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_U));
129 6 pixel_t* baseV = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_V));
130
131 6 pixel_t* ovY = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_Y));
132 6 pixel_t* ovU = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_U));
133 6 pixel_t* ovV = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_V));
134
135 6 pixel_t* maskY = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_Y)) : nullptr;
136 6 pixel_t* maskU = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_U)) : nullptr;
137 6 pixel_t* maskV = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_V)) : nullptr;
138
139 6 const int half_pixel_value = (sizeof(pixel_t) == 1) ? 128 : (1 << (bits_per_pixel - 1));
140 6 const int max_pixel_value = (sizeof(pixel_t) == 1) ? 255 : (1 << bits_per_pixel) - 1;
141 6 const int pixel_range = max_pixel_value + 1;
142 6 const int SHIFT = (sizeof(pixel_t) == 1) ? 5 : 5 + (bits_per_pixel - 8);
143 6 const int MASK_CORR_SHIFT = (sizeof(pixel_t) == 1) ? 8 : bits_per_pixel;
144 6 const int OPACITY_SHIFT = 8; // opacity always max 0..256
145 6 const int over32 = (1 << SHIFT); // 32
146 6 const int basepitch = (base->pitch) / sizeof(pixel_t);
147 6 const int overlaypitch = (overlay->pitch) / sizeof(pixel_t);
148 6 const int maskpitch = maskMode ? (mask->pitch) / sizeof(pixel_t) : 0;
149
150 // avoid "uint16*uint16 can't get into int32" overflows
151 typedef typename std::conditional < sizeof(pixel_t) == 1, int, typename std::conditional < sizeof(pixel_t) == 2, int64_t, float>::type >::type result_t;
152
153 /*
154 In YUV, "add" and "subtract" are not just per-channel math. The luma (Y) is added/subtracted, but if the result
155 overflows (Y > max) or underflows (Y < 0), the chroma (U/V) is "pulled" toward neutral (gray/white) to mimic
156 how RGB overbright/underbright behaves visually.
157
158 In RGB, adding two bright colors can result in "white" (all channels maxed). In YUV, if you just add Y, U, and V,
159 we can get weird color shifts. The code compensates by blending U/V toward neutral when Y is out of range,
160 making the result look more like RGB addition.
161
162 For RGB, a simple per-channel add/subtract (with clamping for 8/16-bit, or no clamping for float) is done.
163 The "magic" is only needed for YUV to avoid odd color artifacts. In RGB, overbright naturally becomes white,
164 so no special handling is needed.
165 */
166
167 6 int w = base->w();
168 6 int h = base->h();
169
5/16
void OL_AddImage::BlendImageMask<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 23 taken 1 time.
void OL_AddImage::BlendImageMask<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 23 taken 1 time.
void OL_AddImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 25 not taken.
void OL_AddImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 25 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 23 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 23 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 25 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 25 not taken.
6 if (opacity == 256) {
170
6/16
void OL_AddImage::BlendImageMask<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 22 → 12 taken 3 times.
✓ Branch 22 → 37 taken 1 time.
void OL_AddImage::BlendImageMask<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 22 → 12 taken 5 times.
✓ Branch 22 → 37 taken 2 times.
void OL_AddImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 24 → 15 not taken.
✗ Branch 24 → 39 not taken.
void OL_AddImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 24 → 15 taken 2 times.
✓ Branch 24 → 39 taken 1 time.
void OL_AddImage::BlendImageMask<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 22 → 12 not taken.
✗ Branch 22 → 37 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 22 → 12 not taken.
✗ Branch 22 → 37 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 24 → 15 not taken.
✗ Branch 24 → 39 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 24 → 15 not taken.
✗ Branch 24 → 39 not taken.
14 for (int y = 0; y < h; y++) {
171
6/16
void OL_AddImage::BlendImageMask<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 19 → 13 taken 21 times.
✓ Branch 19 → 20 taken 3 times.
void OL_AddImage::BlendImageMask<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 19 → 13 taken 29 times.
✓ Branch 19 → 20 taken 5 times.
void OL_AddImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 22 → 16 not taken.
✗ Branch 22 → 23 not taken.
void OL_AddImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 22 → 16 taken 8 times.
✓ Branch 22 → 23 taken 2 times.
void OL_AddImage::BlendImageMask<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 19 → 13 not taken.
✗ Branch 19 → 20 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 19 → 13 not taken.
✗ Branch 19 → 20 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 22 → 16 not taken.
✗ Branch 22 → 23 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 22 → 16 not taken.
✗ Branch 22 → 23 not taken.
68 for (int x = 0; x < w; x++) {
172 int Y, U, V;
173 if (of_add) {
174 37 Y = baseY[x] + (maskMode ? (((result_t)ovY[x] * maskY[x]) >> MASK_CORR_SHIFT) : ovY[x]);
175 37 U = baseU[x] + (int)(maskMode ? ((((result_t)half_pixel_value*(pixel_range - maskU[x])) + ((result_t)maskU[x] * ovU[x])) >> MASK_CORR_SHIFT) : ovU[x]) - half_pixel_value;
176 37 V = baseV[x] + (int)(maskMode ? ((((result_t)half_pixel_value*(pixel_range - maskV[x])) + ((result_t)maskV[x] * ovV[x])) >> MASK_CORR_SHIFT) : ovV[x]) - half_pixel_value;
177 // When Y is too high, U and V are blended toward half_pixel_value (neutral chroma), making the color "whiter".
178
3/8
void OL_AddImage::BlendImageMask<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 13 → 14 taken 12 times.
✓ Branch 13 → 16 taken 17 times.
void OL_AddImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 19 taken 8 times.
void OL_AddImage::BlendImageMask<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 16 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 19 not taken.
37 if (Y>max_pixel_value) { // Apply overbrightness to UV
179 12 int multiplier = max(0,pixel_range + over32 -Y); // 0 to 32
180 12 U = ((U*( multiplier)) + (half_pixel_value*(over32-multiplier)))>>SHIFT;
181 12 V = ((V*( multiplier)) + (half_pixel_value*(over32-multiplier)))>>SHIFT;
182 12 Y = max_pixel_value;
183 }
184 }
185 else {
186 // of_subtract
187 21 Y = baseY[x] - (maskMode ? (((result_t)ovY[x] * maskY[x]) >> MASK_CORR_SHIFT) : ovY[x]);
188 21 U = baseU[x] - (int)(maskMode ? ((((result_t)half_pixel_value*(pixel_range - maskU[x])) + ((result_t)maskU[x] * ovU[x])) >> MASK_CORR_SHIFT) : ovU[x]) + half_pixel_value;
189 21 V = baseV[x] - (int)(maskMode ? ((((result_t)half_pixel_value*(pixel_range - maskV[x])) + ((result_t)maskV[x] * ovV[x])) >> MASK_CORR_SHIFT) : ovV[x]) + half_pixel_value;
190
2/8
void OL_AddImage::BlendImageMask<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 13 → 14 taken 9 times.
✓ Branch 13 → 16 taken 12 times.
void OL_AddImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 19 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 16 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 19 not taken.
21 if (Y<0) { // Apply superdark to UV
191 9 int multiplier = min(-Y,over32); // 0 to 32
192 9 U = ((U*(over32 - multiplier)) + (half_pixel_value*( multiplier)))>>SHIFT;
193 9 V = ((V*(over32 - multiplier)) + (half_pixel_value*( multiplier)))>>SHIFT;
194 9 Y = 0;
195 }
196 }
197 58 baseU[x] = (pixel_t)clamp(U, 0, max_pixel_value);
198 58 baseV[x] = (pixel_t)clamp(V, 0, max_pixel_value);
199 58 baseY[x] = (pixel_t)Y;
200 }
201 10 baseY += basepitch;
202 10 baseU += basepitch;
203 10 baseV += basepitch;
204
205 10 ovY += overlaypitch;
206 10 ovU += overlaypitch;
207 10 ovV += overlaypitch;
208
209 if(maskMode) {
210 2 maskY += maskpitch;
211 2 maskU += maskpitch;
212 2 maskV += maskpitch;
213 }
214 }
215 } else {
216
4/16
void OL_AddImage::BlendImageMask<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 36 → 24 taken 3 times.
✓ Branch 36 → 37 taken 1 time.
void OL_AddImage::BlendImageMask<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 36 → 24 taken 3 times.
✓ Branch 36 → 37 taken 1 time.
void OL_AddImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 38 → 26 not taken.
✗ Branch 38 → 39 not taken.
void OL_AddImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 38 → 26 not taken.
✗ Branch 38 → 39 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 36 → 24 not taken.
✗ Branch 36 → 37 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 36 → 24 not taken.
✗ Branch 36 → 37 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 38 → 26 not taken.
✗ Branch 38 → 39 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 38 → 26 not taken.
✗ Branch 38 → 39 not taken.
8 for (int y = 0; y < h; y++) {
217
4/16
void OL_AddImage::BlendImageMask<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 33 → 25 taken 21 times.
✓ Branch 33 → 34 taken 3 times.
void OL_AddImage::BlendImageMask<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 33 → 25 taken 21 times.
✓ Branch 33 → 34 taken 3 times.
void OL_AddImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 36 → 27 not taken.
✗ Branch 36 → 37 not taken.
void OL_AddImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 36 → 27 not taken.
✗ Branch 36 → 37 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 33 → 25 not taken.
✗ Branch 33 → 34 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 33 → 25 not taken.
✗ Branch 33 → 34 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 36 → 27 not taken.
✗ Branch 36 → 37 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 36 → 27 not taken.
✗ Branch 36 → 37 not taken.
48 for (int x = 0; x < w; x++) {
218 int Y, U, V;
219 if(of_add)
220 21 Y = baseY[x] + (maskMode ? (((result_t)maskY[x] * opacity*ovY[x]) >> (OPACITY_SHIFT + MASK_CORR_SHIFT)) : ((opacity*ovY[x]) >> OPACITY_SHIFT));
221 else
222 21 Y = baseY[x] - (maskMode ? (((result_t)maskY[x] * opacity*ovY[x]) >> (OPACITY_SHIFT + MASK_CORR_SHIFT)) : ((opacity*ovY[x]) >> OPACITY_SHIFT));
223 if (maskMode) {
224 result_t mU = (maskU[x] * opacity) >> OPACITY_SHIFT;
225 result_t mV = (maskV[x] * opacity) >> OPACITY_SHIFT;
226 if(of_add) {
227 U = baseU[x] + (int)(((half_pixel_value*(pixel_range - mU)) + (mU*ovU[x])) >> MASK_CORR_SHIFT) - half_pixel_value;
228 V = baseV[x] + (int)(((half_pixel_value*(pixel_range - mV)) + (mV*ovV[x])) >> MASK_CORR_SHIFT) - half_pixel_value;
229 }
230 else {
231 U = baseU[x] - (int)(((half_pixel_value*(pixel_range - mU)) + (mU*ovU[x])) >> MASK_CORR_SHIFT) + half_pixel_value;
232 V = baseV[x] - (int)(((half_pixel_value*(pixel_range - mV)) + (mV*ovV[x])) >> MASK_CORR_SHIFT) + half_pixel_value;
233 }
234 }
235 else {
236 if(of_add) {
237 21 U = baseU[x] + (((half_pixel_value*inv_opacity)+(opacity*(ovU[x])))>>OPACITY_SHIFT) - half_pixel_value;
238 21 V = baseV[x] + (((half_pixel_value*inv_opacity)+(opacity*(ovV[x])))>>OPACITY_SHIFT) - half_pixel_value;
239 }
240 else {
241 21 U = baseU[x] - (((half_pixel_value*inv_opacity)+(opacity*(ovU[x])))>>OPACITY_SHIFT) + half_pixel_value;
242 21 V = baseV[x] - (((half_pixel_value*inv_opacity)+(opacity*(ovV[x])))>>OPACITY_SHIFT) + half_pixel_value;
243 }
244 }
245 if(of_add) {
246
2/8
void OL_AddImage::BlendImageMask<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 27 → 28 taken 9 times.
✓ Branch 27 → 30 taken 12 times.
void OL_AddImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 33 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 30 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 33 not taken.
21 if (Y>max_pixel_value) { // Apply overbrightness to UV
247 9 int multiplier = max(0,(max_pixel_value + 1) + over32 - Y); // 288-Y : 0 to 32
248 9 U = ((U*multiplier) + (half_pixel_value*(over32 - multiplier))) >> SHIFT;
249 9 V = ((V*multiplier) + (half_pixel_value*(over32 - multiplier))) >> SHIFT;
250 9 Y = max_pixel_value;
251 }
252 }
253 else {
254 // of_subtract
255
2/8
void OL_AddImage::BlendImageMask<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 27 → 28 taken 6 times.
✓ Branch 27 → 30 taken 15 times.
void OL_AddImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 33 not taken.
void OL_AddImage::BlendImageMask<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 30 not taken.
void OL_AddImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 33 not taken.
21 if (Y<0) { // Apply overbrightness to UV
256 6 int multiplier = min(-Y,over32); // 0 to 32
257 6 U = ((U*(over32 - multiplier)) + (half_pixel_value*( multiplier)))>>SHIFT;
258 6 V = ((V*(over32 - multiplier)) + (half_pixel_value*( multiplier)))>>SHIFT;
259 6 Y = 0;
260 }
261 }
262 42 baseU[x] = (pixel_t)clamp(U, 0, max_pixel_value);
263 42 baseV[x] = (pixel_t)clamp(V, 0, max_pixel_value);
264 42 baseY[x] = (pixel_t)Y;
265 }
266 6 baseY += basepitch;
267 6 baseU += basepitch;
268 6 baseV += basepitch;
269
270 6 ovY += overlaypitch;
271 6 ovU += overlaypitch;
272 6 ovV += overlaypitch;
273
274 if(maskMode) {
275 maskY += maskpitch;
276 maskU += maskpitch;
277 maskV += maskpitch;
278 }
279 }
280 }
281 6 }
282
283 // float add/subtract with YUV overshoot handling
284 template<bool maskMode, bool of_add>
285 4 void OL_AddImage::BlendImageMask_float(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) {
286 // specialized pixel_t float images
287 // No clamping needed.
288 // float range here is supposed to be [0.0f .. 1.0f] for Y, [-0.5f .. 0.5f] for U/V
289 // mask is [0.0f .. 1.0f]
290 4 float* baseY = reinterpret_cast<float*>(base->GetPtr(PLANAR_Y));
291 4 float* baseU = reinterpret_cast<float*>(base->GetPtr(PLANAR_U));
292 4 float* baseV = reinterpret_cast<float*>(base->GetPtr(PLANAR_V));
293
294 4 float* ovY = reinterpret_cast<float*>(overlay->GetPtr(PLANAR_Y));
295 4 float* ovU = reinterpret_cast<float*>(overlay->GetPtr(PLANAR_U));
296 4 float* ovV = reinterpret_cast<float*>(overlay->GetPtr(PLANAR_V));
297
298 4 float* maskY = maskMode ? reinterpret_cast<float*>(mask->GetPtr(PLANAR_Y)) : nullptr;
299 4 float* maskU = maskMode ? reinterpret_cast<float*>(mask->GetPtr(PLANAR_U)) : nullptr;
300 4 float* maskV = maskMode ? reinterpret_cast<float*>(mask->GetPtr(PLANAR_V)) : nullptr;
301
302 // For float, half_pixel_value is 0.0f, max_pixel_value is 1.0f for Y
303 4 constexpr float half_pixel_value = 0.0f; // intentionally keep it 0.0f for U/V calculation, compiler will optimize away
304 4 constexpr float max_pixel_value = 1.0f; // for Y overshoot check
305 4 constexpr float pixel_range = 1.0f; // mask must be in [0.0f, 1.0f]
306
307 // have no opacity (0..256), but special opacity_f (0..1.0) for float
308 // Unlike integer case which has OPACITY_SHIFT of 8 bit for integer arithmetic
309 4 const float inv_opacity_f = 1.0f - opacity_f;
310
311 4 const int basepitch = (base->pitch) / sizeof(float);
312 4 const int overlaypitch = (overlay->pitch) / sizeof(float);
313 4 const int maskpitch = maskMode ? (mask->pitch) / sizeof(float) : 0;
314
315 4 int w = base->w();
316 4 int h = base->h();
317
318
4/8
void OL_AddImage::BlendImageMask_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 22 taken 1 time.
void OL_AddImage::BlendImageMask_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 23 taken 1 time.
void OL_AddImage::BlendImageMask_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 24 not taken.
void OL_AddImage::BlendImageMask_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 25 not taken.
4 if (opacity_f == 1.0f) {
319
4/8
void OL_AddImage::BlendImageMask_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 21 → 12 taken 3 times.
✓ Branch 21 → 34 taken 1 time.
void OL_AddImage::BlendImageMask_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 22 → 12 taken 3 times.
✓ Branch 22 → 36 taken 1 time.
void OL_AddImage::BlendImageMask_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 23 → 15 not taken.
✗ Branch 23 → 37 not taken.
void OL_AddImage::BlendImageMask_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 24 → 15 not taken.
✗ Branch 24 → 38 not taken.
8 for (int y = 0; y < h; y++) {
320
4/8
void OL_AddImage::BlendImageMask_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 18 → 13 taken 21 times.
✓ Branch 18 → 19 taken 3 times.
void OL_AddImage::BlendImageMask_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 19 → 13 taken 21 times.
✓ Branch 19 → 20 taken 3 times.
void OL_AddImage::BlendImageMask_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 21 → 16 not taken.
✗ Branch 21 → 22 not taken.
void OL_AddImage::BlendImageMask_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 22 → 16 not taken.
✗ Branch 22 → 23 not taken.
48 for (int x = 0; x < w; ++x) {
321 float Y, U, V;
322 if (of_add) {
323 21 Y = baseY[x] + (maskMode ? ovY[x] * maskY[x] : ovY[x]);
324 21 U = baseU[x] + (maskMode ? (half_pixel_value * (pixel_range - maskU[x]) + maskU[x] * ovU[x]) : ovU[x]) - half_pixel_value;
325 21 V = baseV[x] + (maskMode ? (half_pixel_value * (pixel_range - maskV[x]) + maskV[x] * ovV[x]) : ovV[x]) - half_pixel_value;
326 } else {
327 21 Y = baseY[x] - (maskMode ? ovY[x] * maskY[x] : ovY[x]);
328 21 U = baseU[x] - (maskMode ? (half_pixel_value * (pixel_range - maskU[x]) + maskU[x] * ovU[x]) : ovU[x]) + half_pixel_value;
329 21 V = baseV[x] - (maskMode ? (half_pixel_value * (pixel_range - maskV[x]) + maskV[x] * ovV[x]) : ovV[x]) + half_pixel_value;
330 }
331
332 42 constexpr float over32 = 32.0f / 255.0f; // ~0.12549f
333
334 if (of_add) {
335
2/4
void OL_AddImage::BlendImageMask_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 15 → 16 taken 15 times.
✓ Branch 15 → 18 taken 6 times.
void OL_AddImage::BlendImageMask_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 21 not taken.
21 if (Y > max_pixel_value) { // Y > 1.0f
336 15 float multiplier = max(0.0f, 1.0f + over32 - Y); // 1.12549 - Y, clamp to >=0
337 // Blend U/V toward neutral (0.0f)
338 15 U = U * multiplier / over32;
339 15 V = V * multiplier / over32;
340 15 Y = max_pixel_value; // 1.0f
341 }
342 }
343 else {
344
2/4
void OL_AddImage::BlendImageMask_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 14 → 15 taken 12 times.
✓ Branch 14 → 17 taken 9 times.
void OL_AddImage::BlendImageMask_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 20 not taken.
21 if (Y < 0.0f) {
345 12 float multiplier = min(-Y, over32); // 0 to over32
346 12 U = U * (over32 - multiplier) / over32;
347 12 V = V * (over32 - multiplier) / over32;
348 12 Y = 0.0f;
349 }
350 }
351
352 // No other clamping for float
353 42 baseU[x] = U;
354 42 baseV[x] = V;
355 42 baseY[x] = Y;
356 }
357 6 baseY += basepitch;
358 6 baseU += basepitch;
359 6 baseV += basepitch;
360
361 6 ovY += overlaypitch;
362 6 ovU += overlaypitch;
363 6 ovV += overlaypitch;
364
365 if (maskMode) {
366 maskY += maskpitch;
367 maskU += maskpitch;
368 maskV += maskpitch;
369 }
370 }
371 } else {
372
4/8
void OL_AddImage::BlendImageMask_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 33 → 23 taken 3 times.
✓ Branch 33 → 34 taken 1 time.
void OL_AddImage::BlendImageMask_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 35 → 24 taken 3 times.
✓ Branch 35 → 36 taken 1 time.
void OL_AddImage::BlendImageMask_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 36 → 25 not taken.
✗ Branch 36 → 37 not taken.
void OL_AddImage::BlendImageMask_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 37 → 26 not taken.
✗ Branch 37 → 38 not taken.
8 for (int y = 0; y < h; y++) {
373
4/8
void OL_AddImage::BlendImageMask_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 30 → 24 taken 21 times.
✓ Branch 30 → 31 taken 3 times.
void OL_AddImage::BlendImageMask_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 32 → 25 taken 21 times.
✓ Branch 32 → 33 taken 3 times.
void OL_AddImage::BlendImageMask_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 34 → 26 not taken.
✗ Branch 34 → 35 not taken.
void OL_AddImage::BlendImageMask_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 35 → 27 not taken.
✗ Branch 35 → 36 not taken.
48 for (int x = 0; x < w; ++x) {
374 float Y, U, V;
375 if (of_add)
376 21 Y = baseY[x] + (maskMode ? maskY[x] * opacity_f * ovY[x] : opacity_f * ovY[x]);
377 else
378 21 Y = baseY[x] - (maskMode ? maskY[x] * opacity_f * ovY[x] : opacity_f * ovY[x]);
379 if (maskMode) {
380 float mU = maskU[x] * opacity_f;
381 float mV = maskV[x] * opacity_f;
382 if (of_add) {
383 U = baseU[x] + (half_pixel_value * (pixel_range - mU) + mU * ovU[x]) - half_pixel_value;
384 V = baseV[x] + (half_pixel_value * (pixel_range - mV) + mV * ovV[x]) - half_pixel_value;
385 } else {
386 U = baseU[x] - (half_pixel_value * (pixel_range - mU) + mU * ovU[x]) + half_pixel_value;
387 V = baseV[x] - (half_pixel_value * (pixel_range - mV) + mV * ovV[x]) + half_pixel_value;
388 }
389 } else {
390 if (of_add) {
391 21 U = baseU[x] + (half_pixel_value * inv_opacity_f + opacity_f * ovU[x]) - half_pixel_value;
392 21 V = baseV[x] + (half_pixel_value * inv_opacity_f + opacity_f * ovV[x]) - half_pixel_value;
393 } else {
394 21 U = baseU[x] - (half_pixel_value * inv_opacity_f + opacity_f * ovU[x]) + half_pixel_value;
395 21 V = baseV[x] - (half_pixel_value * inv_opacity_f + opacity_f * ovV[x]) + half_pixel_value;
396 }
397 }
398
399 42 constexpr float over32 = 32.0f / 255.0f; // ~0.12549f
400
401 if (of_add) {
402
2/4
void OL_AddImage::BlendImageMask_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 28 → 29 taken 6 times.
✓ Branch 28 → 31 taken 15 times.
void OL_AddImage::BlendImageMask_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 34 not taken.
21 if (Y > max_pixel_value) { // Y > 1.0f
403 6 float multiplier = max(0.0f, 1.0f + over32 - Y); // 1.12549 - Y, clamp to >=0
404 // Blend U/V toward neutral (0.0f)
405 6 U = U * multiplier / over32;
406 6 V = V * multiplier / over32;
407 6 Y = max_pixel_value; // 1.0f
408 }
409 }
410 else {
411
2/4
void OL_AddImage::BlendImageMask_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 26 → 27 taken 9 times.
✓ Branch 26 → 29 taken 12 times.
void OL_AddImage::BlendImageMask_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 33 not taken.
21 if (Y < 0.0f) {
412 9 float multiplier = min(-Y, over32); // 0 to over32
413 9 U = U * (over32 - multiplier) / over32;
414 9 V = V * (over32 - multiplier) / over32;
415 9 Y = 0.0f;
416 }
417 }
418
419 // No other clamping for float
420 42 baseU[x] = U;
421 42 baseV[x] = V;
422 42 baseY[x] = Y;
423 }
424 6 baseY += basepitch;
425 6 baseU += basepitch;
426 6 baseV += basepitch;
427
428 6 ovY += overlaypitch;
429 6 ovU += overlaypitch;
430 6 ovV += overlaypitch;
431
432 if (maskMode) {
433 maskY += maskpitch;
434 maskU += maskpitch;
435 maskV += maskpitch;
436 }
437 }
438 }
439 4 }
440
441
442 // integer 8-16-bit RGB add/subtract
443 template<typename pixel_t, bool maskMode, bool of_add>
444 4 void OL_AddImage::BlendImageMask_RGB(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) {
445 4 int w = base->w();
446 4 int h = base->h();
447 4 const int pixelsize = sizeof(pixel_t);
448 4 const int max_pixel_value = (sizeof(pixel_t) == 1) ? 255 : (1 << bits_per_pixel) - 1;
449 4 auto factor = maskMode ? opacity_f / max_pixel_value : opacity_f;
450
451
4/16
void OL_AddImage::BlendImageMask_RGB<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 5 not taken.
✗ Branch 18 → 19 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 5 not taken.
✗ Branch 18 → 19 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 20 → 5 not taken.
✗ Branch 20 → 21 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 20 → 5 not taken.
✗ Branch 20 → 21 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 18 → 5 taken 6 times.
✓ Branch 18 → 19 taken 2 times.
void OL_AddImage::BlendImageMask_RGB<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 18 → 5 taken 6 times.
✓ Branch 18 → 19 taken 2 times.
void OL_AddImage::BlendImageMask_RGB<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 20 → 5 not taken.
✗ Branch 20 → 21 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 20 → 5 not taken.
✗ Branch 20 → 21 not taken.
16 for (int p = 0; p < 3; ++p) {
452 12 pixel_t* baseP = reinterpret_cast<pixel_t*>(base->GetPtrByIndex(p));
453 12 pixel_t* ovP = reinterpret_cast<pixel_t*>(overlay->GetPtrByIndex(p));
454 12 pixel_t* maskP = maskMode ? reinterpret_cast<pixel_t*>(mask->GetPtrByIndex(p)) : nullptr;
455 12 int basePitch = base->GetPitchByIndex(p) / pixelsize;
456 12 int overlayPitch = overlay->GetPitchByIndex(p) / pixelsize;
457 12 int maskPitch = maskMode ? (mask->GetPitchByIndex(p) / pixelsize) : 0;
458
459
4/16
void OL_AddImage::BlendImageMask_RGB<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 10 not taken.
✗ Branch 16 → 17 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 10 not taken.
✗ Branch 16 → 17 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 12 not taken.
✗ Branch 18 → 19 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 12 not taken.
✗ Branch 18 → 19 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 16 → 10 taken 18 times.
✓ Branch 16 → 17 taken 6 times.
void OL_AddImage::BlendImageMask_RGB<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 16 → 10 taken 18 times.
✓ Branch 16 → 17 taken 6 times.
void OL_AddImage::BlendImageMask_RGB<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 12 not taken.
✗ Branch 18 → 19 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 12 not taken.
✗ Branch 18 → 19 not taken.
48 for (int y = 0; y < h; ++y) {
460
4/16
void OL_AddImage::BlendImageMask_RGB<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 14 → 11 not taken.
✗ Branch 14 → 15 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 14 → 11 not taken.
✗ Branch 14 → 15 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 13 not taken.
✗ Branch 16 → 17 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 13 not taken.
✗ Branch 16 → 17 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 14 → 11 taken 90 times.
✓ Branch 14 → 15 taken 18 times.
void OL_AddImage::BlendImageMask_RGB<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 14 → 11 taken 90 times.
✓ Branch 14 → 15 taken 18 times.
void OL_AddImage::BlendImageMask_RGB<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 13 not taken.
✗ Branch 16 → 17 not taken.
void OL_AddImage::BlendImageMask_RGB<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 13 not taken.
✗ Branch 16 → 17 not taken.
216 for (int x = 0; x < w; ++x) {
461 180 int baseVal = baseP[x];
462 180 int ovVal = ovP[x];
463
464 180 const float new_mask = maskMode ? (float)reinterpret_cast<const pixel_t*>(maskP)[x] * factor : factor;
465 float result;
466
467 if constexpr (of_add)
468 90 result = baseVal + ovVal * new_mask;
469 else
470 90 result = baseVal - ovVal * new_mask;
471
472 180 baseP[x] = (pixel_t)(min(max((int)(result + 0.5f), 0), max_pixel_value));
473 }
474 36 baseP += basePitch;
475 36 ovP += overlayPitch;
476 if constexpr (maskMode) maskP += maskPitch;
477 }
478 }
479 4 }
480
481
482 // 32-bit float RGB add/subtract
483 template<bool maskMode, bool of_add>
484 4 void OL_AddImage::BlendImageMask_RGB_float(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) {
485 4 int w = base->w();
486 4 int h = base->h();
487
488 4 auto factor = maskMode ? opacity_f / 1.0f : opacity_f; // for float, max_pixel_value is 1.0f for masks
489
490
4/8
void OL_AddImage::BlendImageMask_RGB_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 16 → 5 taken 6 times.
✓ Branch 16 → 17 taken 2 times.
void OL_AddImage::BlendImageMask_RGB_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 16 → 5 taken 6 times.
✓ Branch 16 → 17 taken 2 times.
void OL_AddImage::BlendImageMask_RGB_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 5 not taken.
✗ Branch 18 → 19 not taken.
void OL_AddImage::BlendImageMask_RGB_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 18 → 5 not taken.
✗ Branch 18 → 19 not taken.
16 for (int p = 0; p < 3; ++p) {
491 12 float* baseP = reinterpret_cast<float*>(base->GetPtrByIndex(p));
492 12 float* ovP = reinterpret_cast<float*>(overlay->GetPtrByIndex(p));
493 12 float* maskP = maskMode ? reinterpret_cast<float*>(mask->GetPtrByIndex(p)) : nullptr;
494 12 int basePitch = base->GetPitchByIndex(p) / sizeof(float);
495 12 int overlayPitch = overlay->GetPitchByIndex(p) / sizeof(float);
496 12 int maskPitch = maskMode ? (mask->GetPitchByIndex(p) / sizeof(float)) : 0;
497
498
4/8
void OL_AddImage::BlendImageMask_RGB_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 14 → 10 taken 18 times.
✓ Branch 14 → 15 taken 6 times.
void OL_AddImage::BlendImageMask_RGB_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 14 → 10 taken 18 times.
✓ Branch 14 → 15 taken 6 times.
void OL_AddImage::BlendImageMask_RGB_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 12 not taken.
✗ Branch 16 → 17 not taken.
void OL_AddImage::BlendImageMask_RGB_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 12 not taken.
✗ Branch 16 → 17 not taken.
48 for (int y = 0; y < h; ++y) {
499
4/8
void OL_AddImage::BlendImageMask_RGB_float<false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 12 → 11 taken 90 times.
✓ Branch 12 → 13 taken 18 times.
void OL_AddImage::BlendImageMask_RGB_float<false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 12 → 11 taken 90 times.
✓ Branch 12 → 13 taken 18 times.
void OL_AddImage::BlendImageMask_RGB_float<true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 14 → 13 not taken.
✗ Branch 14 → 15 not taken.
void OL_AddImage::BlendImageMask_RGB_float<true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 14 → 13 not taken.
✗ Branch 14 → 15 not taken.
216 for (int x = 0; x < w; ++x) {
500 180 float baseVal = baseP[x];
501 180 float ovVal = ovP[x];
502
503 180 const float new_mask = maskMode ? (float)reinterpret_cast<const float*>(maskP)[x] * factor : factor;
504 float result;
505
506 if constexpr (of_add)
507 90 result = baseVal + ovVal * new_mask;
508 else
509 90 result = baseVal - ovVal * new_mask;
510 180 baseP[x] = result; // no clamping for float
511 }
512 36 baseP += basePitch;
513 36 ovP += overlayPitch;
514 if constexpr (maskMode) maskP += maskPitch;
515 }
516 }
517 4 }
518
519