palette.h (5511B)
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_TRANSFORM_PALETTE_H_ 7 #define LIB_JXL_MODULAR_TRANSFORM_PALETTE_H_ 8 9 #include <algorithm> 10 #include <array> 11 #include <cstddef> 12 #include <cstdint> 13 14 #include "lib/jxl/base/compiler_specific.h" 15 #include "lib/jxl/base/data_parallel.h" 16 #include "lib/jxl/base/status.h" 17 #include "lib/jxl/modular/encoding/context_predict.h" 18 #include "lib/jxl/modular/modular_image.h" 19 #include "lib/jxl/modular/options.h" 20 21 namespace jxl { 22 23 namespace palette_internal { 24 25 static constexpr int kMaxPaletteLookupTableSize = 1 << 16; 26 27 static constexpr int kRgbChannels = 3; 28 29 // 5x5x5 color cube for the larger cube. 30 static constexpr int kLargeCube = 5; 31 32 // Smaller interleaved color cube to fill the holes of the larger cube. 33 static constexpr int kSmallCube = 4; 34 static constexpr int kSmallCubeBits = 2; 35 // kSmallCube ** 3 36 static constexpr int kLargeCubeOffset = kSmallCube * kSmallCube * kSmallCube; 37 static constexpr int kImplicitPaletteSize = 38 kLargeCubeOffset + kLargeCube * kLargeCube * kLargeCube; 39 40 template <int denom> 41 static inline pixel_type Scale(uint64_t value, uint64_t bit_depth) { 42 // return (value * ((static_cast<pixel_type_w>(1) << bit_depth) - 1)) / denom; 43 // We only call this function with kSmallCube or kLargeCube - 1 as denom, 44 // allowing us to avoid a division here. 45 static_assert(denom == 4); 46 return (value * ((static_cast<uint64_t>(1) << bit_depth) - 1)) >> 2; 47 } 48 49 // The purpose of this function is solely to extend the interpretation of 50 // palette indices to implicit values. If index < nb_deltas, indicating that the 51 // result is a delta palette entry, it is the responsibility of the caller to 52 // treat it as such. 53 static JXL_MAYBE_UNUSED pixel_type 54 GetPaletteValue(const pixel_type *const palette, int index, const size_t c, 55 const int palette_size, const int onerow, const int bit_depth) { 56 if (index < 0) { 57 static constexpr std::array<std::array<pixel_type, 3>, 72> kDeltaPalette = { 58 { 59 {{0, 0, 0}}, {{4, 4, 4}}, {{11, 0, 0}}, 60 {{0, 0, -13}}, {{0, -12, 0}}, {{-10, -10, -10}}, 61 {{-18, -18, -18}}, {{-27, -27, -27}}, {{-18, -18, 0}}, 62 {{0, 0, -32}}, {{-32, 0, 0}}, {{-37, -37, -37}}, 63 {{0, -32, -32}}, {{24, 24, 45}}, {{50, 50, 50}}, 64 {{-45, -24, -24}}, {{-24, -45, -45}}, {{0, -24, -24}}, 65 {{-34, -34, 0}}, {{-24, 0, -24}}, {{-45, -45, -24}}, 66 {{64, 64, 64}}, {{-32, 0, -32}}, {{0, -32, 0}}, 67 {{-32, 0, 32}}, {{-24, -45, -24}}, {{45, 24, 45}}, 68 {{24, -24, -45}}, {{-45, -24, 24}}, {{80, 80, 80}}, 69 {{64, 0, 0}}, {{0, 0, -64}}, {{0, -64, -64}}, 70 {{-24, -24, 45}}, {{96, 96, 96}}, {{64, 64, 0}}, 71 {{45, -24, -24}}, {{34, -34, 0}}, {{112, 112, 112}}, 72 {{24, -45, -45}}, {{45, 45, -24}}, {{0, -32, 32}}, 73 {{24, -24, 45}}, {{0, 96, 96}}, {{45, -24, 24}}, 74 {{24, -45, -24}}, {{-24, -45, 24}}, {{0, -64, 0}}, 75 {{96, 0, 0}}, {{128, 128, 128}}, {{64, 0, 64}}, 76 {{144, 144, 144}}, {{96, 96, 0}}, {{-36, -36, 36}}, 77 {{45, -24, -45}}, {{45, -45, -24}}, {{0, 0, -96}}, 78 {{0, 128, 128}}, {{0, 96, 0}}, {{45, 24, -45}}, 79 {{-128, 0, 0}}, {{24, -45, 24}}, {{-45, 24, -45}}, 80 {{64, 0, -64}}, {{64, -64, -64}}, {{96, 0, 96}}, 81 {{45, -45, 24}}, {{24, 45, -45}}, {{64, 64, -64}}, 82 {{128, 128, 0}}, {{0, 0, -128}}, {{-24, 45, -45}}, 83 }}; 84 if (c >= kRgbChannels) { 85 return 0; 86 } 87 // Do not open the brackets, otherwise INT32_MIN negation could overflow. 88 index = -(index + 1); 89 index %= 1 + 2 * (kDeltaPalette.size() - 1); 90 static constexpr int kMultiplier[] = {-1, 1}; 91 pixel_type result = 92 kDeltaPalette[((index + 1) >> 1)][c] * kMultiplier[index & 1]; 93 if (bit_depth > 8) { 94 result *= static_cast<pixel_type>(1) << (bit_depth - 8); 95 } 96 return result; 97 } else if (palette_size <= index && index < palette_size + kLargeCubeOffset) { 98 if (c >= kRgbChannels) return 0; 99 index -= palette_size; 100 index >>= c * kSmallCubeBits; 101 return Scale<kSmallCube>(index % kSmallCube, bit_depth) + 102 (1 << (std::max(0, bit_depth - 3))); 103 } else if (palette_size + kLargeCubeOffset <= index) { 104 if (c >= kRgbChannels) return 0; 105 index -= palette_size + kLargeCubeOffset; 106 // TODO(eustas): should we take care of ambiguity created by 107 // index >= kLargeCube ** 3 ? 108 switch (c) { 109 case 0: 110 default: 111 break; 112 case 1: 113 index /= kLargeCube; 114 break; 115 case 2: 116 index /= kLargeCube * kLargeCube; 117 break; 118 } 119 return Scale<kLargeCube - 1>(index % kLargeCube, bit_depth); 120 } 121 return palette[c * onerow + static_cast<size_t>(index)]; 122 } 123 124 } // namespace palette_internal 125 126 Status InvPalette(Image &input, uint32_t begin_c, uint32_t nb_colors, 127 uint32_t nb_deltas, Predictor predictor, 128 const weighted::Header &wp_header, ThreadPool *pool); 129 130 Status MetaPalette(Image &input, uint32_t begin_c, uint32_t end_c, 131 uint32_t nb_colors, uint32_t nb_deltas, bool lossy); 132 133 } // namespace jxl 134 135 #endif // LIB_JXL_MODULAR_TRANSFORM_PALETTE_H_