Coverage Report

Created: 2025-06-16 07:00

/src/imagemagick/coders/xbm.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                            X   X  BBBB   M   M                              %
7
%                             X X   B   B  MM MM                              %
8
%                              X    BBBB   M M M                              %
9
%                             X X   B   B  M   M                              %
10
%                            X   X  BBBB   M   M                              %
11
%                                                                             %
12
%                                                                             %
13
%                  Read/Write X Windows System Bitmap Format                  %
14
%                                                                             %
15
%                              Software Design                                %
16
%                                   Cristy                                    %
17
%                                 July 1992                                   %
18
%                                                                             %
19
%                                                                             %
20
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
21
%  dedicated to making software imaging solutions freely available.           %
22
%                                                                             %
23
%  You may not use this file except in compliance with the License.  You may  %
24
%  obtain a copy of the License at                                            %
25
%                                                                             %
26
%    https://imagemagick.org/script/license.php                               %
27
%                                                                             %
28
%  Unless required by applicable law or agreed to in writing, software        %
29
%  distributed under the License is distributed on an "AS IS" BASIS,          %
30
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31
%  See the License for the specific language governing permissions and        %
32
%  limitations under the License.                                             %
33
%                                                                             %
34
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
%
36
%
37
*/
38

39
/*
40
  Include declarations.
41
*/
42
#include "MagickCore/studio.h"
43
#include "MagickCore/attribute.h"
44
#include "MagickCore/blob.h"
45
#include "MagickCore/blob-private.h"
46
#include "MagickCore/cache.h"
47
#include "MagickCore/color-private.h"
48
#include "MagickCore/colormap.h"
49
#include "MagickCore/colorspace.h"
50
#include "MagickCore/colorspace-private.h"
51
#include "MagickCore/exception.h"
52
#include "MagickCore/exception-private.h"
53
#include "MagickCore/image.h"
54
#include "MagickCore/image-private.h"
55
#include "MagickCore/list.h"
56
#include "MagickCore/magick.h"
57
#include "MagickCore/memory_.h"
58
#include "MagickCore/monitor.h"
59
#include "MagickCore/monitor-private.h"
60
#include "MagickCore/pixel-accessor.h"
61
#include "MagickCore/quantum-private.h"
62
#include "MagickCore/static.h"
63
#include "MagickCore/string_.h"
64
#include "MagickCore/string-private.h"
65
#include "MagickCore/module.h"
66
#include "MagickCore/utility.h"
67

68
/*
69
  Forward declarations.
70
*/
71
static MagickBooleanType
72
  WriteXBMImage(const ImageInfo *,Image *,ExceptionInfo *);
73

74
/*
75
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76
%                                                                             %
77
%                                                                             %
78
%                                                                             %
79
%   I s X B M                                                                 %
80
%                                                                             %
81
%                                                                             %
82
%                                                                             %
83
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84
%
85
%  IsXBM() returns MagickTrue if the image format type, identified by the
86
%  magick string, is XBM.
87
%
88
%  The format of the IsXBM method is:
89
%
90
%      MagickBooleanType IsXBM(const unsigned char *magick,const size_t length)
91
%
92
%  A description of each parameter follows:
93
%
94
%    o magick: compare image format pattern against these bytes.
95
%
96
%    o length: Specifies the length of the magick string.
97
%
98
*/
99
static MagickBooleanType IsXBM(const unsigned char *magick,const size_t length)
100
0
{
101
0
  if (length < 7)
102
0
    return(MagickFalse);
103
0
  if (memcmp(magick,"#define",7) == 0)
104
0
    return(MagickTrue);
105
0
  return(MagickFalse);
106
0
}
107

