1 // Copyright 2016 The Draco Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 #ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_WRAP_TRANSFORM_BASE_H_ 16 #define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_WRAP_TRANSFORM_BASE_H_ 17 18 #include <limits> 19 #include <vector> 20 21 #include "draco/compression/config/compression_shared.h" 22 #include "draco/core/macros.h" 23 24 namespace draco { 25 26 // PredictionSchemeWrapTransform uses the min and max bounds of the original 27 // data to wrap stored correction values around these bounds centered at 0, 28 // i.e., when the range of the original values O is between <MIN, MAX> and 29 // N = MAX-MIN, we can then store any correction X = O - P, as: 30 // X + N, if X < -N / 2 31 // X - N, if X > N / 2 32 // X otherwise 33 // To unwrap this value, the decoder then simply checks whether the final 34 // corrected value F = P + X is out of the bounds of the input values. 35 // All out of bounds values are unwrapped using 36 // F + N, if F < MIN 37 // F - N, if F > MAX 38 // This wrapping can reduce the number of unique values, which translates to a 39 // better entropy of the stored values and better compression rates. 40 template <typename DataTypeT> 41 class PredictionSchemeWrapTransformBase { 42 public: PredictionSchemeWrapTransformBase()43 PredictionSchemeWrapTransformBase() 44 : num_components_(0), 45 min_value_(0), 46 max_value_(0), 47 max_dif_(0), 48 max_correction_(0), 49 min_correction_(0) {} 50 GetType()51 static constexpr PredictionSchemeTransformType GetType() { 52 return PREDICTION_TRANSFORM_WRAP; 53 } 54 Init(int num_components)55 void Init(int num_components) { 56 num_components_ = num_components; 57 clamped_value_.resize(num_components); 58 } 59 AreCorrectionsPositive()60 bool AreCorrectionsPositive() const { return false; } 61 ClampPredictedValue(const DataTypeT * predicted_val)62 inline const DataTypeT *ClampPredictedValue( 63 const DataTypeT *predicted_val) const { 64 for (int i = 0; i < this->num_components(); ++i) { 65 if (predicted_val[i] > max_value_) { 66 clamped_value_[i] = max_value_; 67 } else if (predicted_val[i] < min_value_) { 68 clamped_value_[i] = min_value_; 69 } else { 70 clamped_value_[i] = predicted_val[i]; 71 } 72 } 73 return &clamped_value_[0]; 74 } 75 76 // TODO(b/199760123): Consider refactoring to avoid this dummy. quantization_bits()77 int quantization_bits() const { 78 DRACO_DCHECK(false); 79 return -1; 80 } 81 82 protected: InitCorrectionBounds()83 bool InitCorrectionBounds() { 84 const int64_t dif = 85 static_cast<int64_t>(max_value_) - static_cast<int64_t>(min_value_); 86 if (dif < 0 || dif >= std::numeric_limits<DataTypeT>::max()) { 87 return false; 88 } 89 max_dif_ = 1 + static_cast<DataTypeT>(dif); 90 max_correction_ = max_dif_ / 2; 91 min_correction_ = -max_correction_; 92 if ((max_dif_ & 1) == 0) { 93 max_correction_ -= 1; 94 } 95 return true; 96 } 97 num_components()98 inline int num_components() const { return num_components_; } min_value()99 inline DataTypeT min_value() const { return min_value_; } set_min_value(const DataTypeT & v)100 inline void set_min_value(const DataTypeT &v) { min_value_ = v; } max_value()101 inline DataTypeT max_value() const { return max_value_; } set_max_value(const DataTypeT & v)102 inline void set_max_value(const DataTypeT &v) { max_value_ = v; } max_dif()103 inline DataTypeT max_dif() const { return max_dif_; } min_correction()104 inline DataTypeT min_correction() const { return min_correction_; } max_correction()105 inline DataTypeT max_correction() const { return max_correction_; } 106 107 private: 108 int num_components_; 109 DataTypeT min_value_; 110 DataTypeT max_value_; 111 DataTypeT max_dif_; 112 DataTypeT max_correction_; 113 DataTypeT min_correction_; 114 // This is in fact just a tmp variable to avoid reallocation. 115 mutable std::vector<DataTypeT> clamped_value_; 116 }; 117 118 } // namespace draco 119 120 #endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_WRAP_TRANSFORM_BASE_H_ 121