// 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. #ifndef LIB_JXL_DEC_PATCH_DICTIONARY_H_ #define LIB_JXL_DEC_PATCH_DICTIONARY_H_ // Chooses reference patches, and avoids encoding them once per occurrence. #include #include #include #include #include #include #include "lib/jxl/base/status.h" #include "lib/jxl/dec_bit_reader.h" namespace jxl { enum class PatchBlendMode : uint8_t { // The new values are the old ones. Useful to skip some channels. kNone = 0, // The new values (in the crop) replace the old ones: sample = new kReplace = 1, // The new values (in the crop) get added to the old ones: sample = old + new kAdd = 2, // The new values (in the crop) get multiplied by the old ones: // sample = old * new // This blend mode is only supported if BlendColorSpace is kEncoded. The // range of the new value matters for multiplication purposes, and its // nominal range of 0..1 is computed the same way as this is done for the // alpha values in kBlend and kAlphaWeightedAdd. kMul = 3, // The new values (in the crop) replace the old ones if alpha>0: // For first alpha channel: // alpha = old + new * (1 - old) // For other channels if !alpha_associated: // sample = ((1 - new_alpha) * old * old_alpha + new_alpha * new) / alpha // For other channels if alpha_associated: // sample = (1 - new_alpha) * old + new // The alpha formula applies to the alpha used for the division in the other // channels formula, and applies to the alpha channel itself if its // blend_channel value matches itself. // If using kBlendAbove, new is the patch and old is the original image; if // using kBlendBelow, the meaning is inverted. kBlendAbove = 4, kBlendBelow = 5, // The new values (in the crop) are added to the old ones if alpha>0: // For first alpha channel: sample = sample = old + new * (1 - old) // For other channels: sample = old + alpha * new kAlphaWeightedAddAbove = 6, kAlphaWeightedAddBelow = 7, kNumBlendModes, }; inline bool UsesAlpha(PatchBlendMode mode) { return mode == PatchBlendMode::kBlendAbove || mode == PatchBlendMode::kBlendBelow || mode == PatchBlendMode::kAlphaWeightedAddAbove || mode == PatchBlendMode::kAlphaWeightedAddBelow; } inline bool UsesClamp(PatchBlendMode mode) { return UsesAlpha(mode) || mode == PatchBlendMode::kMul; } struct PatchBlending { PatchBlendMode mode; uint32_t alpha_channel; bool clamp; }; // Position and size of the patch in the reference frame. struct PatchReferencePosition { size_t ref, x0, y0, xsize, ysize; }; struct PatchPosition { // Position of top-left corner of the patch in the image. size_t x, y; size_t ref_pos_idx; }; struct PassesSharedState; // Encoder-side helper class to encode the PatchesDictionary. class PatchDictionaryEncoder; class PatchDictionary { public: PatchDictionary() = default; void SetPassesSharedState(const PassesSharedState* shared) { shared_ = shared; } bool HasAny() const { return !positions_.empty(); } Status Decode(BitReader* br, size_t xsize, size_t ysize, bool* uses_extra_channels); void Clear() { positions_.clear(); ComputePatchTree(); } // Adds patches to a segment of `xsize` pixels, starting at `inout`, assumed // to be located at position (x0, y) in the frame. Status AddOneRow(float* const* inout, size_t y, size_t x0, size_t xsize) const; // Returns dependencies of this patch dictionary on reference frame ids as a // bit mask: bits 0-3 indicate reference frame 0-3. int GetReferences() const; std::vector GetPatchesForRow(size_t y) const; private: friend class PatchDictionaryEncoder; const PassesSharedState* shared_; std::vector positions_; std::vector ref_positions_; std::vector blendings_; // Interval tree on the y coordinates of the patches. struct PatchTreeNode { ssize_t left_child; ssize_t right_child; size_t y_center; // Range of patches in sorted_patches_y0_ and sorted_patches_y1_ that // contain the row y_center. size_t start; size_t num; }; std::vector patch_tree_; // Number of patches for each row. std::vector num_patches_; std::vector> sorted_patches_y0_; std::vector> sorted_patches_y1_; void ComputePatchTree(); }; } // namespace jxl #endif // LIB_JXL_DEC_PATCH_DICTIONARY_H_