108
/*
109
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110
%                                                                             %
111
%                                                                             %
112
%                                                                             %
113
%   R e a d X B M I m a g e                                                   %
114
%                                                                             %
115
%                                                                             %
116
%                                                                             %
117
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118
%
119
%  ReadXBMImage() reads an X11 bitmap image file and returns it.  It
120
%  allocates the memory necessary for the new Image structure and returns a
121
%  pointer to the new image.
122
%
123
%  The format of the ReadXBMImage method is:
124
%
125
%      Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception)
126
%
127
%  A description of each parameter follows:
128
%
129
%    o image_info: the image info.
130
%
131
%    o exception: return any errors or warnings in this structure.
132
%
133
*/
134
135
static int XBMInteger(Image *image,short int *hex_digits)
136
52.7k
{
137
52.7k
  int
138
52.7k
    c;
139
140
52.7k
  unsigned int
141
52.7k
    value;
142
143
  /*
144
    Skip any leading whitespace.
145
  */
146
52.7k
  do
147
54.3k
  {
148
54.3k
    c=ReadBlobByte(image);
149
54.3k
    if (c == EOF)
150
257
      return(-1);
151
54.3k
  } while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'));
152
  /*
153
    Evaluate number.
154
  */
155
52.4k
  value=0;
156
52.4k
  do
157
57.5k
  {
158
57.5k
    if (value <= (unsigned int) (INT_MAX/16))
159
57.0k
      {
160
57.0k
        value*=16;
161
57.0k
        c&=0xff;
162
57.0k
        if (value <= (unsigned int) ((INT_MAX-1)-hex_digits[c]))
163
56.6k
          value+=(unsigned int) hex_digits[c];
164
57.0k
      }
165
57.5k
    c=ReadBlobByte(image);
166
57.5k
    if (c == EOF)
167
186
      return(-1);
168
57.5k
  } while (hex_digits[c & 0xff] >= 0);
169
52.2k
  return((int) value);
170
52.4k
}
171
172
static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception)
173
1.74k
{
174
1.74k
  char
175
1.74k
    buffer[MagickPathExtent],
176
1.74k
    name[MagickPathExtent];
177
178
1.74k
  Image
179
1.74k
    *image;
180
181
1.74k
  int
182
1.74k
    c;
183
184
1.74k
  long
185
1.74k
    height,
186
1.74k
    width;
187
188
1.74k
  MagickBooleanType
189
1.74k
    status;
190
191
1.74k
  MagickOffsetType
192
1.74k
    offset;
193
194
1.74k
  Quantum
195
1.74k
    *q;
196
197
1.74k
  short int
198
1.74k
    hex_digits[256];
199
200
1.74k
  ssize_t
201
1.74k
    i,
202
1.74k
    x,
203
1.74k
    y;
204
205
1.74k
  unsigned char
206
1.74k
    *data,
207
1.74k
    *p;
208
209
1.74k
  unsigned int
210
1.74k
    bit,
211
1.74k
    byte,
212
1.74k
    bytes_per_line,
213
1.74k
    length,
214
1.74k
    padding,
215
1.74k
    version;
216
217
  /*
218
    Open image file.
219
  */
220
1.74k
  assert(image_info != (const ImageInfo *) NULL);
221
1.74k
  assert(image_info->signature == MagickCoreSignature);
222
1.74k
  assert(exception != (ExceptionInfo *) NULL);
223
1.74k
  assert(exception->signature == MagickCoreSignature);
224
1.74k
  if (IsEventLogging() != MagickFalse)
225
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
226
0
      image_info->filename);
227
1.74k
  image=AcquireImage(image_info,exception);
228
1.74k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
229
1.74k
  if (status == MagickFalse)
230
0
    {
231
0
      image=DestroyImageList(image);
232
0
      return((Image *) NULL);
233
0
    }
234
  /*
235
    Read X bitmap header.
236
  */
237
1.74k
  width=0;
238
1.74k
  height=0;
239
1.74k
  *name='\0';
240
4.76k
  while (ReadBlobString(image,buffer) != (char *) NULL)
241
4.26k
    if (MagickSscanf(buffer,"#define %1024s %ld",name,&width) == 2)
242
2.50k
      if ((strlen(name) >= 6) &&
243
2.50k
          (LocaleCompare(name+strlen(name)-6,"_width") == 0))
244
1.24k
        break;
245
4.32k
  while (ReadBlobString(image,buffer) != (char *) NULL)
