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