Grok 20.3.2
mqc_enc_inl.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19
20#define BYPASS_CT_INIT 0xFF
21
29#define mqc_byteout(mqc) \
30 { \
31 assert((mqc)->bp >= ((mqc)->start - 1)); \
32 if(*(mqc)->bp == 0xff) \
33 { \
34 (mqc)->bp++; \
35 *(mqc)->bp = (uint8_t)(((mqc)->c) >> 20); \
36 (mqc)->c &= 0xfffff; \
37 (mqc)->ct = 7; \
38 } \
39 else \
40 { \
41 if(((mqc)->c & 0x8000000) == 0) \
42 { \
43 (mqc)->bp++; \
44 *(mqc)->bp = (uint8_t)(((mqc)->c) >> 19); \
45 (mqc)->c &= 0x7ffff; \
46 (mqc)->ct = 8; \
47 } \
48 else \
49 { \
50 (*(mqc)->bp)++; \
51 if(*(mqc)->bp == 0xff) \
52 { \
53 (mqc)->c &= 0x7ffffff; \
54 (mqc)->bp++; \
55 *(mqc)->bp = (uint8_t)(((mqc)->c) >> 20); \
56 (mqc)->c &= 0xfffff; \
57 (mqc)->ct = 7; \
58 } \
59 else \
60 { \
61 (mqc)->bp++; \
62 *(mqc)->bp = (uint8_t)(((mqc)->c) >> 19); \
63 (mqc)->c &= 0x7ffff; \
64 (mqc)->ct = 8; \
65 } \
66 } \
67 } \
68 }
69
70/*
71 * @brief Renormalize mqc->a and mqc->c while compressing, so that
72 * mqc->a stays between 0x8000 and 0x10000
73 *
74 * @param mqc @ref mqcoder
75 * @param a_ value of mqc->a
76 * @param c_ value of mqc->c
77 * @param ct value of mqc->ct
78 */
79#define mqc_renorme_macro(mqc, a_, c_, ct_) \
80 { \
81 do \
82 { \
83 a_ <<= 1; \
84 c_ <<= 1; \
85 ct_--; \
86 if(ct_ == 0) \
87 { \
88 mqc->c = c_; \
89 mqc_byteout(mqc); \
90 c_ = mqc->c; \
91 ct_ = mqc->ct; \
92 } \
93 } while((a_ & 0x8000) == 0); \
94 }
95
96#define mqc_codemps_macro(mqc, curctx, a, c, ct) \
97 do \
98 { \
99 a -= (*curctx)->qeval; \
100 if((a & 0x8000) == 0) \
101 { \
102 if(a < (*curctx)->qeval) \
103 a = (*curctx)->qeval; \
104 else \
105 c += (*curctx)->qeval; \
106 *curctx = (*curctx)->nmps; \
107 mqc_renorme_macro(mqc, a, c, ct); \
108 } \
109 else \
110 { \
111 c += (*curctx)->qeval; \
112 } \
113 } while(0)
114
115#define mqc_codelps_macro(mqc, curctx, a, c, ct) \
116 do \
117 { \
118 a -= (*curctx)->qeval; \
119 if(a < (*curctx)->qeval) \
120 c += (*curctx)->qeval; \
121 else \
122 a = (*curctx)->qeval; \
123 *curctx = (*curctx)->nlps; \
124 mqc_renorme_macro(mqc, a, c, ct); \
125 } while(0)
126
127#ifdef PLUGIN_DEBUG_ENCODE
128#define mqc_encode_macro(mqc, curctx, a, c, ct, d) \
129 { \
130 (mqc)->debug_mqc.context_number = ctxno; \
131 nextCXD(&(mqc)->debug_mqc, d); \
132 if((*curctx)->mps == (d)) \
133 mqc_codemps_macro(mqc, curctx, a, c, ct) else mqc_codelps_macro(mqc, curctx, a, c, ct) \
134 }
135#else
136#define mqc_encode_macro(mqc, curctx, a, c, ct, d) \
137 { \
138 if((*curctx)->mps == (d)) \
139 mqc_codemps_macro(mqc, curctx, a, c, ct); \
140 else \
141 mqc_codelps_macro(mqc, curctx, a, c, ct); \
142 }
143#endif
144#define mqc_bypass_enc_macro(mqc, c, ct, d) \
145 { \
146 if(ct == BYPASS_CT_INIT) \
147 ct = 8; \
148 ct--; \
149 c = c + ((d) << ct); \
150 if(ct == 0) \
151 { \
152 *mqc->bp = (uint8_t)c; \
153 ct = 8; \
154 /* If the previous byte was 0xff, make sure that the next msb is 0 */ \
155 if(*mqc->bp == 0xff) \
156 ct = 7; \
157 mqc->bp++; \
158 c = 0; \
159 } \
160 }