Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
13.5M
{
38
13.5M
  bit_stream->bytes          = bytes;
39
13.5M
  bit_stream->bits_remaining = 8;
40
13.5M
}
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
1.31G
{
54
1.31G
  register unsigned int
55
1.31G
    remaining_quantum_bits,
56
1.31G
    quantum;
57
58
1.31G
  remaining_quantum_bits = requested_bits;
59
1.31G
  quantum = 0;
60
61
2.85G
  while (remaining_quantum_bits != 0)
62
1.53G
    {
63
1.53G
      register unsigned int
64
1.53G
        octet_bits;
65
66
1.53G
      octet_bits = remaining_quantum_bits;
67
1.53G
      if (octet_bits > bit_stream->bits_remaining)
68
219M
        octet_bits = bit_stream->bits_remaining;
69
70
1.53G
      remaining_quantum_bits -= octet_bits;
71
1.53G
      bit_stream->bits_remaining -= octet_bits;
72
73
1.53G
      quantum = (quantum << octet_bits) |
74
1.53G
        ((*bit_stream->bytes >> (bit_stream->bits_remaining))
75
1.53G
         & BitAndMasks[octet_bits]);
76
77
1.53G
      if (bit_stream->bits_remaining == 0)
78
565M
        {
79
565M
          bit_stream->bytes++;
80
565M
          bit_stream->bits_remaining=8;
81
565M
        }
82
1.53G
    }
83
1.31G
  return quantum;
84
1.31G
}
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
3.00M
{
96
3.00M
  bit_stream->bytes          = bytes;
97
3.00M
  bit_stream->bits_remaining = 8;
98
3.00M
}
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
702M
{
114
702M
  register unsigned int
115
702M
    remaining_quantum_bits = requested_bits;
116
117
1.44G
  while (remaining_quantum_bits != 0)
118
738M
    {
119
738M
      register unsigned int
120
738M
        octet_bits;
121
122
738M
      octet_bits = remaining_quantum_bits;
123
738M
      if (octet_bits > bit_stream->bits_remaining)
124
36.0M
        octet_bits = bit_stream->bits_remaining;
125
126
738M
      remaining_quantum_bits -= octet_bits;
127
128
738M
      if (bit_stream->bits_remaining == 8)
129
249M
        *bit_stream->bytes = 0;
130
131
738M
      bit_stream->bits_remaining -= octet_bits;
132
133
738M
      *bit_stream->bytes |=
134
738M
        (((quantum >> (remaining_quantum_bits)) &
135
738M
          BitAndMasks[octet_bits]) << (bit_stream->bits_remaining));
136
137
738M
      if (bit_stream->bits_remaining == 0)
138
249M
        {
139
249M
          bit_stream->bytes++;
140
249M
          bit_stream->bits_remaining=8;
141
249M
        }
142
738M
    }
143
702M
}
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
76.8k
{
157
76.8k
  word_stream->word            = 0;
158
76.8k
  word_stream->bits_remaining  = 0;
159
76.8k
  word_stream->read_func       = read_func;
160
76.8k
  word_stream->read_func_state = read_func_state;
161
76.8k
}
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
88.9M
{
175
88.9M
  register unsigned int
176
88.9M
    remaining_quantum_bits,
177
88.9M
    quantum;
178
179
88.9M
  remaining_quantum_bits = requested_bits;
180
88.9M
  quantum = 0;
181
182
178M
  while (remaining_quantum_bits != 0)
183
89.1M
    {
184
89.1M
      register unsigned int
185
89.1M
        word_bits;
186
187
89.1M
      if (word_stream->bits_remaining == 0)
188
2.98M
        {
189
2.98M
          word_stream->word=word_stream->read_func(word_stream->read_func_state);
190
2.98M
          word_stream->bits_remaining=32;
191
2.98M
        }
192
193
89.1M
      word_bits = remaining_quantum_bits;
194
89.1M
      if (word_bits > word_stream->bits_remaining)
195
150k
        word_bits = word_stream->bits_remaining;
196
197
89.1M
      quantum |= (((word_stream->word >> (32-word_stream->bits_remaining))
198
89.1M
                   & BitAndMasks[word_bits]) << (requested_bits-remaining_quantum_bits));
199
200
89.1M
      remaining_quantum_bits -= word_bits;
201
89.1M
      word_stream->bits_remaining -= word_bits;
202
89.1M
    }
203
88.9M
  return quantum;
204
88.9M
}
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
23.2k
{
218
23.2k
  word_stream->word             = 0U;
219
23.2k
  word_stream->bits_remaining   = 32U;
220
23.2k
  word_stream->write_func       = write_func;
221
23.2k
  word_stream->write_func_state = write_func_state;
222
23.2k
}
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
19.4M
{
242
19.4M
  register unsigned int
243
19.4M
    remaining_quantum_bits = requested_bits;
244
245
38.8M
  while (remaining_quantum_bits > 0U)
246
19.4M
    {
247
19.4M
      register unsigned int
248
19.4M
        word_bits;
249
250
19.4M
      word_bits = remaining_quantum_bits;
251
19.4M
      if (word_bits > word_stream->bits_remaining)
252
0
        word_bits = word_stream->bits_remaining;
253
254
19.4M
      word_stream->word |=
255
19.4M
        (((quantum >> (requested_bits-remaining_quantum_bits)) &
256
19.4M
          BitAndMasks[word_bits]) << (32-word_stream->bits_remaining));
257
258
19.4M
      remaining_quantum_bits -= word_bits;
259
19.4M
      word_stream->bits_remaining -= word_bits;
260
261
19.4M
      if (word_stream->bits_remaining == 0U)
262
613k
        {
263
613k
          (void) word_stream->write_func(word_stream->write_func_state,
264
613k
                                         word_stream->word);
265
613k
          word_stream->word=0U;
266
613k
          word_stream->bits_remaining=32U;
267
613k
        }
268
19.4M
    }
269
19.4M
}
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
23.2k
{
282
23.2k
  if (word_stream->bits_remaining != 32U)
283
19.6k
    MagickWordStreamLSBWrite(word_stream,word_stream->bits_remaining,0U);
284
23.2k
}