246
3.63k
    if (MagickSscanf(buffer,"#define %1024s %ld",name,&height) == 2)
247
2.25k
      if ((strlen(name) >= 7) &&
248
2.25k
          (LocaleCompare(name+strlen(name)-7,"_height") == 0))
249
1.05k
        break;
250
1.74k
  if ((width <= 0) || (height <= 0) || (EOFBlob(image) != MagickFalse))
251
1.05k
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
252
1.05k
  image->columns=(size_t) width;
253
1.05k
  image->rows=(size_t) height;
254
1.05k
  image->depth=8;
255
1.05k
  image->storage_class=PseudoClass;
256
1.05k
  image->colors=2;
257
  /*
258
    Scan until hex digits.
259
  */
260
1.05k
  version=11;
261
1.05k
  offset=TellBlob(image);
262
5.74k
  while (ReadBlobString(image,buffer) != (char *) NULL)
263
5.38k
  {
264
5.38k
    if (MagickSscanf(buffer,"static short %1024s = {",name) == 1)
265
635
      version=10;
266
4.75k
    else if (MagickSscanf(buffer,"static unsigned char %1024s = {",name) == 1)
267
377
      version=11;
268
4.37k
    else if (MagickSscanf(buffer,"static char %1024s = {",name) == 1)
269
2.58k
      version=11;
270
1.78k
    else
271
1.78k
      {
272
1.78k
        offset=TellBlob(image);
273
1.78k
        continue;
274
1.78k
      }
275
3.59k
    p=(unsigned char *) strrchr(name,'_');
276
3.59k
    if (p == (unsigned char *) NULL)
277
3.32k
      p=(unsigned char *) name;
278
271
    else
279
271
      p++;
280
3.59k
    if (LocaleCompare("bits[]",(char *) p) == 0)
281
690
      break;
282
3.59k
  }
283
  /*
284
    Initialize image structure.
285
  */
286
1.05k
  if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
287
1.05k
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
288
  /*
289
    Initialize colormap.
290
  */
291
1.05k
  image->colormap[0].red=(MagickRealType) QuantumRange;
292
1.05k
  image->colormap[0].green=(MagickRealType) QuantumRange;
293
1.05k
  image->colormap[0].blue=(MagickRealType) QuantumRange;
294
1.05k
  image->colormap[1].red=0.0;
295
1.05k
  image->colormap[1].green=0.0;
296
1.05k
  image->colormap[1].blue=0.0;
297
1.05k
  if (image_info->ping != MagickFalse)
298
23
    {
299
23
      (void) CloseBlob(image);
300
23
      return(GetFirstImageInList(image));
301
23
    }
302
1.02k
  status=SetImageExtent(image,image->columns,image->rows,exception);
303
1.02k
  if (status == MagickFalse)
304
207
    return(DestroyImageList(image));
305
822
  p=(unsigned char *) strrchr(buffer,'{');
306
822
  if (p != (unsigned char *) NULL)
307
21
    (void) SeekBlob(image,offset+((char *) p-buffer)+1,SEEK_SET);
308
  /*
309
    Initialize hex values.
310
  */
311
211k
  for (i=0; i < (ssize_t) (sizeof(hex_digits)/sizeof(*hex_digits)); i++)
312
210k
    hex_digits[i]=(-1);
313
822
  hex_digits[(int) '0']=0;
314
822
  hex_digits[(int) '1']=1;
315
822
  hex_digits[(int) '2']=2;
316
822
  hex_digits[(int) '3']=3;
317
822
  hex_digits[(int) '4']=4;
318
822
  hex_digits[(int) '5']=5;
319
822
  hex_digits[(int) '6']=6;
320
822
  hex_digits[(int) '7']=7;
321
822
  hex_digits[(int) '8']=8;
322
822
  hex_digits[(int) '9']=9;
323
822
  hex_digits[(int) 'A']=10;
324
822
  hex_digits[(int) 'B']=11;
325
822
  hex_digits[(int) 'C']=12;
326
822
  hex_digits[(int) 'D']=13;
