/src/libjxl/lib/jpegli/common_internal.h
Line | Count | Source |
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_JPEGLI_COMMON_INTERNAL_H_ |
7 | | #define LIB_JPEGLI_COMMON_INTERNAL_H_ |
8 | | |
9 | | #include <cstddef> |
10 | | #include <cstdint> |
11 | | #include <cstring> |
12 | | |
13 | | // Suppress any -Wdeprecated-declarations warning that might be emitted by |
14 | | // GCC or Clang by std::stable_sort in C++17 or later mode |
15 | | #ifdef __clang__ |
16 | | #pragma clang diagnostic push |
17 | | #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
18 | | #elif defined(__GNUC__) |
19 | | #pragma GCC push_options |
20 | | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
21 | | #endif |
22 | | |
23 | | #include <algorithm> |
24 | | |
25 | | #ifdef __clang__ |
26 | | #pragma clang diagnostic pop |
27 | | #elif defined(__GNUC__) |
28 | | #pragma GCC pop_options |
29 | | #endif |
30 | | |
31 | | #include <hwy/aligned_allocator.h> |
32 | | |
33 | | #include "lib/jpegli/memory_manager.h" |
34 | | #include "lib/jpegli/simd.h" |
35 | | #include "lib/jxl/base/compiler_specific.h" // for ssize_t |
36 | | |
37 | | namespace jpegli { |
38 | | |
39 | | enum State { |
40 | | kDecNull, |
41 | | kDecStart, |
42 | | kDecInHeader, |
43 | | kDecHeaderDone, |
44 | | kDecProcessMarkers, |
45 | | kDecProcessScan, |
46 | | kEncNull, |
47 | | kEncStart, |
48 | | kEncHeader, |
49 | | kEncReadImage, |
50 | | kEncWriteCoeffs, |
51 | | }; |
52 | | |
53 | | template <typename T1, typename T2> |
54 | 17.2M | constexpr inline T1 DivCeil(T1 a, T2 b) { |
55 | 17.2M | return (a + b - 1) / b; |
56 | 17.2M | } unsigned long jpegli::DivCeil<unsigned long, unsigned long>(unsigned long, unsigned long) Line | Count | Source | 54 | 17.3k | constexpr inline T1 DivCeil(T1 a, T2 b) { | 55 | 17.3k | return (a + b - 1) / b; | 56 | 17.3k | } |
unsigned int jpegli::DivCeil<unsigned int, int>(unsigned int, int) Line | Count | Source | 54 | 43.5k | constexpr inline T1 DivCeil(T1 a, T2 b) { | 55 | 43.5k | return (a + b - 1) / b; | 56 | 43.5k | } |
unsigned long jpegli::DivCeil<unsigned long, int>(unsigned long, int) Line | Count | Source | 54 | 16.0M | constexpr inline T1 DivCeil(T1 a, T2 b) { | 55 | 16.0M | return (a + b - 1) / b; | 56 | 16.0M | } |
int jpegli::DivCeil<int, int>(int, int) Line | Count | Source | 54 | 1.10M | constexpr inline T1 DivCeil(T1 a, T2 b) { | 55 | 1.10M | return (a + b - 1) / b; | 56 | 1.10M | } |
|
57 | | |
58 | | template <typename T1, typename T2> |
59 | 20.3k | constexpr inline T1 RoundUpTo(T1 a, T2 b) { |
60 | 20.3k | return DivCeil(a, b) * b; |
61 | 20.3k | } unsigned long jpegli::RoundUpTo<unsigned long, unsigned long>(unsigned long, unsigned long) Line | Count | Source | 59 | 17.3k | constexpr inline T1 RoundUpTo(T1 a, T2 b) { | 60 | 17.3k | return DivCeil(a, b) * b; | 61 | 17.3k | } |
unsigned long jpegli::RoundUpTo<unsigned long, int>(unsigned long, int) Line | Count | Source | 59 | 2.96k | constexpr inline T1 RoundUpTo(T1 a, T2 b) { | 60 | 2.96k | return DivCeil(a, b) * b; | 61 | 2.96k | } |
|
62 | | |
63 | | constexpr size_t kDCTBlockSize = 64; |
64 | | // This is set to the same value as MAX_COMPS_IN_SCAN, because that is the |
65 | | // maximum number of channels the libjpeg-turbo decoder can decode. |
66 | | constexpr int kMaxComponents = 4; |
67 | | constexpr int kMaxQuantTables = 4; |
68 | | constexpr int kJpegPrecision = 8; |
69 | | constexpr int kMaxHuffmanTables = 4; |
70 | | constexpr size_t kJpegHuffmanMaxBitLength = 16; |
71 | | constexpr int kJpegHuffmanAlphabetSize = 256; |
72 | | constexpr int kJpegDCAlphabetSize = 12; |
73 | | constexpr int kMaxDHTMarkers = 512; |
74 | | constexpr int kMaxDimPixels = 65535; |
75 | | constexpr uint8_t kApp1 = 0xE1; |
76 | | constexpr uint8_t kApp2 = 0xE2; |
77 | | const uint8_t kIccProfileTag[12] = "ICC_PROFILE"; |
78 | | const uint8_t kExifTag[6] = "Exif\0"; |
79 | | const uint8_t kXMPTag[29] = "http://ns.adobe.com/xap/1.0/"; |
80 | | |
81 | | /* clang-format off */ |
82 | | constexpr uint32_t kJPEGNaturalOrder[80] = { |
83 | | 0, 1, 8, 16, 9, 2, 3, 10, |
84 | | 17, 24, 32, 25, 18, 11, 4, 5, |
85 | | 12, 19, 26, 33, 40, 48, 41, 34, |
86 | | 27, 20, 13, 6, 7, 14, 21, 28, |
87 | | 35, 42, 49, 56, 57, 50, 43, 36, |
88 | | 29, 22, 15, 23, 30, 37, 44, 51, |
89 | | 58, 59, 52, 45, 38, 31, 39, 46, |
90 | | 53, 60, 61, 54, 47, 55, 62, 63, |
91 | | // extra entries for safety in decoder |
92 | | 63, 63, 63, 63, 63, 63, 63, 63, |
93 | | 63, 63, 63, 63, 63, 63, 63, 63 |
94 | | }; |
95 | | |
96 | | constexpr uint32_t kJPEGZigZagOrder[64] = { |
97 | | 0, 1, 5, 6, 14, 15, 27, 28, |
98 | | 2, 4, 7, 13, 16, 26, 29, 42, |
99 | | 3, 8, 12, 17, 25, 30, 41, 43, |
100 | | 9, 11, 18, 24, 31, 40, 44, 53, |
101 | | 10, 19, 23, 32, 39, 45, 52, 54, |
102 | | 20, 22, 33, 38, 46, 51, 55, 60, |
103 | | 21, 34, 37, 47, 50, 56, 59, 61, |
104 | | 35, 36, 48, 49, 57, 58, 62, 63 |
105 | | }; |
106 | | /* clang-format on */ |
107 | | |
108 | | template <typename T> |
109 | | class RowBuffer { |
110 | | public: |
111 | | template <typename CInfoType> |
112 | 11.3k | void Allocate(CInfoType cinfo, size_t num_rows, size_t rowsize) { |
113 | 11.3k | static_assert(sizeof(T) == 4); |
114 | 11.3k | size_t vec_size = std::max(VectorSize(), sizeof(T)); |
115 | 11.3k | size_t alignment = std::max<size_t>(HWY_ALIGNMENT, vec_size); |
116 | 11.3k | size_t min_memstride = alignment + rowsize * sizeof(T) + vec_size; |
117 | 11.3k | size_t memstride = RoundUpTo(min_memstride, alignment); |
118 | 11.3k | xsize_ = rowsize; |
119 | 11.3k | ysize_ = num_rows; |
120 | 11.3k | stride_ = memstride / sizeof(T); |
121 | 11.3k | offset_ = alignment / sizeof(T); |
122 | 11.3k | data_ = ::jpegli::Allocate<T>(cinfo, ysize_ * stride_, JPOOL_IMAGE_ALIGNED); |
123 | 11.3k | } |
124 | | |
125 | 177M | T* Row(ssize_t y) const { |
126 | 177M | return &data_[((ysize_ + y) % ysize_) * stride_ + offset_]; |
127 | 177M | } |
128 | | |
129 | | size_t xsize() const { return xsize_; }; |
130 | | size_t ysize() const { return ysize_; }; |
131 | 30.0M | size_t stride() const { return stride_; } |
132 | | |
133 | | void PadRow(size_t y, size_t from, int border) { |
134 | | float* row = Row(y); |
135 | | for (int offset = -border; offset < 0; ++offset) { |
136 | | row[offset] = row[0]; |
137 | | } |
138 | | float last_val = row[from - 1]; |
139 | | for (size_t x = from; x < xsize_ + border; ++x) { |
140 | | row[x] = last_val; |
141 | | } |
142 | | } |
143 | | |
144 | | void CopyRow(ssize_t dst_row, ssize_t src_row, int border) { |
145 | | memcpy(Row(dst_row) - border, Row(src_row) - border, |
146 | | (xsize_ + 2 * border) * sizeof(T)); |
147 | | } |
148 | | |
149 | | void FillRow(ssize_t y, T val, size_t len) { |
150 | | T* row = Row(y); |
151 | | for (size_t x = 0; x < len; ++x) { |
152 | | row[x] = val; |
153 | | } |
154 | | } |
155 | | |
156 | | private: |
157 | | size_t xsize_; |
158 | | size_t ysize_; |
159 | | size_t stride_; |
160 | | size_t offset_; |
161 | | T* data_; |
162 | | }; |
163 | | |
164 | | } // namespace jpegli |
165 | | |
166 | | #endif // LIB_JPEGLI_COMMON_INTERNAL_H_ |