Coverage Report

Created: 2025-11-16 07:22

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-2020 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

45
/*
46
  Forward declarations.
47
*/
48
static unsigned int
49
  WriteWBMPImage(const ImageInfo *,Image *);
50

51
/*
52
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53
%                                                                             %
54
%                                                                             %
55
%                                                                             %
56
%   R e a d W B M P I m a g e                                                 %
57
%                                                                             %
58
%                                                                             %
59
%                                                                             %
60
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61
%
62
%  Method ReadWBMPImage reads a WBMP (level 0) image file and returns it.  It
63
%  allocates the memory necessary for the new Image structure and returns a
64
%  pointer to the new image.
65
%
66
%  ReadWBMPImage was contributed by Milan Votava <votava@mageo.cz>.
67
%
68
%  The format of the ReadWBMPImage method is:
69
%
70
%      Image *ReadWBMPImage(const ImageInfo *image_info,
71
%        ExceptionInfo *exception)
72
%
73
%  A description of each parameter follows:
74
%
75
%    o image:  Method ReadWBMPImage returns a pointer to the image after
76
%      reading.  A null image is returned if there is a memory shortage or
77
%      if the image cannot be read.
78
%
79
%    o image_info: Specifies a pointer to a ImageInfo structure.
80
%
81
%    o exception: return any errors or warnings in this structure.
82
%
83
%
84
*/
85
86
static unsigned int WBMPReadInteger(Image *image,unsigned long *value)
87
1.30k
{
88
1.30k
  int
89
1.30k
    byte;
90
91
1.30k
  *value=0;
92
1.30k
  do
93
4.74M
  {
94
4.74M
    byte=ReadBlobByte(image);
95
4.74M
    if (byte == EOF)
96
32
      return(False);
97
4.74M
    *value<<=7;
98
4.74M
    *value|=(unsigned int) (byte & 0x7f);
99
4.74M
  } while (byte & 0x80);
100
1.27k
  return(True);
101
1.30k
}
102
103
static Image *ReadWBMPImage(const ImageInfo *image_info,
104
  ExceptionInfo *exception)
105
681
{
106
681
  Image
107
681
    *image;
108
109
681
  int
110
681
    byte;
111
112
681
  long
113
681
    y;
114
115
681
  register IndexPacket
116
681
    *indexes;
117
118
681
  register long
119
681
    x;
120
121
681
  register PixelPacket
122
681
    *q;
123
124
681
  register long
125
681
    i;
126
127
681
  unsigned char
128
681
    bit;
129
130
681
  unsigned int
131
681
    status;
132
133
681
  unsigned short
134
681
    header;
135
136
  /*
137
    Open image file.
138
  */
139
681
  assert(image_info != (const ImageInfo *) NULL);
140
681
  assert(image_info->signature == MagickSignature);
141
681
  assert(exception != (ExceptionInfo *) NULL);
142
681
  assert(exception->signature == MagickSignature);
143
681
  image=AllocateImage(image_info);
144
681
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
145
681
  if (status == False)
146
681
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
147
681
  if (ReadBlob(image,2,(char *) &header) != 2)
148
679
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
149
679
  if (header != 0U)
150
660
    ThrowReaderException(CoderError,OnlyLevelZerofilesSupported,image);
151
  /*
152
    Initialize image structure.
153
  */
154
660
  if (WBMPReadInteger(image,&image->columns) == False)
155
649
    ThrowReaderException(CorruptImageError,CorruptImage,image);
156
649
  if (WBMPReadInteger(image,&image->rows) == False)
157
628
    ThrowReaderException(CorruptImageError,CorruptImage,image);
158
628
  if ((image->columns == 0) || (image->rows == 0))
159
624
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
160
624
  for (i=0; i < image->offset; i++)
161
0
    {
162
0
      if (EOF == ReadBlobByte(image))
163
0
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
164
0
                       image->filename);
165
0
    }
166
624
  if (!AllocateImageColormap(image,2))
167
624
    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
168
624
  if (image_info->ping)
169
0
    {
170
0
      CloseBlob(image);
171
0
      StopTimer(&image->timer);
172
0
      return(image);
173
0
    }