327
822
  hex_digits[(int) 'E']=14;
328
822
  hex_digits[(int) 'F']=15;
329
822
  hex_digits[(int) 'a']=10;
330
822
  hex_digits[(int) 'b']=11;
331
822
  hex_digits[(int) 'c']=12;
332
822
  hex_digits[(int) 'd']=13;
333
822
  hex_digits[(int) 'e']=14;
334
822
  hex_digits[(int) 'f']=15;
335
822
  hex_digits[(int) 'x']=0;
336
822
  hex_digits[(int) ' ']=(-1);
337
822
  hex_digits[(int) ',']=(-1);
338
822
  hex_digits[(int) '}']=(-1);
339
822
  hex_digits[(int) '\n']=(-1);
340
822
  hex_digits[(int) '\t']=(-1);
341
  /*
342
    Read hex image data.
343
  */
344
822
  padding=0;
345
822
  if (((image->columns % 16) != 0) && ((image->columns % 16) < 9) &&
346
822
      (version == 10))
347
253
    padding=1;
348
822
  bytes_per_line=(unsigned int) (image->columns+7)/8+padding;
349
822
  length=(unsigned int) image->rows;
350
822
  data=(unsigned char *) AcquireQuantumMemory(length,bytes_per_line*
351
822
    sizeof(*data));
352
822
  if (data == (unsigned char *) NULL)
353
822
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
354
822
  p=data;
355
822
  if (version == 10)
356
50.6k
    for (i=0; i < (ssize_t) (bytes_per_line*image->rows); (i+=2))
357
50.4k
    {
358
50.4k
      c=XBMInteger(image,hex_digits);
359
50.4k
      if (c < 0)
360
176
        {
361
176
          data=(unsigned char *) RelinquishMagickMemory(data);
362
176
          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
363
0
        }
364
50.2k
      *p++=(unsigned char) c;
365
50.2k
      if ((padding == 0) || (((i+2) % bytes_per_line) != 0))
366
44.8k
        *p++=(unsigned char) (c >> 8);
367
50.2k
    }
368
379
  else
369
2.41k
    for (i=0; i < (ssize_t) (bytes_per_line*image->rows); i++)
370
2.31k
    {
371
2.31k
      c=XBMInteger(image,hex_digits);
372
2.31k
      if (c < 0)
373
276
        {
374
276
          data=(unsigned char *) RelinquishMagickMemory(data);
375
276
          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
376
0
        }
377
2.03k
      *p++=(unsigned char) c;
378
2.03k
    }
379
370
  if (EOFBlob(image) != MagickFalse)
380
0
    {
381
0
      data=(unsigned char *) RelinquishMagickMemory(data);
382
0
      ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
383
0
    }
384
  /*
385
    Convert X bitmap image to pixel packets.
386
  */
387
370
  p=data;
388
13.3k
  for (y=0; y < (ssize_t) image->rows; y++)
389
12.9k
  {
390
12.9k
    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
391
12.9k
    if (q == (Quantum *) NULL)
392
0
      break;
393
12.9k
    bit=0;
394
12.9k
    byte=0;
395
726k
    for (x=0; x < (ssize_t) image->columns; x++)
396
713k
    {
397
713k
      if (bit == 0)
398
95.5k
        byte=(unsigned int) (*p++);
399
713k
      SetPixelIndex(image,(Quantum) ((byte & 0x01) != 0 ? 0x01 : 0x00),q);
400
713k
      bit++;
401
713k
      byte>>=1;
402
713k
      if (bit == 8)
403
85.1k
        bit=0;
404
713k
      q+=(ptrdiff_t) GetPixelChannels(image);
405
713k
    }
406
12.9k
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
407
0
      break;
408
12.9k
    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
409
12.9k
      image->rows);
410
12.9k
    if (status == MagickFalse)
411
0
      break;
412
12.9k
  }
413
370
  data=(unsigned char *) RelinquishMagickMemory(data);
414
370
  (void) SyncImage(image,exception);
415
370
  if (CloseBlob(image) == MagickFalse)
