/src/graphicsmagick/magick/bit_stream.c
Line | Count | Source |
1 | | /* |
2 | | Copyright (C) 2003-2019 GraphicsMagick Group |
3 | | |
4 | | This program is covered by multiple licenses, which are described in |
5 | | Copyright.txt. You should have received a copy of Copyright.txt with this |
6 | | package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
7 | | |
8 | | Interfaces to deal with marshalling quantums to and from a bit-stream. |
9 | | Written by Bob Friesenhahn, September 2003 |
10 | | |
11 | | */ |
12 | | |
13 | | #include "magick/studio.h" |
14 | | #include "magick/bit_stream.h" |
15 | | |
16 | | |
17 | | static const unsigned int BitAndMasks[33] = |
18 | | { |
19 | | /* |
20 | | Same as (~(~0 << retrieve_bits)) |
21 | | */ |
22 | | 0x00000000U, 0x00000001U, 0x00000003U, 0x00000007U, 0x0000000fU, |
23 | | 0x0000001fU, 0x0000003fU, 0x0000007fU, 0x000000ffU, 0x000001ffU, |
24 | | 0x000003ffU, 0x000007ffU, 0x00000fffU, 0x00001fffU, 0x00003fffU, |
25 | | 0x00007fffU, 0x0000ffffU, 0x0001ffffU, 0x0003ffffU, 0x0007ffffU, |
26 | | 0x000fffffU, 0x001fffffU, 0x003fffffU, 0x007fffffU, 0x00ffffffU, |
27 | | 0x01ffffffU, 0x03ffffffU, 0x07ffffffU, 0x0fffffffU, 0x1fffffffU, |
28 | | 0x3fffffffU, 0x7fffffffU, 0xffffffffU |
29 | | }; |
30 | | |
31 | | /* |
32 | | Initialize Bit Stream for reading |
33 | | */ |
34 | | MagickExport |
35 | | void MagickBitStreamInitializeRead(BitStreamReadHandle * restrict bit_stream, |
36 | | const unsigned char *bytes) |
37 | 10.9M | { |
38 | 10.9M | bit_stream->bytes = bytes; |
39 | 10.9M | bit_stream->bits_remaining = 8; |
40 | 10.9M | } |
41 | | |
42 | | /* |
43 | | Return the requested number of bits from the current position in a |
44 | | bit stream. Stream is read in most-significant bit/byte "big endian" |
45 | | order. |
46 | | |
47 | | bit_stream - already initialized bit stream. |
48 | | requested_bits - number of bits to read |
49 | | */ |
50 | | MagickExport MAGICK_FUNC_HOT |
51 | | unsigned int MagickBitStreamMSBRead(BitStreamReadHandle * restrict bit_stream, |
52 | | const unsigned int requested_bits) |
53 | 418M | { |
54 | 418M | register unsigned int |
55 | 418M | remaining_quantum_bits, |
56 | 418M | quantum; |
57 | | |
58 | 418M | remaining_quantum_bits = requested_bits; |
59 | 418M | quantum = 0; |
60 | | |
61 | 976M | while (remaining_quantum_bits != 0) |
62 | 557M | { |
63 | 557M | register unsigned int |
64 | 557M | octet_bits; |
65 | | |
66 | 557M | octet_bits = remaining_quantum_bits; |
67 | 557M | if (octet_bits > bit_stream->bits_remaining) |
68 | 138M | octet_bits = bit_stream->bits_remaining; |
69 | | |
70 | 557M | remaining_quantum_bits -= octet_bits; |
71 | 557M | bit_stream->bits_remaining -= octet_bits; |
72 | | |
73 | 557M | quantum = (quantum << octet_bits) | |
74 | 557M | ((*bit_stream->bytes >> (bit_stream->bits_remaining)) |
75 | 557M | & BitAndMasks[octet_bits]); |
76 | | |
77 | 557M | if (bit_stream->bits_remaining == 0) |
78 | 341M | { |
79 | 341M | bit_stream->bytes++; |
80 | 341M | bit_stream->bits_remaining=8; |
81 | 341M | } |
82 | 557M | } |
83 | 418M | return quantum; |
84 | 418M | } |
85 | | |
86 | | /* |
87 | | Initialize Bit Stream for writing |
88 | | |
89 | | bit_stream - bit stream to initialize. |
90 | | bytes - byte array to write bits to |
91 | | */ |
92 | | MagickExport |
93 | | void MagickBitStreamInitializeWrite(BitStreamWriteHandle * restrict bit_stream, |
94 | | unsigned char *bytes) |
95 | 2.35M | { |
96 | 2.35M | bit_stream->bytes = bytes; |
97 | 2.35M | bit_stream->bits_remaining = 8; |
98 | 2.35M | } |
99 | | |
100 | | /* |
101 | | Write quantum using the specified number of bits at the current |
102 | | position in the bit stream. Stream is written in most-significant |
103 | | bit/byte "big endian" order. |
104 | | |
105 | | bit_stream - already initialized bit stream. |
106 | | requested_bits - number of bits to write to stream. |
107 | | quantum - value to write. |
108 | | */ |
109 | | MagickExport MAGICK_FUNC_HOT |
110 | | void MagickBitStreamMSBWrite(BitStreamWriteHandle * restrict bit_stream, |
111 | | const unsigned int requested_bits, |
112 | | const unsigned int quantum) |
113 | 289M | { |
114 | 289M | register unsigned int |
115 | 289M | remaining_quantum_bits = requested_bits; |
116 | | |
117 | 609M | while (remaining_quantum_bits != 0) |
118 | 320M | { |
119 | 320M | register unsigned int |
120 | 320M | octet_bits; |
121 | | |
122 | 320M | octet_bits = remaining_quantum_bits; |
123 | 320M | if (octet_bits > bit_stream->bits_remaining) |
124 | 31.0M | octet_bits = bit_stream->bits_remaining; |
125 | | |
126 | 320M | remaining_quantum_bits -= octet_bits; |
127 | | |
128 | 320M | if (bit_stream->bits_remaining == 8) |
129 | 177M | *bit_stream->bytes = 0; |
130 | | |
131 | 320M | bit_stream->bits_remaining -= octet_bits; |
132 | | |
133 | 320M | *bit_stream->bytes |= |
134 | 320M | (((quantum >> (remaining_quantum_bits)) & |
135 | 320M | BitAndMasks[octet_bits]) << (bit_stream->bits_remaining)); |
136 | | |
137 | 320M | if (bit_stream->bits_remaining == 0) |
138 | 177M | { |
139 | 177M | bit_stream->bytes++; |
140 | 177M | bit_stream->bits_remaining=8; |
141 | 177M | } |
142 | 320M | } |
143 | 289M | } |
144 | | |
145 | | /* |
146 | | Initialize Word Stream for reading |
147 | | |
148 | | word_stream - stream to initialize. |
149 | | read_func - function to retrieve the next word. |
150 | | read_func_state - state to pass to read_func. |
151 | | */ |
152 | | MagickExport void |
153 | | MagickWordStreamInitializeRead(WordStreamReadHandle * restrict word_stream, |
154 | | WordStreamReadFunc read_func, |
155 | | void *read_func_state) |
156 | 74.0k | { |
157 | 74.0k | word_stream->word = 0; |
158 | 74.0k | word_stream->bits_remaining = 0; |
159 | 74.0k | word_stream->read_func = read_func; |
160 | 74.0k | word_stream->read_func_state = read_func_state; |
161 | 74.0k | } |
162 | | |
163 | | /* |
164 | | Return the requested number of bits from the current position in a |
165 | | 32-bit word stream. Stream is read starting with the least significant |
166 | | bits of the word. |
167 | | |
168 | | word_stream - an initialized word reader stream. |
169 | | requested_bits - number of bits to retrieve from the stream. |
170 | | */ |
171 | | MagickExport MAGICK_FUNC_HOT |
172 | | unsigned int MagickWordStreamLSBRead(WordStreamReadHandle * restrict word_stream, |
173 | | const unsigned int requested_bits) |
174 | 65.8M | { |
175 | 65.8M | register unsigned int |
176 | 65.8M | remaining_quantum_bits, |
177 | 65.8M | quantum; |
178 | | |
179 | 65.8M | remaining_quantum_bits = requested_bits; |
180 | 65.8M | quantum = 0; |
181 | | |
182 | 131M | while (remaining_quantum_bits != 0) |
183 | 66.0M | { |
184 | 66.0M | register unsigned int |
185 | 66.0M | word_bits; |
186 | | |
187 | 66.0M | if (word_stream->bits_remaining == 0) |
188 | 2.26M | { |
189 | 2.26M | word_stream->word=word_stream->read_func(word_stream->read_func_state); |
190 | 2.26M | word_stream->bits_remaining=32; |
191 | 2.26M | } |
192 | | |
193 | 66.0M | word_bits = remaining_quantum_bits; |
194 | 66.0M | if (word_bits > word_stream->bits_remaining) |
195 | 157k | word_bits = word_stream->bits_remaining; |
196 | | |
197 | 66.0M | quantum |= (((word_stream->word >> (32-word_stream->bits_remaining)) |
198 | 66.0M | & BitAndMasks[word_bits]) << (requested_bits-remaining_quantum_bits)); |
199 | | |
200 | 66.0M | remaining_quantum_bits -= word_bits; |
201 | 66.0M | word_stream->bits_remaining -= word_bits; |
202 | 66.0M | } |
203 | 65.8M | return quantum; |
204 | 65.8M | } |
205 | | |
206 | | /* |
207 | | Initialize Word Stream for writing |
208 | | |
209 | | word_stream - stream to initialize. |
210 | | write_func_state - state to pass to write_func. |
211 | | write_func - function to retrieve the next word. |
212 | | */ |
213 | | MagickExport void |
214 | | MagickWordStreamInitializeWrite(WordStreamWriteHandle * restrict word_stream, |
215 | | WordStreamWriteFunc write_func, |
216 | | void *write_func_state) |
217 | 29.0k | { |
218 | 29.0k | word_stream->word = 0U; |
219 | 29.0k | word_stream->bits_remaining = 32U; |
220 | 29.0k | word_stream->write_func = write_func; |
221 | 29.0k | word_stream->write_func_state = write_func_state; |
222 | 29.0k | } |
223 | | |
224 | | /* |
225 | | Write quantum using the specified number of bits at the current |
226 | | position in a 32-bit word stream. Samples are output to words |
227 | | starting at the least significant bits of the word. |
228 | | |
229 | | Note that since a callback function is used to output the words, |
230 | | the remaining bits in the last word need to be flushed out by |
231 | | invoking MagickWordStreamLSBWriteFlush(). |
232 | | |
233 | | word_stream - already initialized word stream. |
234 | | requested_bits - number of bits to write to stream. |
235 | | quantum - value to write. |
236 | | */ |
237 | | MagickExport MAGICK_FUNC_HOT |
238 | | void MagickWordStreamLSBWrite(WordStreamWriteHandle * restrict word_stream, |
239 | | const unsigned int requested_bits, |
240 | | const unsigned int quantum) |
241 | 20.8M | { |
242 | 20.8M | register unsigned int |
243 | 20.8M | remaining_quantum_bits = requested_bits; |
244 | | |
245 | 41.6M | while (remaining_quantum_bits > 0U) |
246 | 20.8M | { |
247 | 20.8M | register unsigned int |
248 | 20.8M | word_bits; |
249 | | |
250 | 20.8M | word_bits = remaining_quantum_bits; |
251 | 20.8M | if (word_bits > word_stream->bits_remaining) |
252 | 0 | word_bits = word_stream->bits_remaining; |
253 | | |
254 | 20.8M | word_stream->word |= |
255 | 20.8M | (((quantum >> (requested_bits-remaining_quantum_bits)) & |
256 | 20.8M | BitAndMasks[word_bits]) << (32-word_stream->bits_remaining)); |
257 | | |
258 | 20.8M | remaining_quantum_bits -= word_bits; |
259 | 20.8M | word_stream->bits_remaining -= word_bits; |
260 | | |
261 | 20.8M | if (word_stream->bits_remaining == 0U) |
262 | 659k | { |
263 | 659k | (void) word_stream->write_func(word_stream->write_func_state, |
264 | 659k | word_stream->word); |
265 | 659k | word_stream->word=0U; |
266 | 659k | word_stream->bits_remaining=32U; |
267 | 659k | } |
268 | 20.8M | } |
269 | 20.8M | } |
270 | | |
271 | | /* |
272 | | Write the current output word, regardless of completion. Unset bits |
273 | | are set to zero. Should be used to ensure that last word in word |
274 | | stream is written to the output. May also be used to apply |
275 | | word-level padding at the end of an image row. |
276 | | |
277 | | word_stream - already initialized word stream. |
278 | | */ |
279 | | MagickExport void |
280 | | MagickWordStreamLSBWriteFlush(WordStreamWriteHandle * restrict word_stream) |
281 | 29.0k | { |
282 | 29.0k | if (word_stream->bits_remaining != 32U) |
283 | 25.8k | MagickWordStreamLSBWrite(word_stream,word_stream->bits_remaining,0U); |
284 | 29.0k | } |