dec_ma.cc (4956B)
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 #include "lib/jxl/modular/encoding/dec_ma.h" 7 8 #include <limits> 9 #include <vector> 10 11 #include "lib/jxl/base/printf_macros.h" 12 #include "lib/jxl/dec_ans.h" 13 #include "lib/jxl/modular/encoding/ma_common.h" 14 #include "lib/jxl/modular/modular_image.h" 15 #include "lib/jxl/pack_signed.h" 16 17 namespace jxl { 18 19 namespace { 20 21 Status ValidateTree(const Tree &tree) { 22 int num_properties = 0; 23 for (auto node : tree) { 24 if (node.property >= num_properties) { 25 num_properties = node.property + 1; 26 } 27 } 28 std::vector<int> height(tree.size()); 29 std::vector<std::pair<pixel_type, pixel_type>> property_ranges( 30 num_properties * tree.size()); 31 for (int i = 0; i < num_properties; i++) { 32 property_ranges[i].first = std::numeric_limits<pixel_type>::min(); 33 property_ranges[i].second = std::numeric_limits<pixel_type>::max(); 34 } 35 const int kHeightLimit = 2048; 36 for (size_t i = 0; i < tree.size(); i++) { 37 if (height[i] > kHeightLimit) { 38 return JXL_FAILURE("Tree too tall: %d", height[i]); 39 } 40 if (tree[i].property == -1) continue; 41 height[tree[i].lchild] = height[i] + 1; 42 height[tree[i].rchild] = height[i] + 1; 43 for (size_t p = 0; p < static_cast<size_t>(num_properties); p++) { 44 if (p == static_cast<size_t>(tree[i].property)) { 45 pixel_type l = property_ranges[i * num_properties + p].first; 46 pixel_type u = property_ranges[i * num_properties + p].second; 47 pixel_type val = tree[i].splitval; 48 if (l > val || u <= val) { 49 return JXL_FAILURE("Invalid tree"); 50 } 51 property_ranges[tree[i].lchild * num_properties + p] = 52 std::make_pair(val + 1, u); 53 property_ranges[tree[i].rchild * num_properties + p] = 54 std::make_pair(l, val); 55 } else { 56 property_ranges[tree[i].lchild * num_properties + p] = 57 property_ranges[i * num_properties + p]; 58 property_ranges[tree[i].rchild * num_properties + p] = 59 property_ranges[i * num_properties + p]; 60 } 61 } 62 } 63 return true; 64 } 65 66 Status DecodeTree(BitReader *br, ANSSymbolReader *reader, 67 const std::vector<uint8_t> &context_map, Tree *tree, 68 size_t tree_size_limit) { 69 size_t leaf_id = 0; 70 size_t to_decode = 1; 71 tree->clear(); 72 while (to_decode > 0) { 73 JXL_RETURN_IF_ERROR(br->AllReadsWithinBounds()); 74 if (tree->size() > tree_size_limit) { 75 return JXL_FAILURE("Tree is too large: %" PRIuS " nodes vs %" PRIuS 76 " max nodes", 77 tree->size(), tree_size_limit); 78 } 79 to_decode--; 80 uint32_t prop1 = reader->ReadHybridUint(kPropertyContext, br, context_map); 81 if (prop1 > 256) return JXL_FAILURE("Invalid tree property value"); 82 int property = prop1 - 1; 83 if (property == -1) { 84 size_t predictor = 85 reader->ReadHybridUint(kPredictorContext, br, context_map); 86 if (predictor >= kNumModularPredictors) { 87 return JXL_FAILURE("Invalid predictor"); 88 } 89 int64_t predictor_offset = 90 UnpackSigned(reader->ReadHybridUint(kOffsetContext, br, context_map)); 91 uint32_t mul_log = 92 reader->ReadHybridUint(kMultiplierLogContext, br, context_map); 93 if (mul_log >= 31) { 94 return JXL_FAILURE("Invalid multiplier logarithm"); 95 } 96 uint32_t mul_bits = 97 reader->ReadHybridUint(kMultiplierBitsContext, br, context_map); 98 if (mul_bits >= (1u << (31u - mul_log)) - 1u) { 99 return JXL_FAILURE("Invalid multiplier"); 100 } 101 uint32_t multiplier = (mul_bits + 1U) << mul_log; 102 tree->emplace_back(-1, 0, leaf_id++, 0, static_cast<Predictor>(predictor), 103 predictor_offset, multiplier); 104 continue; 105 } 106 int splitval = 107 UnpackSigned(reader->ReadHybridUint(kSplitValContext, br, context_map)); 108 tree->emplace_back(property, splitval, tree->size() + to_decode + 1, 109 tree->size() + to_decode + 2, Predictor::Zero, 0, 1); 110 to_decode += 2; 111 } 112 return ValidateTree(*tree); 113 } 114 } // namespace 115 116 Status DecodeTree(BitReader *br, Tree *tree, size_t tree_size_limit) { 117 std::vector<uint8_t> tree_context_map; 118 ANSCode tree_code; 119 JXL_RETURN_IF_ERROR( 120 DecodeHistograms(br, kNumTreeContexts, &tree_code, &tree_context_map)); 121 // TODO(eustas): investigate more infinite tree cases. 122 if (tree_code.degenerate_symbols[tree_context_map[kPropertyContext]] > 0) { 123 return JXL_FAILURE("Infinite tree"); 124 } 125 ANSSymbolReader reader(&tree_code, br); 126 JXL_RETURN_IF_ERROR(DecodeTree(br, &reader, tree_context_map, tree, 127 std::min(tree_size_limit, kMaxTreeSize))); 128 if (!reader.CheckANSFinalState()) { 129 return JXL_FAILURE("ANS decode final state failed"); 130 } 131 return true; 132 } 133 134 } // namespace jxl