1 // Copyright (c) Team CharLS. 2 // SPDX-License-Identifier: BSD-3-Clause 3 4 #pragma once 5 6 #include "constants.h" 7 #include "util.h" 8 9 #include <cstdint> 10 11 namespace charls { 12 13 // Optimized trait classes for lossless compression of 8 bit color and 8/16 bit monochrome images. 14 // This class assumes MaximumSampleValue correspond to a whole number of bits, and no custom ResetValue is set when encoding. 15 // The point of this is to have the most optimized code for the most common and most demanding scenario. 16 template<typename SampleType, int32_t BitsPerPixel> 17 struct lossless_traits_impl 18 { 19 using sample_type = SampleType; 20 21 static constexpr int32_t maximum_sample_value{(1U << BitsPerPixel) - 1}; 22 static constexpr int32_t near_lossless{}; 23 static constexpr int32_t quantized_bits_per_pixel{BitsPerPixel}; 24 static constexpr int32_t range{compute_range_parameter(maximum_sample_value, near_lossless)}; 25 static constexpr int32_t bits_per_pixel{BitsPerPixel}; 26 static constexpr int32_t limit{compute_limit_parameter(BitsPerPixel)}; 27 static constexpr int32_t reset_threshold{default_reset_value}; 28 compute_error_valuelossless_traits_impl29 FORCE_INLINE constexpr static int32_t compute_error_value(const int32_t d) noexcept 30 { 31 return modulo_range(d); 32 } 33 is_nearlossless_traits_impl34 FORCE_INLINE constexpr static bool is_near(const int32_t lhs, const int32_t rhs) noexcept 35 { 36 return lhs == rhs; 37 } 38 39 FORCE_INLINE constexpr static int32_t modulo_rangelossless_traits_impl40 modulo_range(const int32_t error_value) noexcept 41 { 42 return (static_cast<int32_t>(static_cast<uint32_t>(error_value) << (int32_t_bit_count - bits_per_pixel))) >> 43 (int32_t_bit_count - bits_per_pixel); 44 } 45 compute_reconstructed_samplelossless_traits_impl46 FORCE_INLINE static SampleType compute_reconstructed_sample(const int32_t predicted_value, 47 const int32_t error_value) noexcept 48 { 49 return static_cast<SampleType>(maximum_sample_value & (predicted_value + error_value)); 50 } 51 correct_predictionlossless_traits_impl52 FORCE_INLINE static int32_t correct_prediction(const int32_t predicted) noexcept 53 { 54 if ((predicted & maximum_sample_value) == predicted) 55 return predicted; 56 57 return (~(predicted >> (int32_t_bit_count - 1))) & maximum_sample_value; 58 } 59 }; 60 61 62 template<typename PixelType, int32_t BitsPerPixel> 63 struct lossless_traits final : lossless_traits_impl<PixelType, BitsPerPixel> 64 { 65 using pixel_type = PixelType; 66 }; 67 68 69 template<> 70 struct lossless_traits<uint8_t, 8> final : lossless_traits_impl<uint8_t, 8> 71 { 72 using pixel_type = sample_type; 73 74 FORCE_INLINE constexpr static signed char mod_range(const int32_t error_value) noexcept 75 { 76 return static_cast<signed char>(error_value); 77 } 78 79 FORCE_INLINE constexpr static int32_t compute_error_value(const int32_t d) noexcept 80 { 81 return static_cast<signed char>(d); 82 } 83 84 FORCE_INLINE constexpr static uint8_t compute_reconstructed_sample(const int32_t predicted_value, 85 const int32_t error_value) noexcept 86 { 87 return static_cast<uint8_t>(predicted_value + error_value); 88 } 89 }; 90 91 92 template<> 93 struct lossless_traits<uint16_t, 16> final : lossless_traits_impl<uint16_t, 16> 94 { 95 using pixel_type = sample_type; 96 97 FORCE_INLINE constexpr static short mod_range(const int32_t error_value) noexcept 98 { 99 return static_cast<short>(error_value); 100 } 101 102 FORCE_INLINE constexpr static int32_t compute_error_value(const int32_t d) noexcept 103 { 104 return static_cast<short>(d); 105 } 106 107 FORCE_INLINE constexpr static sample_type compute_reconstructed_sample(const int32_t predicted_value, 108 const int32_t error_value) noexcept 109 { 110 return static_cast<sample_type>(predicted_value + error_value); 111 } 112 }; 113 114 115 template<typename PixelType, int32_t BitsPerPixel> 116 struct lossless_traits<triplet<PixelType>, BitsPerPixel> final : lossless_traits_impl<PixelType, BitsPerPixel> 117 { 118 using pixel_type = triplet<PixelType>; 119 120 FORCE_INLINE constexpr static bool is_near(const int32_t lhs, const int32_t rhs) noexcept 121 { 122 return lhs == rhs; 123 } 124 125 FORCE_INLINE static bool is_near(pixel_type lhs, pixel_type rhs) noexcept 126 { 127 return lhs == rhs; 128 } 129 130 FORCE_INLINE static PixelType compute_reconstructed_sample(const int32_t predicted_value, 131 const int32_t error_value) noexcept 132 { 133 return static_cast<PixelType>(predicted_value + error_value); 134 } 135 }; 136 137 138 template<typename PixelType, int32_t BitsPerPixel> 139 struct lossless_traits<quad<PixelType>, BitsPerPixel> final : lossless_traits_impl<PixelType, BitsPerPixel> 140 { 141 using pixel_type = quad<PixelType>; 142 143 FORCE_INLINE constexpr static bool is_near(const int32_t lhs, const int32_t rhs) noexcept 144 { 145 return lhs == rhs; 146 } 147 148 FORCE_INLINE static bool is_near(pixel_type lhs, pixel_type rhs) noexcept 149 { 150 return lhs == rhs; 151 } 152 153 FORCE_INLINE static PixelType compute_reconstructed_sample(const int32_t predicted_value, 154 const int32_t error_value) noexcept 155 { 156 return static_cast<PixelType>(predicted_value + error_value); 157 } 158 }; 159 160 } // namespace charls 161