libjxl

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

dec_patch_dictionary.h (4668B)


      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 #ifndef LIB_JXL_DEC_PATCH_DICTIONARY_H_
      7 #define LIB_JXL_DEC_PATCH_DICTIONARY_H_
      8 
      9 // Chooses reference patches, and avoids encoding them once per occurrence.
     10 
     11 #include <stddef.h>
     12 #include <string.h>
     13 #include <sys/types.h>
     14 
     15 #include <vector>
     16 
     17 #include "lib/jxl/base/status.h"
     18 #include "lib/jxl/dec_bit_reader.h"
     19 
     20 namespace jxl {
     21 
     22 enum class PatchBlendMode : uint8_t {
     23   // The new values are the old ones. Useful to skip some channels.
     24   kNone = 0,
     25   // The new values (in the crop) replace the old ones: sample = new
     26   kReplace = 1,
     27   // The new values (in the crop) get added to the old ones: sample = old + new
     28   kAdd = 2,
     29   // The new values (in the crop) get multiplied by the old ones:
     30   // sample = old * new
     31   // This blend mode is only supported if BlendColorSpace is kEncoded. The
     32   // range of the new value matters for multiplication purposes, and its
     33   // nominal range of 0..1 is computed the same way as this is done for the
     34   // alpha values in kBlend and kAlphaWeightedAdd.
     35   kMul = 3,
     36   // The new values (in the crop) replace the old ones if alpha>0:
     37   // For first alpha channel:
     38   // alpha = old + new * (1 - old)
     39   // For other channels if !alpha_associated:
     40   // sample = ((1 - new_alpha) * old * old_alpha + new_alpha * new) / alpha
     41   // For other channels if alpha_associated:
     42   // sample = (1 - new_alpha) * old + new
     43   // The alpha formula applies to the alpha used for the division in the other
     44   // channels formula, and applies to the alpha channel itself if its
     45   // blend_channel value matches itself.
     46   // If using kBlendAbove, new is the patch and old is the original image; if
     47   // using kBlendBelow, the meaning is inverted.
     48   kBlendAbove = 4,
     49   kBlendBelow = 5,
     50   // The new values (in the crop) are added to the old ones if alpha>0:
     51   // For first alpha channel: sample = sample = old + new * (1 - old)
     52   // For other channels: sample = old + alpha * new
     53   kAlphaWeightedAddAbove = 6,
     54   kAlphaWeightedAddBelow = 7,
     55   kNumBlendModes,
     56 };
     57 
     58 inline bool UsesAlpha(PatchBlendMode mode) {
     59   return mode == PatchBlendMode::kBlendAbove ||
     60          mode == PatchBlendMode::kBlendBelow ||
     61          mode == PatchBlendMode::kAlphaWeightedAddAbove ||
     62          mode == PatchBlendMode::kAlphaWeightedAddBelow;
     63 }
     64 inline bool UsesClamp(PatchBlendMode mode) {
     65   return UsesAlpha(mode) || mode == PatchBlendMode::kMul;
     66 }
     67 
     68 struct PatchBlending {
     69   PatchBlendMode mode;
     70   uint32_t alpha_channel;
     71   bool clamp;
     72 };
     73 
     74 // Position and size of the patch in the reference frame.
     75 struct PatchReferencePosition {
     76   size_t ref, x0, y0, xsize, ysize;
     77 };
     78 
     79 struct PatchPosition {
     80   // Position of top-left corner of the patch in the image.
     81   size_t x, y;
     82   size_t ref_pos_idx;
     83 };
     84 
     85 struct PassesSharedState;
     86 
     87 // Encoder-side helper class to encode the PatchesDictionary.
     88 class PatchDictionaryEncoder;
     89 
     90 class PatchDictionary {
     91  public:
     92   PatchDictionary() = default;
     93 
     94   void SetPassesSharedState(const PassesSharedState* shared) {
     95     shared_ = shared;
     96   }
     97 
     98   bool HasAny() const { return !positions_.empty(); }
     99 
    100   Status Decode(BitReader* br, size_t xsize, size_t ysize,
    101                 bool* uses_extra_channels);
    102 
    103   void Clear() {
    104     positions_.clear();
    105     ComputePatchTree();
    106   }
    107 
    108   // Adds patches to a segment of `xsize` pixels, starting at `inout`, assumed
    109   // to be located at position (x0, y) in the frame.
    110   Status AddOneRow(float* const* inout, size_t y, size_t x0,
    111                    size_t xsize) const;
    112 
    113   // Returns dependencies of this patch dictionary on reference frame ids as a
    114   // bit mask: bits 0-3 indicate reference frame 0-3.
    115   int GetReferences() const;
    116 
    117   std::vector<size_t> GetPatchesForRow(size_t y) const;
    118 
    119  private:
    120   friend class PatchDictionaryEncoder;
    121 
    122   const PassesSharedState* shared_;
    123   std::vector<PatchPosition> positions_;
    124   std::vector<PatchReferencePosition> ref_positions_;
    125   std::vector<PatchBlending> blendings_;
    126 
    127   // Interval tree on the y coordinates of the patches.
    128   struct PatchTreeNode {
    129     ssize_t left_child;
    130     ssize_t right_child;
    131     size_t y_center;
    132     // Range of patches in sorted_patches_y0_ and sorted_patches_y1_ that
    133     // contain the row y_center.
    134     size_t start;
    135     size_t num;
    136   };
    137   std::vector<PatchTreeNode> patch_tree_;
    138   // Number of patches for each row.
    139   std::vector<size_t> num_patches_;
    140   std::vector<std::pair<size_t, size_t>> sorted_patches_y0_;
    141   std::vector<std::pair<size_t, size_t>> sorted_patches_y1_;
    142 
    143   void ComputePatchTree();
    144 };
    145 
    146 }  // namespace jxl
    147 
    148 #endif  // LIB_JXL_DEC_PATCH_DICTIONARY_H_