Coverage Report

Created: 2026-05-24 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/wbmp.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2026 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
%
6
% This program is covered by multiple licenses, which are described in
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9
%
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11
%                                                                             %
12
%                                                                             %
13
%                                                                             %
14
%                         W   W  BBBB   M   M  PPPP                           %
15
%                         W   W  B   B  MM MM  P   P                          %
16
%                         W W W  BBBB   M M M  PPPP                           %
17
%                         WW WW  B   B  M   M  P                              %
18
%                         W   W  BBBB   M   M  P                              %
19
%                                                                             %
20
%                                                                             %
21
%              Read/Write Wireless Bitmap (level 0) Image Format.             %
22
%                                                                             %
23
%                                                                             %
24
%                              Software Design                                %
25
%                                John Cristy                                  %
26
%                               January 2000                                  %
27
%                                                                             %
28
%                                                                             %
29
%                                                                             %
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31
%
32
%
33
*/
34
/*
35
  Include declarations.
36
*/
37
#include "magick/studio.h"
38
#include "magick/blob.h"
39
#include "magick/colormap.h"
40
#include "magick/magick.h"
41
#include "magick/monitor.h"
42
#include "magick/pixel_cache.h"
43
#include "magick/utility.h"
44
#include "magick/static.h"
45

46
/*
47
  Forward declarations.
48
*/
49
static unsigned int
50
  WriteWBMPImage(const ImageInfo *,Image *);
51

52
/*
53
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54
%                                                                             %
55
%                                                                             %
56
%                                                                             %
57
%   R e a d W B M P I m a g e                                                 %
58
%                                                                             %
59
%                                                                             %
60
%                                                                             %
61
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62
%
63
%  Method ReadWBMPImage reads a WBMP (level 0) image file and returns it.  It
64
%  allocates the memory necessary for the new Image structure and returns a
65
%  pointer to the new image.
66
%
67
%  ReadWBMPImage was contributed by Milan Votava <votava@mageo.cz>.
68
%
69
%  The format of the ReadWBMPImage method is:
70
%
71
%      Image *ReadWBMPImage(const ImageInfo *image_info,
72
%        ExceptionInfo *exception)
73
%
74
%  A description of each parameter follows:
75
%
76
%    o image:  Method ReadWBMPImage returns a pointer to the image after
77
%      reading.  A null image is returned if there is a memory shortage or
78
%      if the image cannot be read.
79
%
80
%    o image_info: Specifies a pointer to a ImageInfo structure.
81
%
82
%    o exception: return any errors or warnings in this structure.
83
%
84
%
85
*/
86
87
static unsigned int WBMPReadInteger(Image *image,unsigned long *value)
88
1.43k
{
89
1.43k
  int
90
1.43k
    byte;
91
92
1.43k
  *value=0;
93
1.43k
  do
94
4.41M
  {
95
4.41M
    byte=ReadBlobByte(image);
96
4.41M
    if (byte == EOF)
97
34
      return(False);
98
4.41M
    *value<<=7;
99
4.41M
    *value|=(unsigned int) (byte & 0x7f);
100
4.41M
  } while (byte & 0x80);
101
1.40k
  return(True);
102
1.43k
}
103
104
static Image *ReadWBMPImage(const ImageInfo *image_info,
105
  ExceptionInfo *exception)
106
748
{
107
748
  Image
108
748
    *image;
109
110
748
  int
111
748
    byte;
112
113
748
  long
114
748
    y;
115
116
748
  register IndexPacket
117
748
    *indexes;
118
119
748
  register long
120
748
    x;
121
122
748
  register PixelPacket
123
748
    *q;
124
125
748
  register long
126
748
    i;
127
128
748
  unsigned char
129
748
    bit;
130
131
748
  unsigned int
132
748
    status;
133
134
748
  unsigned short
135
748
    header;
136
137
  /*
138
    Open image file.
139
  */
140
748
  assert(image_info != (const ImageInfo *) NULL);
141
748
  assert(image_info->signature == MagickSignature);
142
748
  assert(exception != (ExceptionInfo *) NULL);
143
748
  assert(exception->signature == MagickSignature);
144
748
  image=AllocateImage(image_info);
145
748
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
146
748
  if (status == False)
147
748
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
148
748
  if (ReadBlob(image,2,(char *) &header) != 2)
149
745
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
150
745
  if (header != 0U)
151
725
    ThrowReaderException(CoderError,OnlyLevelZerofilesSupported,image);
152
  /*
153
    Initialize image structure.
154
  */
155
725
  if (WBMPReadInteger(image,&image->columns) == False)
156
711
    ThrowReaderException(CorruptImageError,CorruptImage,image);
157
711
  if (WBMPReadInteger(image,&image->rows) == False)
158
691
    ThrowReaderException(CorruptImageError,CorruptImage,image);
159
691
  if ((image->columns == 0) || (image->rows == 0))
160
687
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
161
687
  for (i=0; i < image->offset; i++)
162
0
    {
163
0
      if (EOF == ReadBlobByte(image))
164
0
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
165
0
                       image->filename);
166
0
    }
