alpha.cc (3933B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #include "lib/jxl/alpha.h" 7 8 #include <string.h> 9 10 #include <algorithm> 11 12 namespace jxl { 13 14 static float Clamp(float x) { return std::max(std::min(1.0f, x), 0.0f); } 15 16 void PerformAlphaBlending(const AlphaBlendingInputLayer& bg, 17 const AlphaBlendingInputLayer& fg, 18 const AlphaBlendingOutput& out, size_t num_pixels, 19 bool alpha_is_premultiplied, bool clamp) { 20 if (alpha_is_premultiplied) { 21 for (size_t x = 0; x < num_pixels; ++x) { 22 float fga = clamp ? Clamp(fg.a[x]) : fg.a[x]; 23 out.r[x] = (fg.r[x] + bg.r[x] * (1.f - fga)); 24 out.g[x] = (fg.g[x] + bg.g[x] * (1.f - fga)); 25 out.b[x] = (fg.b[x] + bg.b[x] * (1.f - fga)); 26 out.a[x] = (1.f - (1.f - fga) * (1.f - bg.a[x])); 27 } 28 } else { 29 for (size_t x = 0; x < num_pixels; ++x) { 30 float fga = clamp ? Clamp(fg.a[x]) : fg.a[x]; 31 const float new_a = 1.f - (1.f - fga) * (1.f - bg.a[x]); 32 const float rnew_a = (new_a > 0 ? 1.f / new_a : 0.f); 33 out.r[x] = (fg.r[x] * fga + bg.r[x] * bg.a[x] * (1.f - fga)) * rnew_a; 34 out.g[x] = (fg.g[x] * fga + bg.g[x] * bg.a[x] * (1.f - fga)) * rnew_a; 35 out.b[x] = (fg.b[x] * fga + bg.b[x] * bg.a[x] * (1.f - fga)) * rnew_a; 36 out.a[x] = new_a; 37 } 38 } 39 } 40 void PerformAlphaBlending(const float* bg, const float* bga, const float* fg, 41 const float* fga, float* out, size_t num_pixels, 42 bool alpha_is_premultiplied, bool clamp) { 43 if (bg == bga && fg == fga) { 44 for (size_t x = 0; x < num_pixels; ++x) { 45 float fa = clamp ? fga[x] : Clamp(fga[x]); 46 out[x] = (1.f - (1.f - fa) * (1.f - bga[x])); 47 } 48 } else { 49 if (alpha_is_premultiplied) { 50 for (size_t x = 0; x < num_pixels; ++x) { 51 float fa = clamp ? fga[x] : Clamp(fga[x]); 52 out[x] = (fg[x] + bg[x] * (1.f - fa)); 53 } 54 } else { 55 for (size_t x = 0; x < num_pixels; ++x) { 56 float fa = clamp ? fga[x] : Clamp(fga[x]); 57 const float new_a = 1.f - (1.f - fa) * (1.f - bga[x]); 58 const float rnew_a = (new_a > 0 ? 1.f / new_a : 0.f); 59 out[x] = (fg[x] * fa + bg[x] * bga[x] * (1.f - fa)) * rnew_a; 60 } 61 } 62 } 63 } 64 65 void PerformAlphaWeightedAdd(const float* bg, const float* fg, const float* fga, 66 float* out, size_t num_pixels, bool clamp) { 67 if (fg == fga) { 68 memcpy(out, bg, num_pixels * sizeof(*out)); 69 } else if (clamp) { 70 for (size_t x = 0; x < num_pixels; ++x) { 71 out[x] = bg[x] + fg[x] * Clamp(fga[x]); 72 } 73 } else { 74 for (size_t x = 0; x < num_pixels; ++x) { 75 out[x] = bg[x] + fg[x] * fga[x]; 76 } 77 } 78 } 79 80 void PerformMulBlending(const float* bg, const float* fg, float* out, 81 size_t num_pixels, bool clamp) { 82 if (clamp) { 83 for (size_t x = 0; x < num_pixels; ++x) { 84 out[x] = bg[x] * Clamp(fg[x]); 85 } 86 } else { 87 for (size_t x = 0; x < num_pixels; ++x) { 88 out[x] = bg[x] * fg[x]; 89 } 90 } 91 } 92 93 void PremultiplyAlpha(float* JXL_RESTRICT r, float* JXL_RESTRICT g, 94 float* JXL_RESTRICT b, const float* JXL_RESTRICT a, 95 size_t num_pixels) { 96 for (size_t x = 0; x < num_pixels; ++x) { 97 const float multiplier = std::max(kSmallAlpha, a[x]); 98 r[x] *= multiplier; 99 g[x] *= multiplier; 100 b[x] *= multiplier; 101 } 102 } 103 104 void UnpremultiplyAlpha(float* JXL_RESTRICT r, float* JXL_RESTRICT g, 105 float* JXL_RESTRICT b, const float* JXL_RESTRICT a, 106 size_t num_pixels) { 107 for (size_t x = 0; x < num_pixels; ++x) { 108 const float multiplier = 1.f / std::max(kSmallAlpha, a[x]); 109 r[x] *= multiplier; 110 g[x] *= multiplier; 111 b[x] *= multiplier; 112 } 113 } 114 115 } // namespace jxl