174
  /*
175
    Convert bi-level image to pixel packets.
176
  */
177
121k
  for (y=0; y < (long) image->rows; y++)
178
120k
  {
179
120k
    q=SetImagePixels(image,0,y,image->columns,1);
180
120k
    if (q == (PixelPacket *) NULL)
181
222
      break;
182
120k
    indexes=AccessMutableIndexes(image);
183
120k
    bit=0;
184
120k
    byte=0;
185
43.5M
    for (x=0; x < (long) image->columns; x++)
186
43.3M
    {
187
43.3M
      if (bit == 0)
188
5.46M
        {
189
5.46M
          byte=ReadBlobByte(image);
190
5.46M
          if (byte == EOF)
191
5.46M
            ThrowReaderException(CorruptImageError,CorruptImage,image);
192
5.46M
        }
193
43.3M
      indexes[x]=(byte & (0x01 << (7-bit))) ? 1 : 0;
194
43.3M
      bit++;
195
43.3M
      if (bit == 8)
196
5.39M
        bit=0;
197
43.3M
    }
198
120k
    if (!SyncImagePixels(image))
199
0
      break;
200
120k
    if (QuantumTick(y,image->rows))
201
16.7k
      if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText,
202
16.7k
                                  image->filename,
203
16.7k
                                  image->columns,image->rows))
204
0
        break;
205
120k
  }
206
488
  (void) SyncImage(image);
207
488
  if (EOFBlob(image))
208
0
    ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
209
488
      image->filename);
210
488
  CloseBlob(image);
211
488
  StopTimer(&image->timer);
212
488
  return(image);
213
624
}
214

215
/*
216
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217
%                                                                             %
218
%                                                                             %
219
%                                                                             %
220
%   R e g i s t e r W B M P I m a g e                                         %
221
%                                                                             %
222
%                                                                             %
223
%                                                                             %
224
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225
%
226
%  Method RegisterWBMPImage adds attributes for the WBMP image format to
227
%  the list of supported formats.  The attributes include the image format
228
%  tag, a method to read and/or write the format, whether the format
229
%  supports the saving of more than one frame to the same file or blob,
230
%  whether the format supports native in-memory I/O, and a brief
231
%  description of the format.
232
%
233
%  The format of the RegisterWBMPImage method is:
234
%
235
%      RegisterWBMPImage(void)
236
%
237
*/
238
ModuleExport void RegisterWBMPImage(void)
239
1
{
240
1
  MagickInfo
241
1
    *entry;
242
243
1
  entry=SetMagickInfo("WBMP");
244
1
  entry->decoder=(DecoderHandler) ReadWBMPImage;
245
1
  entry->encoder=(EncoderHandler) WriteWBMPImage;
246
1
  entry->adjoin=False;
247
1
  entry->description="Wireless Bitmap (level 0) image";
248
1
  entry->module="WBMP";
249
1
  (void) RegisterMagickInfo(entry);
250
1
}
251

252
/*
253
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254
%                                                                             %
255
%                                                                             %
256
%                                                                             %
257
%   U n r e g i s t e r W B M P I m a g e                                     %
258
%                                                                             %
259
%                                                                             %
260
%                                                                             %
261
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262
%
263
%  Method UnregisterWBMPImage removes format registrations made by the
264
%  WBMP module from the list of supported formats.
265
%
266
%  The format of the UnregisterWBMPImage method is:
267
%
268
%      UnregisterWBMPImage(void)
269
%
270
*/
271
ModuleExport void UnregisterWBMPImage(void)
272
0
{
273
0
  (void) UnregisterMagickInfo("WBMP");
274
0
}
275

