libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

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