167
687
  if (!AllocateImageColormap(image,2))
168
687
    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
169
687
  if (image_info->ping)
170
0
    {
171
0
      CloseBlob(image);
172
0
      StopTimer(&image->timer);
173
0
      return(image);
174
0
    }
175
  /*
176
    Convert bi-level image to pixel packets.
177
  */
178
139k
  for (y=0; y < (long) image->rows; y++)
179
138k
  {
180
138k
    q=SetImagePixels(image,0,y,image->columns,1);
181
138k
    if (q == (PixelPacket *) NULL)
182
230
      break;
183
138k
    indexes=AccessMutableIndexes(image);
184
138k
    bit=0;
185
138k
    byte=0;
186
56.9M
    for (x=0; x < (long) image->columns; x++)
187
56.8M
    {
188
56.8M
      if (bit == 0)
189
7.15M
        {
190
7.15M
          byte=ReadBlobByte(image);
191
7.15M
          if (byte == EOF)
192
7.15M
            ThrowReaderException(CorruptImageError,CorruptImage,image);
193
7.15M
        }
194
56.8M
      indexes[x]=(byte & (0x01 << (7-bit))) ? 1 : 0;
195
56.8M
      bit++;
196
56.8M
      if (bit == 8)
197
7.06M
        bit=0;
198
56.8M
    }
199
138k
    if (!SyncImagePixels(image))
200
0
      break;
201
138k
    if (QuantumTick(y,image->rows))
202
17.5k
      if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText,
203
17.5k
                                  image->filename,
204
17.5k
                                  image->columns,image->rows))
205
0
        break;
206
138k
  }
207
506
  (void) SyncImage(image);
208
506
  if (EOFBlob(image))
209
0
    ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
210
506
      image->filename);
211
506
  CloseBlob(image);
212
506
  StopTimer(&image->timer);
213
506
  return(image);
214
687
}
215

216
/*
217
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218
%                                                                             %
219
%                                                                             %
220
%                                                                             %
221
%   R e g i s t e r W B M P I m a g e                                         %
222
%                                                                             %
223
%                                                                             %
224
%                                                                             %
225
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226
%
227
%  Method RegisterWBMPImage adds attributes for the WBMP image format to
228
%  the list of supported formats.  The attributes include the image format
229
%  tag, a method to read and/or write the format, whether the format
230
%  supports the saving of more than one frame to the same file or blob,
231
%  whether the format supports native in-memory I/O, and a brief
232
%  description of the format.
233
%
234
%  The format of the RegisterWBMPImage method is:
235
%
236
%      RegisterWBMPImage(void)
237
%
238
*/
239
ModuleExport void RegisterWBMPImage(void)
240
1
{
241
1
  MagickInfo
242
1
    *entry;
243
244
  /* WBMP is the most common extension */
245
1
  entry=SetMagickInfo("WBMP");
246
1
  entry->decoder=(DecoderHandler) ReadWBMPImage;
247
1
  entry->encoder=(EncoderHandler) WriteWBMPImage;
248
1
  entry->adjoin=False;
249
1
  entry->description="Wireless Bitmap (level 0) image";
250
1
  entry->module="WBMP";
251
1
  (void) RegisterMagickInfo(entry);
252
253
  /* WBM is a less common extension */
254
1
  entry=SetMagickInfo("WBM");
255
1
  entry->decoder=(DecoderHandler) ReadWBMPImage;
256
1
  entry->encoder=(EncoderHandler) WriteWBMPImage;
257
1
  entry->adjoin=False;
258
1
  entry->description="Wireless Bitmap (level 0) image";
259
1
  entry->module="WBMP";
260
1
  entry->stealth=MagickTrue; /* Don't list in '-list format' output */
261
1
  (void) RegisterMagickInfo(entry);
262
263
  /* WBP is the least common extension */
264
1
  entry=SetMagickInfo("WBP");
265
1
  entry->decoder=(DecoderHandler) ReadWBMPImage;
266
1
  entry->encoder=(EncoderHandler) WriteWBMPImage;
267
1
  entry->adjoin=False;
268
1
  entry->description="Wireless Bitmap (level 0) image";
269
1
  entry->module="WBMP";
270
1
  entry->stealth=MagickTrue; /* Don't list in '-list format' output */
271
1
  (void) RegisterMagickInfo(entry);
272
1
}
273

274
/*
275
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276
%                                                                             %
277
%                                                                             %
278
%                                                                             %
279
%   U n r e g i s t e r W B M P I m a g e                                     %
280
%                                                                             %
281
%                                                                             %
282
%                                                                             %
283
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284
%
285
%  Method UnregisterWBMPImage removes format registrations made by the
286
%  WBMP module from the list of supported formats.
287
%
288
%  The format of the UnregisterWBMPImage method is:
289
%
290
%      UnregisterWBMPImage(void)
291
%
292
*/
293
ModuleExport void UnregisterWBMPImage(void)
294
0
{
295
0
  (void) UnregisterMagickInfo("WBMP");
296
0
  (void) UnregisterMagickInfo("WBM");
297
0
  (void) UnregisterMagickInfo("WBP");
298
0
}
299