416
0
    status=MagickFalse;
417
370
  if (status == MagickFalse)
418
0
    return(DestroyImageList(image));
419
370
  return(GetFirstImageInList(image));
420
370
}
421

422
/*
423
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424
%                                                                             %
425
%                                                                             %
426
%                                                                             %
427
%   R e g i s t e r X B M I m a g e                                           %
428
%                                                                             %
429
%                                                                             %
430
%                                                                             %
431
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432
%
433
%  RegisterXBMImage() adds attributes for the XBM image format to
434
%  the list of supported formats.  The attributes include the image format
435
%  tag, a method to read and/or write the format, whether the format
436
%  supports the saving of more than one frame to the same file or blob,
437
%  whether the format supports native in-memory I/O, and a brief
438
%  description of the format.
439
%
440
%  The format of the RegisterXBMImage method is:
441
%
442
%      size_t RegisterXBMImage(void)
443
%
444
*/
445
ModuleExport size_t RegisterXBMImage(void)
446
10
{
447
10
  MagickInfo
448
10
    *entry;
449
450
10
  entry=AcquireMagickInfo("XBM","XBM",
451
10
    "X Windows system bitmap (black and white)");
452
10
  entry->decoder=(DecodeImageHandler *) ReadXBMImage;
453
10
  entry->encoder=(EncodeImageHandler *) WriteXBMImage;
454
10
  entry->magick=(IsImageFormatHandler *) IsXBM;
455
10
  entry->flags|=CoderDecoderSeekableStreamFlag;
456
10
  entry->flags^=CoderAdjoinFlag;
457
10
  (void) RegisterMagickInfo(entry);
458
10
  return(MagickImageCoderSignature);
459
10
}
460

461
/*
462
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463
%                                                                             %
464
%                                                                             %
465
%                                                                             %
466
%   U n r e g i s t e r X B M I m a g e                                       %
467
%                                                                             %
468
%                                                                             %
469
%                                                                             %
470
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471
%
472
%  UnregisterXBMImage() removes format registrations made by the
473
%  XBM module from the list of supported formats.
474
%
475
%  The format of the UnregisterXBMImage method is:
476
%
477
%      UnregisterXBMImage(void)
478
%
479
*/
480
ModuleExport void UnregisterXBMImage(void)
481
0
{
482
0
  (void) UnregisterMagickInfo("XBM");
483
0
}
484

485
/*
486
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487
%                                                                             %
488
%                                                                             %
489
%                                                                             %
490
%   W r i t e X B M I m a g e                                                 %
491
%                                                                             %
492
%                                                                             %
493
%                                                                             %
494
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
495
%
496
%  WriteXBMImage() writes an image to a file in the X bitmap format.
497
%
498
%  The format of the WriteXBMImage method is:
499
%
500
%      MagickBooleanType WriteXBMImage(const ImageInfo *image_info,
501
%        Image *image,ExceptionInfo *exception)
502
%
503
%  A description of each parameter follows.
504
%
505
%    o image_info: the image info.
506
%
507
%    o image:  The image.
508
%
509
%    o exception: return any errors or warnings in this structure.
510
%
511
*/
512
static MagickBooleanType WriteXBMImage(const ImageInfo *image_info,Image *image,
513
  ExceptionInfo *exception)
