Coverage Report

Created: 2026-01-20 07:37

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
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
}