encoding.h (5219B)
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_MODULAR_ENCODING_ENCODING_H_ 7 #define LIB_JXL_MODULAR_ENCODING_ENCODING_H_ 8 9 #include <array> 10 #include <cstddef> 11 #include <cstdint> 12 #include <vector> 13 14 #include "lib/jxl/base/compiler_specific.h" 15 #include "lib/jxl/base/status.h" 16 #include "lib/jxl/field_encodings.h" 17 #include "lib/jxl/image.h" 18 #include "lib/jxl/modular/encoding/context_predict.h" 19 #include "lib/jxl/modular/encoding/dec_ma.h" 20 #include "lib/jxl/modular/modular_image.h" 21 #include "lib/jxl/modular/options.h" 22 #include "lib/jxl/modular/transform/transform.h" 23 24 namespace jxl { 25 26 struct ANSCode; 27 class BitReader; 28 29 // Valid range of properties for using lookup tables instead of trees. 30 constexpr int32_t kPropRangeFast = 512; 31 32 struct GroupHeader : public Fields { 33 GroupHeader(); 34 35 JXL_FIELDS_NAME(GroupHeader) 36 37 Status VisitFields(Visitor *JXL_RESTRICT visitor) override { 38 JXL_QUIET_RETURN_IF_ERROR(visitor->Bool(false, &use_global_tree)); 39 JXL_QUIET_RETURN_IF_ERROR(visitor->VisitNested(&wp_header)); 40 uint32_t num_transforms = static_cast<uint32_t>(transforms.size()); 41 JXL_QUIET_RETURN_IF_ERROR(visitor->U32(Val(0), Val(1), BitsOffset(4, 2), 42 BitsOffset(8, 18), 0, 43 &num_transforms)); 44 if (visitor->IsReading()) transforms.resize(num_transforms); 45 for (size_t i = 0; i < num_transforms; i++) { 46 JXL_QUIET_RETURN_IF_ERROR(visitor->VisitNested(&transforms[i])); 47 } 48 return true; 49 } 50 51 bool use_global_tree; 52 weighted::Header wp_header; 53 54 std::vector<Transform> transforms; 55 }; 56 57 FlatTree FilterTree(const Tree &global_tree, 58 std::array<pixel_type, kNumStaticProperties> &static_props, 59 size_t *num_props, bool *use_wp, bool *wp_only, 60 bool *gradient_only); 61 62 template <typename T, bool HAS_MULTIPLIERS> 63 struct TreeLut { 64 std::array<T, 2 * kPropRangeFast> context_lookup; 65 std::array<int8_t, 2 * kPropRangeFast> offsets; 66 std::array<int8_t, HAS_MULTIPLIERS ? (2 * kPropRangeFast) : 0> multipliers; 67 }; 68 69 template <typename T, bool HAS_MULTIPLIERS> 70 bool TreeToLookupTable(const FlatTree &tree, TreeLut<T, HAS_MULTIPLIERS> &lut) { 71 struct TreeRange { 72 // Begin *excluded*, end *included*. This works best with > vs <= decision 73 // nodes. 74 int begin, end; 75 size_t pos; 76 }; 77 std::vector<TreeRange> ranges; 78 ranges.push_back(TreeRange{-kPropRangeFast - 1, kPropRangeFast - 1, 0}); 79 while (!ranges.empty()) { 80 TreeRange cur = ranges.back(); 81 ranges.pop_back(); 82 if (cur.begin < -kPropRangeFast - 1 || cur.begin >= kPropRangeFast - 1 || 83 cur.end > kPropRangeFast - 1) { 84 // Tree is outside the allowed range, exit. 85 return false; 86 } 87 auto &node = tree[cur.pos]; 88 // Leaf. 89 if (node.property0 == -1) { 90 if (node.predictor_offset < std::numeric_limits<int8_t>::min() || 91 node.predictor_offset > std::numeric_limits<int8_t>::max()) { 92 return false; 93 } 94 if (node.multiplier < std::numeric_limits<int8_t>::min() || 95 node.multiplier > std::numeric_limits<int8_t>::max()) { 96 return false; 97 } 98 if (!HAS_MULTIPLIERS && node.multiplier != 1) { 99 return false; 100 } 101 for (int i = cur.begin + 1; i < cur.end + 1; i++) { 102 lut.context_lookup[i + kPropRangeFast] = node.childID; 103 if (HAS_MULTIPLIERS) { 104 lut.multipliers[i + kPropRangeFast] = node.multiplier; 105 } 106 lut.offsets[i + kPropRangeFast] = node.predictor_offset; 107 } 108 continue; 109 } 110 // > side of top node. 111 if (node.properties[0] >= kNumStaticProperties) { 112 ranges.push_back(TreeRange({node.splitvals[0], cur.end, node.childID})); 113 ranges.push_back( 114 TreeRange({node.splitval0, node.splitvals[0], node.childID + 1})); 115 } else { 116 ranges.push_back(TreeRange({node.splitval0, cur.end, node.childID})); 117 } 118 // <= side 119 if (node.properties[1] >= kNumStaticProperties) { 120 ranges.push_back( 121 TreeRange({node.splitvals[1], node.splitval0, node.childID + 2})); 122 ranges.push_back( 123 TreeRange({cur.begin, node.splitvals[1], node.childID + 3})); 124 } else { 125 ranges.push_back( 126 TreeRange({cur.begin, node.splitval0, node.childID + 2})); 127 } 128 } 129 return true; 130 } 131 // TODO(veluca): make cleaner interfaces. 132 133 Status ValidateChannelDimensions(const Image &image, 134 const ModularOptions &options); 135 136 Status ModularGenericDecompress(BitReader *br, Image &image, 137 GroupHeader *header, size_t group_id, 138 ModularOptions *options, 139 bool undo_transforms = true, 140 const Tree *tree = nullptr, 141 const ANSCode *code = nullptr, 142 const std::vector<uint8_t> *ctx_map = nullptr, 143 bool allow_truncated_group = false); 144 } // namespace jxl 145 146 #endif // LIB_JXL_MODULAR_ENCODING_ENCODING_H_