514
370
{
515
370
  char
516
370
    basename[MagickPathExtent],
517
370
    buffer[MagickPathExtent];
518
519
370
  MagickBooleanType
520
370
    status;
521
522
370
  const Quantum
523
370
    *p;
524
525
370
  ssize_t
526
370
    x;
527
528
370
  size_t
529
370
    bit,
530
370
    byte;
531
532
370
  ssize_t
533
370
    count,
534
370
    y;
535
536
  /*
537
    Open output image file.
538
  */
539
370
  assert(image_info != (const ImageInfo *) NULL);
540
370
  assert(image_info->signature == MagickCoreSignature);
541
370
  assert(image != (Image *) NULL);
542
370
  assert(image->signature == MagickCoreSignature);
543
370
  assert(exception != (ExceptionInfo *) NULL);
544
370
  assert(exception->signature == MagickCoreSignature);
545
370
  if (image->debug != MagickFalse)
546
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
547
370
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
548
370
  if (status == MagickFalse)
549
0
    return(status);
550
370
  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
551
0
    (void) TransformImageColorspace(image,sRGBColorspace,exception);
552
  /*
553
    Write X bitmap header.
554
  */
555
370
  GetPathComponent(image->filename,BasePath,basename);
556
370
  (void) FormatLocaleString(buffer,MagickPathExtent,"#define %s_width %.20g\n",
557
370
    basename,(double) image->columns);
558
370
  (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
559
370
  (void) FormatLocaleString(buffer,MagickPathExtent,"#define %s_height %.20g\n",
560
370
    basename,(double) image->rows);
561
370
  (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
562
370
  (void) FormatLocaleString(buffer,MagickPathExtent,
563
370
    "static char %s_bits[] = {\n",basename);
564
370
  (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
565
370
  (void) CopyMagickString(buffer," ",MagickPathExtent);
566
370
  (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
567
  /*
568
    Convert MIFF to X bitmap pixels.
569
  */
570
370
  (void) SetImageType(image,BilevelType,exception);
571
370
  bit=0;
572
370
  byte=0;
573
370
  count=0;
574
370
  x=0;
575
370
  y=0;
576
370
  (void) CopyMagickString(buffer," ",MagickPathExtent);
577
370
  (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
578
13.3k
  for (y=0; y < (ssize_t) image->rows; y++)
579
12.9k
  {
580
12.9k
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
581
12.9k
    if (p == (const Quantum *) NULL)
582
0
      break;
583
726k
    for (x=0; x < (ssize_t) image->columns; x++)
584
713k
    {
585
713k
      byte>>=1;
586
713k
      if (GetPixelLuma(image,p) < ((double) QuantumRange/2))
587
122k
        byte|=0x80;
588
713k
      bit++;
589
713k
      if (bit == 8)
590
85.1k
        {
591
          /*
592
            Write a bitmap byte to the image file.
593
          */
594
85.1k
          (void) FormatLocaleString(buffer,MagickPathExtent,"0x%02X, ",
595
85.1k
            (unsigned int) (byte & 0xff));
596
85.1k
          (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
597
85.1k
          count++;
598
85.1k
          if (count == 12)
599
6.29k
            {
600
6.29k
              (void) CopyMagickString(buffer,"\n  ",MagickPathExtent);
601
6.29k
              (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
602
6.29k
              count=0;
603
6.29k
            };
604
85.1k
          bit=0;
605
85.1k
          byte=0;
606
85.1k
        }
607
713k
      p+=(ptrdiff_t) GetPixelChannels(image);
608
713k
    }
609
12.9k
    if (bit != 0)
610
10.4k
      {
611
        /*
612
          Write a bitmap byte to the image file.
613
        */
614
10.4k
        byte>>=(8-bit);
615
10.4k
        (void) FormatLocaleString(buffer,MagickPathExtent,"0x%02X, ",
616
10.4k
          (unsigned int) (byte & 0xff));
617
10.4k
        (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
618
10.4k
        count++;
619
10.4k
        if (count == 12)
620
1.54k
          {
621
1.54k
            (void) CopyMagickString(buffer,"\n  ",MagickPathExtent);
622
1.54k
            (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
623
1.54k
            count=0;
624
1.54k
          };
625
10.4k
        bit=0;
626
10.4k
        byte=0;
627
10.4k
      };
628
12.9k
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
629
12.9k
      image->rows);
630
12.9k
    if (status == MagickFalse)
631
0
      break;
632
12.9k
  }
633
370
  (void) CopyMagickString(buffer,"};\n",MagickPathExtent);
634
370
  (void) WriteBlob(image,strlen(buffer),(unsigned char *) buffer);
635
370
  if (CloseBlob(image) == MagickFalse)
636
0
    status=MagickFalse;
637
370
  return(status);
638
370
}