/src/brunsli/c/common/quant_matrix.cc
Line | Count | Source |
1 | | // Copyright (c) Google LLC 2019 |
2 | | // |
3 | | // Use of this source code is governed by an MIT-style |
4 | | // license that can be found in the LICENSE file or at |
5 | | // https://opensource.org/licenses/MIT. |
6 | | |
7 | | #include "./quant_matrix.h" |
8 | | |
9 | | #include "./constants.h" |
10 | | #include "./platform.h" |
11 | | #include <brunsli/types.h> |
12 | | |
13 | | namespace brunsli { |
14 | | |
15 | | // TODO(eustas): consider high-precision (16-bit) tables in Brunsli v3. |
16 | | void FillQuantMatrix(bool is_chroma, uint32_t q, |
17 | 859 | uint8_t dst[kDCTBlockSize]) { |
18 | 859 | BRUNSLI_DCHECK(q >= 0 && q < kQFactorLimit); |
19 | 859 | const uint8_t* const in = kDefaultQuantMatrix[is_chroma]; |
20 | 55.8k | for (int i = 0; i < kDCTBlockSize; ++i) { |
21 | 54.9k | const uint32_t v = (in[i] * q + 32) >> 6; |
22 | | // clamp to prevent illegal quantizer values |
23 | 54.9k | dst[i] = (v < 1) ? 1 : (v > 255) ? 255u : v; |
24 | 54.9k | } |
25 | 859 | } |
26 | | |
27 | | // TODO(eustas): consider high-precision (16-bit) tables in Brunsli v3. |
28 | | uint32_t FindBestMatrix(const int* src, bool is_chroma, |
29 | 0 | uint8_t dst[kDCTBlockSize]) { |
30 | 0 | uint32_t best_q = 0; |
31 | 0 | const size_t kMaxDiffCost = 33; |
32 | 0 | const size_t kWorstLen = (kDCTBlockSize + 1) * (kMaxDiffCost + 1); |
33 | 0 | size_t best_len = kWorstLen; |
34 | 0 | for (uint32_t q = 0; q < kQFactorLimit; ++q) { |
35 | 0 | FillQuantMatrix(is_chroma, q, dst); |
36 | | // Copycat encoder behavior. |
37 | 0 | int last_diff = 0; // difference predictor |
38 | 0 | size_t len = 0; |
39 | 0 | for (int k = 0; k < kDCTBlockSize; ++k) { |
40 | 0 | const int j = kJPEGNaturalOrder[k]; |
41 | 0 | const int new_diff = src[j] - dst[j]; |
42 | 0 | int diff = new_diff - last_diff; |
43 | 0 | last_diff = new_diff; |
44 | 0 | if (diff != 0) { |
45 | 0 | len += 1; |
46 | 0 | if (diff < 0) diff = -diff; |
47 | 0 | diff -= 1; |
48 | 0 | if (diff == 0) { |
49 | 0 | len++; |
50 | 0 | } else if (diff > 65535) { |
51 | 0 | len = kWorstLen; |
52 | 0 | break; |
53 | 0 | } else { |
54 | 0 | uint32_t diff_len = Log2FloorNonZero(diff) + 1; |
55 | 0 | if (diff_len == 16) diff_len--; |
56 | 0 | len += 2 * diff_len + 1; |
57 | 0 | } |
58 | 0 | } |
59 | 0 | } |
60 | 0 | if (len < best_len) { |
61 | 0 | best_len = len; |
62 | 0 | best_q = q; |
63 | 0 | } |
64 | 0 | } |
65 | 0 | FillQuantMatrix(is_chroma, best_q, dst); |
66 | 0 | return best_q; |
67 | 0 | } |
68 | | |
69 | | } // namespace brunsli |