276
/*
277
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278
%                                                                             %
279
%                                                                             %
280
%                                                                             %
281
%   W r i t e W B M P I m a g e                                               %
282
%                                                                             %
283
%                                                                             %
284
%                                                                             %
285
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286
%
287
%  Method WriteWBMPImage writes an image to a file in the Wireless Bitmap
288
%  (level 0) image format.
289
%
290
%  WriteWBMPImage was contributed by Milan Votava <votava@mageo.cz>.
291
%
292
%  The format of the WriteWBMPImage method is:
293
%
294
%      unsigned int WriteWBMPImage(const ImageInfo *image_info,Image *image)
295
%
296
%  A description of each parameter follows.
297
%
298
%    o status: Method WriteWBMPImage return True if the image is written.
299
%      False is returned is there is a memory shortage or if the image file
300
%      fails to write.
301
%
302
%    o image_info: Specifies a pointer to a ImageInfo structure.
303
%
304
%    o image:  A pointer to an Image structure.
305
%
306
%
307
*/
308
309
static void WBMPWriteInteger(Image *image,const unsigned long value)
310
398
{
311
398
  int
312
398
    bits,
313
398
    flag,
314
398
    n;
315
316
398
  register long
317
398
    i;
318
319
398
  unsigned char
320
398
    buffer[5],
321
398
    octet;
322
323
398
  n=1;
324
398
  bits=28;
325
398
  flag=False;
326
2.38k
  for(i=4; i >= 0; i--)
327
1.99k
  {
328
1.99k
    octet=(unsigned char) ((value >> bits) & 0x7f);
329
1.99k
    if (!flag && octet)
330
398
      {
331
398
        flag=True;
332
398
        n=i+1;
333
398
      }
334
1.99k
    buffer[4-i]=octet | (i && (flag || octet))*(0x01 << 7);
335
1.99k
    bits-=7;
336
1.99k
  }
337
398
  (void) WriteBlob(image,n,(char *) buffer+5-n);
338
398
}
339
340
static unsigned int WriteWBMPImage(const ImageInfo *image_info,Image *image)
341
199
{
342
199
  long
343
199
    y;
344
345
199
  register const PixelPacket
346
199
    *p;
347
348
199
  register const IndexPacket
349
199
    *indexes;
350
351
199
  register long
352
199
    x;
353
354
199
  unsigned char
355
199
    bit,
356
199
    byte,
357
199
    polarity;
358
359
199
  unsigned int
360
199
    status;
361
362
  /*
363
    Open output image file.
364
  */
365
199
  assert(image_info != (const ImageInfo *) NULL);
366
199
  assert(image_info->signature == MagickSignature);
367
199
  assert(image != (Image *) NULL);
368
199
  assert(image->signature == MagickSignature);
369
199
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
370
199
  if (status == False)
371
199
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
372
199
  (void) TransformColorspace(image,RGBColorspace);
373
  /*
374
    Convert image to a bi-level image.
375
  */
376
199
  (void) SetImageType(image,BilevelType);
377
199
  polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2);
378
199
  if (image->colors == 2)
379
199
    polarity=PixelIntensityToQuantum(&image->colormap[0]) <
380
199
      PixelIntensityToQuantum(&image->colormap[1]);
381
199
  (void) WriteBlobMSBShort(image,0);
382
199
  WBMPWriteInteger(image,image->columns);
383
199
  WBMPWriteInteger(image,image->rows);
384
97.7k
  for (y=0; y < (long) image->rows; y++)
385
97.5k
  {
386
97.5k
    p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
387
97.5k
    if (p == (const PixelPacket *) NULL)
388
0
      break;
389
97.5k
    indexes=AccessImmutableIndexes(image);
390
97.5k
    bit=0;
391
97.5k
    byte=0;
392
28.7M
    for (x=0; x < (long) image->columns; x++)
393
28.6M
    {
394
28.6M
      if (indexes[x] == polarity)
395
5.63M
        byte|=0x1 << (7-bit);
396
28.6M
      bit++;
397
28.6M
      if (bit == 8)
398
3.55M
        {
399
3.55M
          (void) WriteBlobByte(image,byte);
400
3.55M
          bit=0;
401
3.55M
          byte=0;
402
3.55M
        }
403
28.6M
    }
404
97.5k
    if (bit != 0)
405
61.9k
      (void) WriteBlobByte(image,byte);
406
97.5k
    if (QuantumTick(y,image->rows))
407
14.0k
      if (!MagickMonitorFormatted(y,image->rows,&image->exception,
408
14.0k
                                  SaveImageText,image->filename,
409
14.0k
                                  image->columns,image->rows))
410
0
        break;
411
97.5k
  }
412
199
  status &= CloseBlob(image);
413
199
  return(status);
414
199
}