filters/overlay/OF_darken.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 "blend_common.h" | ||
| 40 | #ifdef INTEL_INTRINSICS | ||
| 41 | #include "intel/blend_common_sse.h" | ||
| 42 | #endif | ||
| 43 | |||
| 44 | #include <stdint.h> | ||
| 45 | #include <type_traits> | ||
| 46 | |||
| 47 | 4 | void OL_DarkenImage::DoBlendImageMask(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) { | |
| 48 |
2/2✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 7 taken 2 times.
|
4 | if(of_mode == OF_Darken) { |
| 49 |
1/2✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 5 not taken.
|
2 | if (bits_per_pixel == 8) |
| 50 | 2 | BlendImageMask<uint8_t, true, true>(base, overlay, mask); | |
| 51 | ✗ | else if(bits_per_pixel <= 16) | |
| 52 | ✗ | BlendImageMask<uint16_t, true, true>(base, overlay, mask); | |
| 53 | //else if(bits_per_pixel == 32) | ||
| 54 | // BlendImageMask<float>(base, overlay, mask); | ||
| 55 | } | ||
| 56 | else { | ||
| 57 | // OF_Lighten | ||
| 58 |
1/2✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 9 not taken.
|
2 | if (bits_per_pixel == 8) |
| 59 | 2 | BlendImageMask<uint8_t, true, false>(base, overlay, mask); | |
| 60 | ✗ | else if(bits_per_pixel <= 16) | |
| 61 | ✗ | BlendImageMask<uint16_t, true, false>(base, overlay, mask); | |
| 62 | //else if(bits_per_pixel == 32) | ||
| 63 | // BlendImageMask<float>(base, overlay, mask); | ||
| 64 | } | ||
| 65 | 4 | } | |
| 66 | |||
| 67 | 4 | void OL_DarkenImage::DoBlendImage(ImageOverlayInternal* base, ImageOverlayInternal* overlay) { | |
| 68 |
2/2✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 7 taken 2 times.
|
4 | if(of_mode == OF_Darken) { |
| 69 |
1/2✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 5 not taken.
|
2 | if (bits_per_pixel == 8) |
| 70 | 2 | BlendImageMask<uint8_t, false, true>(base, overlay, nullptr); | |
| 71 | ✗ | else if(bits_per_pixel <= 16) | |
| 72 | ✗ | BlendImageMask<uint16_t, false, true>(base, overlay, nullptr); | |
| 73 | //else if(bits_per_pixel == 32) | ||
| 74 | // BlendImageMask<float>(base, overlay, mask); | ||
| 75 | } | ||
| 76 | else { | ||
| 77 | // OF_Lighten | ||
| 78 |
1/2✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 9 not taken.
|
2 | if (bits_per_pixel == 8) |
| 79 | 2 | BlendImageMask<uint8_t, false, false>(base, overlay, nullptr); | |
| 80 | ✗ | else if(bits_per_pixel <= 16) | |
| 81 | ✗ | BlendImageMask<uint16_t, false, false>(base, overlay, nullptr); | |
| 82 | //else if(bits_per_pixel == 32) | ||
| 83 | // BlendImageMask<float>(base, overlay, mask); | ||
| 84 | } | ||
| 85 | 4 | } | |
| 86 | |||
| 87 | // float not supported yet | ||
| 88 | template<typename pixel_t, bool maskMode, bool of_darken> | ||
| 89 | 8 | void OL_DarkenImage::BlendImageMask(ImageOverlayInternal* base, ImageOverlayInternal* overlay, ImageOverlayInternal* mask) { | |
| 90 | |||
| 91 | 8 | pixel_t* baseY = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_Y)); | |
| 92 | 8 | pixel_t* baseU = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_U)); | |
| 93 | 8 | pixel_t* baseV = reinterpret_cast<pixel_t *>(base->GetPtr(PLANAR_V)); | |
| 94 | |||
| 95 | 8 | pixel_t* ovY = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_Y)); | |
| 96 | 8 | pixel_t* ovU = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_U)); | |
| 97 | 8 | pixel_t* ovV = reinterpret_cast<pixel_t *>(overlay->GetPtr(PLANAR_V)); | |
| 98 | |||
| 99 | 8 | pixel_t* maskY = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_Y)) : nullptr; | |
| 100 | 8 | pixel_t* maskU = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_U)) : nullptr; | |
| 101 | 8 | pixel_t* maskV = maskMode ? reinterpret_cast<pixel_t *>(mask->GetPtr(PLANAR_V)) : nullptr; | |
| 102 | |||
| 103 | 8 | const int half_pixel_value = (sizeof(pixel_t) == 1) ? 128 : (1 << (bits_per_pixel - 1)); | |
| 104 | 8 | const int max_pixel_value = (sizeof(pixel_t) == 1) ? 255 : (1 << bits_per_pixel) - 1; | |
| 105 | 8 | const int pixel_range = max_pixel_value + 1; | |
| 106 | 8 | const int MASK_CORR_SHIFT = (sizeof(pixel_t) == 1) ? 8 : bits_per_pixel; | |
| 107 | 8 | const int OPACITY_SHIFT = 8; // opacity always max 0..256 | |
| 108 | 8 | const int basepitch = (base->pitch) / sizeof(pixel_t); | |
| 109 | 8 | const int overlaypitch = (overlay->pitch) / sizeof(pixel_t); | |
| 110 | 8 | const int maskpitch = maskMode ? (mask->pitch) / sizeof(pixel_t) : 0; | |
| 111 | |||
| 112 | // avoid "uint16*uint16 can't get into int32" overflows | ||
| 113 | using result_t = typename std::conditional<sizeof(pixel_t) == 1, int, int64_t>::type; | ||
| 114 | |||
| 115 | 8 | int w = base->w(); | |
| 116 | 8 | int h = base->h(); | |
| 117 |
4/16void OL_DarkenImage::BlendImageMask<unsigned char, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 18 not taken.
void OL_DarkenImage::BlendImageMask<unsigned char, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 18 not taken.
void OL_DarkenImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 22 not taken.
void OL_DarkenImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 22 not taken.
void OL_DarkenImage::BlendImageMask<unsigned short, false, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
void OL_DarkenImage::BlendImageMask<unsigned short, false, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
void OL_DarkenImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 22 not taken.
void OL_DarkenImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 22 not taken.
|
8 | if (opacity == 256) { |
| 118 | // full opacity - optimize | ||
| 119 | if constexpr (maskMode) { | ||
| 120 | // opacity == 256 && maskMode | ||
| 121 |
4/8void OL_DarkenImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 21 → 15 taken 4 times.
✓ Branch 21 → 30 taken 2 times.
void OL_DarkenImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 21 → 15 taken 4 times.
✓ Branch 21 → 30 taken 2 times.
void OL_DarkenImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 21 → 15 not taken.
✗ Branch 21 → 30 not taken.
void OL_DarkenImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 21 → 15 not taken.
✗ Branch 21 → 30 not taken.
|
12 | for (int y = 0; y < h; y++) { |
| 122 |
4/8void OL_DarkenImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 19 → 16 taken 16 times.
✓ Branch 19 → 20 taken 4 times.
void OL_DarkenImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 19 → 16 taken 16 times.
✓ Branch 19 → 20 taken 4 times.
void OL_DarkenImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 19 → 16 not taken.
✗ Branch 19 → 20 not taken.
void OL_DarkenImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 19 → 16 not taken.
✗ Branch 19 → 20 not taken.
|
40 | for (int x = 0; x < w; x++) { |
| 123 | bool cmp; | ||
| 124 | if constexpr (of_darken) | ||
| 125 | 16 | cmp = ovY[x] < baseY[x]; | |
| 126 | else | ||
| 127 | 16 | cmp = ovY[x] > baseY[x]; | |
| 128 |
4/8void OL_DarkenImage::BlendImageMask<unsigned char, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 16 → 17 taken 8 times.
✓ Branch 16 → 18 taken 8 times.
void OL_DarkenImage::BlendImageMask<unsigned char, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✓ Branch 16 → 17 taken 8 times.
✓ Branch 16 → 18 taken 8 times.
void OL_DarkenImage::BlendImageMask<unsigned short, true, false>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
void OL_DarkenImage::BlendImageMask<unsigned short, true, true>(ImageOverlayInternal*, ImageOverlayInternal*, ImageOverlayInternal*):
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
|
32 | if (cmp) { |
| 129 | 16 | result_t maskYx = maskY[x]; | |
| 130 | 16 | result_t maskUx = maskU[x]; | |
| 131 | 16 | result_t maskVx = maskV[x]; | |
| 132 | 16 | baseY[x] = (pixel_t)((((pixel_range - maskYx)*baseY[x]) + (maskYx * ovY[x] + half_pixel_value)) >> MASK_CORR_SHIFT); | |
| 133 | 16 | baseU[x] = (pixel_t)((((pixel_range - maskUx)*baseU[x]) + (maskUx * ovU[x] + half_pixel_value)) >> MASK_CORR_SHIFT); | |
| 134 | 16 | baseV[x] = (pixel_t)((((pixel_range - maskVx)*baseV[x]) + (maskVx * ovV[x] + half_pixel_value)) >> MASK_CORR_SHIFT); | |
| 135 | } | ||
| 136 | } | ||
| 137 | 8 | maskY += maskpitch; | |
| 138 | 8 | maskU += maskpitch; | |
| 139 | 8 | maskV += maskpitch; | |
| 140 | |||
| 141 | 8 | baseY += basepitch; | |
| 142 | 8 | baseU += basepitch; | |
| 143 | 8 | baseV += basepitch; | |
| 144 | |||
| 145 | 8 | ovY += overlaypitch; | |
| 146 | 8 | ovU += overlaypitch; | |
| 147 | 8 | ovV += overlaypitch; | |
| 148 | } | ||
| 149 | } else { | ||
| 150 | // opacity == 256 && !maskMode | ||
| 151 | if constexpr (of_darken) { | ||
| 152 | #ifdef INTEL_INTRINSICS | ||
| 153 |
1/2✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 14 not taken.
|
2 | if (sizeof(pixel_t)==1 && (env->GetCPUFlags() & CPUF_SSE4_1)) { |
| 154 | 2 | overlay_darken_sse41((BYTE *)baseY, (BYTE *)baseU, (BYTE *)baseV, (BYTE *)ovY, (BYTE *)ovU, (BYTE *)ovV, basepitch, overlaypitch, w, h); | |
| 155 | ✗ | } else if (sizeof(pixel_t)==1 && (env->GetCPUFlags() & CPUF_SSE2)) { | |
| 156 | ✗ | overlay_darken_sse2((BYTE *)baseY, (BYTE *)baseU, (BYTE *)baseV, (BYTE *)ovY, (BYTE *)ovU, (BYTE *)ovV, basepitch, overlaypitch, w, h); | |
| 157 | } else | ||
| 158 | #ifdef X86_32 | ||
| 159 | if (sizeof(pixel_t)==1 && (env->GetCPUFlags() & CPUF_MMX)) { | ||
| 160 | overlay_darken_mmx((BYTE *)baseY, (BYTE *)baseU, (BYTE *)baseV, (BYTE *)ovY, (BYTE *)ovU, (BYTE *)ovV, basepitch, overlaypitch, w, h); | ||
| 161 | } else | ||
| 162 | #endif | ||
| 163 | #endif | ||
| 164 | { | ||
| 165 | |||
| 166 | ✗ | overlay_darken_c<pixel_t>((BYTE *)baseY, (BYTE *)baseU, (BYTE *)baseV, (BYTE *)ovY, (BYTE *)ovU, (BYTE *)ovV, basepitch, overlaypitch, w, h); | |
| 167 | } | ||
| 168 | } else { | ||
| 169 | // OF_Lighten | ||
| 170 | #ifdef INTEL_INTRINSICS | ||
| 171 |
1/2✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 14 not taken.
|
2 | if (sizeof(pixel_t)==1 && (env->GetCPUFlags() & CPUF_SSE4_1)) { |
| 172 | 2 | overlay_lighten_sse41((BYTE *)baseY, (BYTE *)baseU, (BYTE *)baseV, (BYTE *)ovY, (BYTE *)ovU, (BYTE *)ovV, basepitch, overlaypitch, w, h); | |
| 173 | ✗ | } else if (sizeof(pixel_t)==1 && (env->GetCPUFlags() & CPUF_SSE2)) { | |
| 174 | ✗ | overlay_lighten_sse2((BYTE *)baseY, (BYTE *)baseU, (BYTE *)baseV, (BYTE *)ovY, (BYTE *)ovU, (BYTE *)ovV, basepitch, overlaypitch, w, h); | |
| 175 | } else | ||
| 176 | #ifdef X86_32 | ||
| 177 | if (sizeof(pixel_t)==1 && (env->GetCPUFlags() & CPUF_MMX)) { | ||
| 178 | overlay_lighten_mmx((BYTE *)baseY, (BYTE *)baseU, (BYTE *)baseV, (BYTE *)ovY, (BYTE *)ovU, (BYTE *)ovV, basepitch, overlaypitch, w, h); | ||
| 179 | } else | ||
| 180 | #endif | ||
| 181 | #endif | ||
| 182 | { | ||
| 183 | ✗ | overlay_lighten_c<pixel_t>((BYTE *)baseY, (BYTE *)baseU, (BYTE *)baseV, (BYTE *)ovY, (BYTE *)ovU, (BYTE *)ovV, basepitch, overlaypitch, w, h); | |
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | } | ||
| 188 | } else { | ||
| 189 | // opacity != 256 && maskMode | ||
| 190 | ✗ | for (int y = 0; y < h; y++) { | |
| 191 | ✗ | for (int x = 0; x < w; x++) { | |
| 192 | bool cmp; | ||
| 193 | if constexpr (of_darken) | ||
| 194 | ✗ | cmp = ovY[x] < baseY[x]; | |
| 195 | else | ||
| 196 | ✗ | cmp = ovY[x] > baseY[x]; | |
| 197 | ✗ | if (cmp) { | |
| 198 | if constexpr (maskMode) { | ||
| 199 | ✗ | result_t mY = (maskY[x] * opacity) >> OPACITY_SHIFT; | |
| 200 | ✗ | result_t mU = (maskU[x] * opacity) >> OPACITY_SHIFT; | |
| 201 | ✗ | result_t mV = (maskV[x] * opacity) >> OPACITY_SHIFT; | |
| 202 | ✗ | baseY[x] = (pixel_t)((((pixel_range - mY)*baseY[x]) + (mY*ovY[x] + half_pixel_value)) >> MASK_CORR_SHIFT); | |
| 203 | ✗ | baseU[x] = (pixel_t)((((pixel_range - mU)*baseU[x]) + (mU*ovU[x] + half_pixel_value)) >> MASK_CORR_SHIFT); | |
| 204 | ✗ | baseV[x] = (pixel_t)((((pixel_range - mV)*baseV[x]) + (mV*ovV[x] + half_pixel_value)) >> MASK_CORR_SHIFT); | |
| 205 | } | ||
| 206 | else { | ||
| 207 | ✗ | baseY[x] = (pixel_t)(((inv_opacity*baseY[x]) + (opacity*ovY[x] + 128)) >> OPACITY_SHIFT); // 128: half 256 opacity mul rounding | |
| 208 | ✗ | baseU[x] = (pixel_t)(((inv_opacity*baseU[x]) + (opacity*ovU[x] + 128)) >> OPACITY_SHIFT); | |
| 209 | ✗ | baseV[x] = (pixel_t)(((inv_opacity*baseV[x]) + (opacity*ovV[x] + 128)) >> OPACITY_SHIFT); | |
| 210 | } | ||
| 211 | } | ||
| 212 | } | ||
| 213 | ✗ | baseY += basepitch; | |
| 214 | ✗ | baseU += basepitch; | |
| 215 | ✗ | baseV += basepitch; | |
| 216 | |||
| 217 | ✗ | ovY += overlaypitch; | |
| 218 | ✗ | ovU += overlaypitch; | |
| 219 | ✗ | ovV += overlaypitch; | |
| 220 | |||
| 221 | if constexpr (maskMode) { | ||
| 222 | ✗ | maskY += maskpitch; | |
| 223 | ✗ | maskU += maskpitch; | |
| 224 | ✗ | maskV += maskpitch; | |
| 225 | } | ||
| 226 | } | ||
| 227 | } | ||
| 228 | 8 | } | |
| 229 | |||
| 230 |