300
/*
301
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302
%                                                                             %
303
%                                                                             %
304
%                                                                             %
305
%   W r i t e W B M P I m a g e                                               %
306
%                                                                             %
307
%                                                                             %
308
%                                                                             %
309
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310
%
311
%  Method WriteWBMPImage writes an image to a file in the Wireless Bitmap
312
%  (level 0) image format.
313
%
314
%  WriteWBMPImage was contributed by Milan Votava <votava@mageo.cz>.
315
%
316
%  The format of the WriteWBMPImage method is:
317
%
318
%      unsigned int WriteWBMPImage(const ImageInfo *image_info,Image *image)
319
%
320
%  A description of each parameter follows.
321
%
322
%    o status: Method WriteWBMPImage return True if the image is written.
323
%      False is returned is there is a memory shortage or if the image file
324
%      fails to write.
325
%
326
%    o image_info: Specifies a pointer to a ImageInfo structure.
327
%
328
%    o image:  A pointer to an Image structure.
329
%
330
%
331
*/
332
333
static void WBMPWriteInteger(Image *image,const unsigned long value)
334
414
{
335
414
  int
336
414
    bits,
337
414
    flag,
338
414
    n;
339
340
414
  register long
341
414
    i;
342
343
414
  unsigned char
344
414
    buffer[5],
345
414
    octet;
346
347
414
  n=1;
348
414
  bits=28;
349
414
  flag=False;
350
2.48k
  for(i=4; i >= 0; i--)
351
2.07k
  {
352
2.07k
    octet=(unsigned char) ((value >> bits) & 0x7f);
353
2.07k
    if (!flag && octet)
354
414
      {
355
414
        flag=True;
356
414
        n=i+1;
357
414
      }
358
2.07k
    buffer[4-i]=octet | (i && (flag || octet))*(0x01 << 7);
359
2.07k
    bits-=7;
360
2.07k
  }
361
414
  (void) WriteBlob(image,n,(char *) buffer+5-n);
362
414
}
363
364
static unsigned int WriteWBMPImage(const ImageInfo *image_info,Image *image)
365
207
{
366
207
  long
367
207
    y;
368
369
207
  register const PixelPacket
370
207
    *p;
371
372
207
  register const IndexPacket
373
207
    *indexes;
374
375
207
  register long
376
207
    x;
377
378
207
  unsigned char
379
207
    bit,
380
207
    byte,
381
207
    polarity;
382
383
207
  unsigned int
384
207
    status;
385
386
  /*
387
    Open output image file.
388
  */
389
207
  assert(image_info != (const ImageInfo *) NULL);
390
207
  assert(image_info->signature == MagickSignature);
391
207
  assert(image != (Image *) NULL);
392
207
  assert(image->signature == MagickSignature);
393
207
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
394
207
  if (status == False)
395
207
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
396
207
  if (TransformColorspace(image,RGBColorspace) == MagickFail)
397
207
    ThrowWriterException(CoderError,UnableToTransformColorspace,image);
398
  /*
399
    Convert image to a bi-level image.
400
  */
401
207
  if (SetImageType(image,BilevelType) == MagickFail)
402
207
    ThrowWriterException(CoderError,UnableToSetImageType,image);
403
207
  polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2);
404
207
  if (image->colors == 2)
405
207
    polarity=PixelIntensityToQuantum(&image->colormap[0]) <
406
207
      PixelIntensityToQuantum(&image->colormap[1]);
407
207
  (void) WriteBlobMSBShort(image,0);
408
207
  WBMPWriteInteger(image,image->columns);
409
207
  WBMPWriteInteger(image,image->rows);
410
97.7k
  for (y=0; y < (long) image->rows; y++)
411
97.5k
  {
412
97.5k
    p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
413
97.5k
    if (p == (const PixelPacket *) NULL)
414
0
      break;
415
97.5k
    indexes=AccessImmutableIndexes(image);
416
97.5k
    bit=0;
417
97.5k
    byte=0;
418
29.9M
    for (x=0; x < (long) image->columns; x++)
419
29.8M
    {
420
29.8M
      if (indexes[x] == polarity)
421
8.04M
        byte|=0x1 << (7-bit);
422
29.8M
      bit++;
423
29.8M
      if (bit == 8)
424
3.70M
        {
425
3.70M
          (void) WriteBlobByte(image,byte);
426
3.70M
          bit=0;
427
3.70M
          byte=0;
428
3.70M
        }
429
29.8M
    }
430
97.5k
    if (bit != 0)
431
69.4k
      (void) WriteBlobByte(image,byte);
432
97.5k
    if (QuantumTick(y,image->rows))
433
14.1k
      if (!MagickMonitorFormatted(y,image->rows,&image->exception,
434
14.1k
                                  SaveImageText,image->filename,
435
14.1k
                                  image->columns,image->rows))
436
0
        break;
437
97.5k
  }
438
207
  status &= CloseBlob(image);
439
207
  return(status);
440
207
}