Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/jpeg-xl/lib/jxl/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 kB image not shown  

Quelle  blending.cc   Sprache: C

 
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "lib/jxl/blending.h"

#include <jxl/memory_manager.h>

#include <cstddef>
#include <cstring>
#include <vector>

#include "lib/jxl/alpha.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_patch_dictionary.h"
#include "lib/jxl/frame_header.h"
#include "lib/jxl/image.h"
#include "lib/jxl/image_metadata.h"

namespace jxl {

bool NeedsBlending(const FrameHeader& frame_header) {
  if (!(frame_header.frame_type == FrameType::kRegularFrame ||
        frame_header.frame_type == FrameType::kSkipProgressive)) {
    return false;
  }
  const auto& info = frame_header.blending_info;
  bool replace_all = (info.mode == BlendMode::kReplace);
  for (const auto& ec_i : frame_header.extra_channel_blending_info) {
    if (ec_i.mode != BlendMode::kReplace) {
      replace_all = false;
    }
  }
  // Replace the full frame: nothing to do.
  if (!frame_header.custom_size_or_origin && replace_all) {
    return false;
  }
  return true;
}

Status PerformBlending(
    JxlMemoryManager* memory_manager, const floatconst* bg,
    const floatconst* fg, floatconst* out, size_t x0, size_t xsize,
    const PatchBlending& color_blending, const PatchBlending* ec_blending,
    const std::vector<ExtraChannelInfo>& extra_channel_info) {
  bool has_alpha = false;
  size_t num_ec = extra_channel_info.size();
  for (size_t i = 0; i < num_ec; i++) {
    if (extra_channel_info[i].type == jxl::ExtraChannel::kAlpha) {
      has_alpha = true;
      break;
    }
  }
  JXL_ASSIGN_OR_RETURN(ImageF tmp,
                       ImageF::Create(memory_manager, xsize, 3 + num_ec));
  // Blend extra channels first so that we use the pre-blending alpha.
  for (size_t i = 0; i < num_ec; i++) {
    switch (ec_blending[i].mode) {
      case PatchBlendMode::kAdd:
        for (size_t x = 0; x < xsize; x++) {
          tmp.Row(3 + i)[x] = bg[3 + i][x + x0] + fg[3 + i][x + x0];
        }
        continue;

      case PatchBlendMode::kBlendAbove: {
        size_t alpha = ec_blending[i].alpha_channel;
        bool is_premultiplied = extra_channel_info[alpha].alpha_associated;
        PerformAlphaBlending(bg[3 + i] + x0, bg[3 + alpha] + x0, fg[3 + i] + x0,
                             fg[3 + alpha] + x0, tmp.Row(3 + i), xsize,
                             is_premultiplied, ec_blending[i].clamp);
        continue;
      }

      case PatchBlendMode::kBlendBelow: {
        size_t alpha = ec_blending[i].alpha_channel;
        bool is_premultiplied = extra_channel_info[alpha].alpha_associated;
        PerformAlphaBlending(fg[3 + i] + x0, fg[3 + alpha] + x0, bg[3 + i] + x0,
                             bg[3 + alpha] + x0, tmp.Row(3 + i), xsize,
                             is_premultiplied, ec_blending[i].clamp);
        continue;
      }

      case PatchBlendMode::kAlphaWeightedAddAbove: {
        size_t alpha = ec_blending[i].alpha_channel;
        PerformAlphaWeightedAdd(bg[3 + i] + x0, fg[3 + i] + x0,
                                fg[3 + alpha] + x0, tmp.Row(3 + i), xsize,
                                ec_blending[i].clamp);
        continue;
      }

      case PatchBlendMode::kAlphaWeightedAddBelow: {
        size_t alpha = ec_blending[i].alpha_channel;
        PerformAlphaWeightedAdd(fg[3 + i] + x0, bg[3 + i] + x0,
                                bg[3 + alpha] + x0, tmp.Row(3 + i), xsize,
                                ec_blending[i].clamp);
        continue;
      }

      case PatchBlendMode::kMul:
        PerformMulBlending(bg[3 + i] + x0, fg[3 + i] + x0, tmp.Row(3 + i),
                           xsize, ec_blending[i].clamp);
        continue;

      case PatchBlendMode::kReplace:
        if (xsize) memcpy(tmp.Row(3 + i), fg[3 + i] + x0, xsize * sizeof(**fg));
        continue;

      case PatchBlendMode::kNone:
        if (xsize) memcpy(tmp.Row(3 + i), bg[3 + i] + x0, xsize * sizeof(**fg));
        continue;
    }
  }
  size_t alpha = color_blending.alpha_channel;

  const auto add = [&]() {
    for (int p = 0; p < 3; p++) {
      float* out = tmp.Row(p);
      for (size_t x = 0; x < xsize; x++) {
        out[x] = bg[p][x + x0] + fg[p][x + x0];
      }
    }
  };

  const auto blend_weighted = [&](const floatconst* bottom,
                                  const floatconst* top) {
    bool is_premultiplied = extra_channel_info[alpha].alpha_associated;
    PerformAlphaBlending(
        {bottom[0] + x0, bottom[1] + x0, bottom[2] + x0,
         bottom[3 + alpha] + x0},
        {top[0] + x0, top[1] + x0, top[2] + x0, top[3 + alpha] + x0},
        {tmp.Row(0), tmp.Row(1), tmp.Row(2), tmp.Row(3 + alpha)}, xsize,
        is_premultiplied, color_blending.clamp);
  };

  const auto add_weighted = [&](const floatconst* bottom,
                                const floatconst* top) {
    for (size_t c = 0; c < 3; c++) {
      PerformAlphaWeightedAdd(bottom[c] + x0, top[c] + x0, top[3 + alpha] + x0,
                              tmp.Row(c), xsize, color_blending.clamp);
    }
  };

  const auto copy = [&](const floatconst* src) {
    for (size_t p = 0; p < 3; p++) {
      memcpy(tmp.Row(p), src[p] + x0, xsize * sizeof(**src));
    }
  };

  switch (color_blending.mode) {
    case PatchBlendMode::kAdd:
      add();
      break;

    case PatchBlendMode::kAlphaWeightedAddAbove:
      has_alpha ? add_weighted(bg, fg) : add();
      break;

    case PatchBlendMode::kAlphaWeightedAddBelow:
      has_alpha ? add_weighted(fg, bg) : add();
      break;

    case PatchBlendMode::kBlendAbove:
      has_alpha ? blend_weighted(bg, fg) : copy(fg);
      break;

    case PatchBlendMode::kBlendBelow:
      has_alpha ? blend_weighted(fg, bg) : copy(fg);
      break;

    case PatchBlendMode::kMul:
      for (int p = 0; p < 3; p++) {
        PerformMulBlending(bg[p] + x0, fg[p] + x0, tmp.Row(p), xsize,
                           color_blending.clamp);
      }
      break;

    case PatchBlendMode::kReplace:
      copy(fg);
      break;

    case PatchBlendMode::kNone:
      copy(bg);
  }

  for (size_t i = 0; i < 3 + num_ec; i++) {
    if (xsize != 0) memcpy(out[i] + x0, tmp.Row(i), xsize * sizeof(**out));
  }
  return true;
}

}  // namespace jxl

Messung V0.5
C=81 H=79 G=79

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.