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_