Coverage Report

Created: 2025-07-16 07:53

/src/libjxl/lib/jxl/alpha.cc
Line
Count
Source (jump to first uncovered line)
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
0
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
960
                          bool alpha_is_premultiplied, bool clamp) {
20
960
  if (alpha_is_premultiplied) {
21
103k
    for (size_t x = 0; x < num_pixels; ++x) {
22
102k
      float fga = clamp ? Clamp(fg.a[x]) : fg.a[x];
23
102k
      out.r[x] = (fg.r[x] + bg.r[x] * (1.f - fga));
24
102k
      out.g[x] = (fg.g[x] + bg.g[x] * (1.f - fga));
25
102k
      out.b[x] = (fg.b[x] + bg.b[x] * (1.f - fga));
26
102k
      out.a[x] = (1.f - (1.f - fga) * (1.f - bg.a[x]));
27
102k
    }
28
960
  } else {
29
0
    for (size_t x = 0; x < num_pixels; ++x) {
30
0
      float fga = clamp ? Clamp(fg.a[x]) : fg.a[x];
31
0
      const float new_a = 1.f - (1.f - fga) * (1.f - bg.a[x]);
32
0
      const float rnew_a = (new_a > 0 ? 1.f / new_a : 0.f);
33
0
      out.r[x] = (fg.r[x] * fga + bg.r[x] * bg.a[x] * (1.f - fga)) * rnew_a;
34
0
      out.g[x] = (fg.g[x] * fga + bg.g[x] * bg.a[x] * (1.f - fga)) * rnew_a;
35
0
      out.b[x] = (fg.b[x] * fga + bg.b[x] * bg.a[x] * (1.f - fga)) * rnew_a;
36
0
      out.a[x] = new_a;
37
0
    }
38
0
  }
39
960
}
40
void PerformAlphaBlending(const float* bg, const float* bga, const float* fg,
41
                          const float* fga, float* out, size_t num_pixels,
42
0
                          bool alpha_is_premultiplied, bool clamp) {
43
0
  if (bg == bga && fg == fga) {
44
0
    for (size_t x = 0; x < num_pixels; ++x) {
45
0
      float fa = clamp ? fga[x] : Clamp(fga[x]);
46
0
      out[x] = (1.f - (1.f - fa) * (1.f - bga[x]));
47
0
    }
48
0
  } else {
49
0
    if (alpha_is_premultiplied) {
50
0
      for (size_t x = 0; x < num_pixels; ++x) {
51
0
        float fa = clamp ? fga[x] : Clamp(fga[x]);
52
0
        out[x] = (fg[x] + bg[x] * (1.f - fa));
53
0
      }
54
0
    } else {
55
0
      for (size_t x = 0; x < num_pixels; ++x) {
56
0
        float fa = clamp ? fga[x] : Clamp(fga[x]);
57
0
        const float new_a = 1.f - (1.f - fa) * (1.f - bga[x]);
58
0
        const float rnew_a = (new_a > 0 ? 1.f / new_a : 0.f);
59
0
        out[x] = (fg[x] * fa + bg[x] * bga[x] * (1.f - fa)) * rnew_a;
60
0
      }
61
0
    }
62
0
  }
63
0
}
64
65
void PerformAlphaWeightedAdd(const float* bg, const float* fg, const float* fga,
66
0
                             float* out, size_t num_pixels, bool clamp) {
67
0
  if (fg == fga) {
68
0
    memcpy(out, bg, num_pixels * sizeof(*out));
69
0
  } else if (clamp) {
70
0
    for (size_t x = 0; x < num_pixels; ++x) {
71
0
      out[x] = bg[x] + fg[x] * Clamp(fga[x]);
72
0
    }
73
0
  } else {
74
0
    for (size_t x = 0; x < num_pixels; ++x) {
75
0
      out[x] = bg[x] + fg[x] * fga[x];
76
0
    }
77
0
  }
78
0
}
79
80
void PerformMulBlending(const float* bg, const float* fg, float* out,
81
744
                        size_t num_pixels, bool clamp) {
82
744
  if (clamp) {
83
0
    for (size_t x = 0; x < num_pixels; ++x) {
84
0
      out[x] = bg[x] * Clamp(fg[x]);
85
0
    }
86
744
  } else {
87
167k
    for (size_t x = 0; x < num_pixels; ++x) {
88
166k
      out[x] = bg[x] * fg[x];
89
166k
    }
90
744
  }
91
744
}
92
93
void PremultiplyAlpha(float* JXL_RESTRICT r, float* JXL_RESTRICT g,
94
                      float* JXL_RESTRICT b, const float* JXL_RESTRICT a,
95
0
                      size_t num_pixels) {
96
0
  for (size_t x = 0; x < num_pixels; ++x) {
97
0
    const float multiplier = std::max(kSmallAlpha, a[x]);
98
0
    r[x] *= multiplier;
99
0
    g[x] *= multiplier;
100
0
    b[x] *= multiplier;
101
0
  }
102
0
}
103
104
void UnpremultiplyAlpha(float* JXL_RESTRICT r, float* JXL_RESTRICT g,
105
                        float* JXL_RESTRICT b, const float* JXL_RESTRICT a,
106
0
                        size_t num_pixels) {
107
0
  for (size_t x = 0; x < num_pixels; ++x) {
108
0
    const float multiplier = 1.f / std::max(kSmallAlpha, a[x]);
109
0
    r[x] *= multiplier;
110
0
    g[x] *= multiplier;
111
0
    b[x] *= multiplier;
112
0
  }
113
0
}
114
115
}  // namespace jxl