/src/graphicsmagick/coders/xbm.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2003-2025 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 | | % X X BBBB M M % |
15 | | % X X B B MM MM % |
16 | | % X BBBB M M M % |
17 | | % X X B B M M % |
18 | | % X X BBBB M M % |
19 | | % % |
20 | | % % |
21 | | % Read/Write X Windows System Bitmap Format. % |
22 | | % % |
23 | | % % |
24 | | % Software Design % |
25 | | % John Cristy % |
26 | | % July 1992 % |
27 | | % % |
28 | | % % |
29 | | % % |
30 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
31 | | % |
32 | | % |
33 | | */ |
34 | | |
35 | | /* |
36 | | Include declarations. |
37 | | */ |
38 | | #include "magick/studio.h" |
39 | | #include "magick/blob.h" |
40 | | #include "magick/colormap.h" |
41 | | #include "magick/magick.h" |
42 | | #include "magick/monitor.h" |
43 | | #include "magick/pixel_cache.h" |
44 | | #include "magick/utility.h" |
45 | | #include "magick/static.h" |
46 | | |
47 | | /* |
48 | | Forward declarations. |
49 | | */ |
50 | | static unsigned int |
51 | | WriteXBMImage(const ImageInfo *,Image *); |
52 | | |
53 | | /* |
54 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
55 | | % % |
56 | | % % |
57 | | % % |
58 | | % I s X B M % |
59 | | % % |
60 | | % % |
61 | | % % |
62 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
63 | | % |
64 | | % Method IsXBM returns True if the image format type, identified by the |
65 | | % magick string, is XBM. |
66 | | % |
67 | | % The format of the IsXBM method is: |
68 | | % |
69 | | % unsigned int IsXBM(const unsigned char *magick,const size_t length) |
70 | | % |
71 | | % A description of each parameter follows: |
72 | | % |
73 | | % o status: Method IsXBM returns True if the image format type is XBM. |
74 | | % |
75 | | % o magick: This string is generally the first few bytes of an image file |
76 | | % or blob. |
77 | | % |
78 | | % o length: Specifies the length of the magick string. |
79 | | % |
80 | | % |
81 | | */ |
82 | | static unsigned int IsXBM(const unsigned char *magick,const size_t length) |
83 | 0 | { |
84 | 0 | if (length < 7) |
85 | 0 | return(False); |
86 | 0 | if (LocaleNCompare((char *) magick,"#define",7) == 0) |
87 | 0 | return(True); |
88 | 0 | return(False); |
89 | 0 | } |
90 | | |
91 | | /* |
92 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
93 | | % % |
94 | | % % |
95 | | % % |
96 | | % R e a d X B M I m a g e % |
97 | | % % |
98 | | % % |
99 | | % % |
100 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
101 | | % |
102 | | % Method ReadXBMImage reads an X11 bitmap image file and returns it. It |
103 | | % allocates the memory necessary for the new Image structure and returns a |
104 | | % pointer to the new image. |
105 | | % |
106 | | % The format of the ReadXBMImage method is: |
107 | | % |
108 | | % Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) |
109 | | % |
110 | | % A description of each parameter follows: |
111 | | % |
112 | | % o image: Method ReadXBMImage returns a pointer to the image after |
113 | | % reading. A null image is returned if there is a memory shortage or |
114 | | % if the image cannot be read. |
115 | | % |
116 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
117 | | % |
118 | | % o exception: return any errors or warnings in this structure. |
119 | | % |
120 | | % |
121 | | */ |
122 | | |
123 | | static int XBMInteger(Image *image,const unsigned int max_digits, short int *hex_digits) |
124 | 2.74M | { |
125 | 2.74M | unsigned int |
126 | 2.74M | digits; |
127 | | |
128 | 2.74M | int |
129 | 2.74M | c, |
130 | 2.74M | value; |
131 | | |
132 | | /* |
133 | | Read hex value in form 0xhh or 0xhhhh from text which may look |
134 | | like ", 0x7f". FIXME: This implementation is non-validating. |
135 | | */ |
136 | | |
137 | 2.74M | value=0; |
138 | 2.74M | digits=0U; |
139 | 5.62M | for ( digits=0U; digits <= max_digits+1; ) |
140 | 5.62M | { |
141 | 5.62M | c=ReadBlobByte(image); |
142 | 5.62M | if (c == EOF) |
143 | 146 | { |
144 | 146 | value=(-1); |
145 | 146 | break; |
146 | 146 | } |
147 | 5.62M | c&=0xff; |
148 | 5.62M | if (isxdigit(c)) |
149 | 2.75M | { |
150 | 2.75M | value=(value << 4)+hex_digits[c]; |
151 | 2.75M | digits++; |
152 | 2.75M | continue; |
153 | 2.75M | } |
154 | 2.86M | if ((hex_digits[c]) < 0 && digits) |
155 | 2.74M | break; |
156 | 2.86M | } |
157 | | /* The '0' in '0x' is currently counted as a digit */ |
158 | 2.74M | if (digits > max_digits+1) |
159 | 5 | value=(-1); |
160 | 2.74M | return(value); |
161 | 2.74M | } |
162 | | |
163 | | static Image *ReadXBMImage(const ImageInfo *image_info,ExceptionInfo *exception) |
164 | 42.5k | { |
165 | 42.5k | char |
166 | 42.5k | buffer[MaxTextExtent], |
167 | 42.5k | name[MaxTextExtent]; |
168 | | |
169 | 42.5k | Image |
170 | 42.5k | *image; |
171 | | |
172 | 42.5k | register IndexPacket |
173 | 42.5k | *indexes; |
174 | | |
175 | 42.5k | register size_t |
176 | 42.5k | bytes_per_line, |
177 | 42.5k | i; |
178 | | |
179 | 42.5k | unsigned long |
180 | 42.5k | x, |
181 | 42.5k | y; |
182 | | |
183 | 42.5k | long |
184 | 42.5k | columns_signed, |
185 | 42.5k | rows_signed; |
186 | | |
187 | 42.5k | register PixelPacket |
188 | 42.5k | *q; |
189 | | |
190 | 42.5k | register unsigned char |
191 | 42.5k | *p; |
192 | | |
193 | 42.5k | unsigned char |
194 | 42.5k | *data; |
195 | | |
196 | 42.5k | unsigned int |
197 | 42.5k | bit, |
198 | 42.5k | byte, |
199 | 42.5k | padding, |
200 | 42.5k | version; |
201 | | |
202 | 42.5k | int |
203 | 42.5k | value; |
204 | | |
205 | 42.5k | short int |
206 | 42.5k | hex_digits[256]; |
207 | | |
208 | 42.5k | MagickPassFail |
209 | 42.5k | status; |
210 | | |
211 | | /* |
212 | | Open image file. |
213 | | */ |
214 | 42.5k | assert(image_info != (const ImageInfo *) NULL); |
215 | 42.5k | assert(image_info->signature == MagickSignature); |
216 | 42.5k | assert(exception != (ExceptionInfo *) NULL); |
217 | 42.5k | assert(exception->signature == MagickSignature); |
218 | 42.5k | image=AllocateImage(image_info); |
219 | 42.5k | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
220 | 42.5k | if (status == False) |
221 | 42.5k | ThrowReaderException(FileOpenError,UnableToOpenFile,image); |
222 | | /* |
223 | | Read X bitmap header. |
224 | | */ |
225 | 42.5k | (void) memset(buffer,0,sizeof(buffer)); |
226 | 42.5k | name[0]='\0'; |
227 | 42.5k | columns_signed=0; |
228 | 42.5k | rows_signed=0; |
229 | 259k | while (ReadBlobString(image,buffer) != (char *) NULL) |
230 | 245k | if (sscanf(buffer,"#define %s %ld",name,&columns_signed) == 2) |
231 | 50.4k | if ((strlen(name) >= 6) && |
232 | 48.9k | (LocaleCompare(name+strlen(name)-6,"_width") == 0)) |
233 | 28.6k | break; |
234 | 76.0k | while (ReadBlobString(image,buffer) != (char *) NULL) |
235 | 46.4k | if (sscanf(buffer,"#define %s %ld",name,&rows_signed) == 2) |
236 | 22.8k | if ((strlen(name) >= 7) && |
237 | 19.8k | (LocaleCompare(name+strlen(name)-7,"_height") == 0)) |
238 | 12.9k | break; |
239 | 42.5k | if (EOFBlob(image)) |
240 | 29.6k | ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); |
241 | 12.9k | if ((columns_signed <= 0) || (rows_signed <= 0)) |
242 | 6.75k | ThrowReaderException(CorruptImageError,ImproperImageHeader,image); |
243 | 6.15k | image->columns=(unsigned long) columns_signed; |
244 | 6.15k | image->rows=(unsigned long) rows_signed; |
245 | 6.15k | image->depth=8; |
246 | 6.15k | image->storage_class=PseudoClass; |
247 | 6.15k | image->colors=2; |
248 | | /* |
249 | | Scan until hex digits. |
250 | | */ |
251 | 6.15k | version=11; |
252 | 38.5k | while (ReadBlobString(image,buffer) != (char *) NULL) |
253 | 32.9k | { |
254 | 32.9k | if (sscanf(buffer,"static short %s = {",name) == 1) |
255 | 1.59k | version=10; |
256 | 31.3k | else |
257 | 31.3k | if (sscanf(buffer,"static unsigned char %s = {",name) == 1) |
258 | 589 | version=11; |
259 | 30.7k | else |
260 | 30.7k | if (sscanf(buffer,"static char %s = {",name) == 1) |
261 | 5.52k | version=11; |
262 | 25.2k | else |
263 | 25.2k | continue; |
264 | 7.71k | p=(unsigned char *) strrchr(name,'_'); |
265 | 7.71k | if (p == (unsigned char *) NULL) |
266 | 3.24k | p=(unsigned char *) name; |
267 | 4.46k | else |
268 | 4.46k | p++; |
269 | 7.71k | if (LocaleCompare("bits[]",(char *) p) == 0) |
270 | 608 | break; |
271 | 7.71k | } |
272 | 6.15k | if (EOFBlob(image)) |
273 | 5.55k | ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image); |
274 | | |
275 | | /* |
276 | | Initialize image structure. |
277 | | */ |
278 | 605 | if (!AllocateImageColormap(image,image->colors)) |
279 | 605 | ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
280 | | /* |
281 | | Initialize colormap. |
282 | | */ |
283 | 605 | image->colormap[0].red=MaxRGB; |
284 | 605 | image->colormap[0].green=MaxRGB; |
285 | 605 | image->colormap[0].blue=MaxRGB; |
286 | 605 | image->colormap[1].red=0; |
287 | 605 | image->colormap[1].green=0; |
288 | 605 | image->colormap[1].blue=0; |
289 | 605 | if (image_info->ping) |
290 | 0 | { |
291 | 0 | CloseBlob(image); |
292 | 0 | StopTimer(&image->timer); |
293 | 0 | return(image); |
294 | 0 | } |
295 | 605 | if (CheckImagePixelLimits(image, exception) != MagickPass) |
296 | 437 | ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); |
297 | | /* |
298 | | Allocate temporary storage for X bitmap image |
299 | | */ |
300 | 437 | padding=0; |
301 | 437 | if ((image->columns % 16) && ((image->columns % 16) < 9) && (version == 10)) |
302 | 110 | padding=1; |
303 | 437 | bytes_per_line=((size_t) image->columns+7)/8+padding; |
304 | 437 | data=MagickAllocateResourceLimitedArray(unsigned char *,image->rows,bytes_per_line); |
305 | 437 | if (data == (unsigned char *) NULL) |
306 | 437 | ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
307 | | /* |
308 | | Initialize hex values. |
309 | | */ |
310 | 112k | for (i = 0; i < sizeof(hex_digits)/sizeof(hex_digits[0]); i++) |
311 | 111k | hex_digits[i]=(-1); |
312 | 437 | hex_digits['0']=0; |
313 | 437 | hex_digits['1']=1; |
314 | 437 | hex_digits['2']=2; |
315 | 437 | hex_digits['3']=3; |
316 | 437 | hex_digits['4']=4; |
317 | 437 | hex_digits['5']=5; |
318 | 437 | hex_digits['6']=6; |
319 | 437 | hex_digits['7']=7; |
320 | 437 | hex_digits['8']=8; |
321 | 437 | hex_digits['9']=9; |
322 | 437 | hex_digits['A']=10; |
323 | 437 | hex_digits['B']=11; |
324 | 437 | hex_digits['C']=12; |
325 | 437 | hex_digits['D']=13; |
326 | 437 | hex_digits['E']=14; |
327 | 437 | hex_digits['F']=15; |
328 | 437 | hex_digits['a']=10; |
329 | 437 | hex_digits['b']=11; |
330 | 437 | hex_digits['c']=12; |
331 | 437 | hex_digits['d']=13; |
332 | 437 | hex_digits['e']=14; |
333 | 437 | hex_digits['f']=15; |
334 | 437 | hex_digits['x']=0; |
335 | 437 | hex_digits[' ']=(-1); |
336 | 437 | hex_digits[',']=(-1); |
337 | 437 | hex_digits['}']=(-1); |
338 | 437 | hex_digits['\n']=(-1); |
339 | 437 | hex_digits['\t']=(-1); |
340 | | /* |
341 | | Read hex image data. |
342 | | */ |
343 | 437 | p=data; |
344 | 437 | if (version == 10) |
345 | 2.72M | for (i=0; i < (bytes_per_line*image->rows); (i+=2)) |
346 | 2.72M | { |
347 | 2.72M | value=XBMInteger(image,4,hex_digits); |
348 | 2.72M | if (value < 0) |
349 | 56 | { |
350 | 56 | MagickFreeResourceLimitedMemory(unsigned char *,data); |
351 | 56 | ThrowReaderException(CorruptImageError,ImproperImageHeader,image); |
352 | 0 | } |
353 | 2.72M | *p++=(unsigned char) value; |
354 | 2.72M | if (!padding || ((i+2) % bytes_per_line)) |
355 | 2.70M | *p++=(unsigned char) (value >> 8); |
356 | 2.72M | } |
357 | 154 | else |
358 | 15.2k | for (i=0; i < (bytes_per_line*image->rows); i++) |
359 | 15.1k | { |
360 | 15.1k | value=XBMInteger(image,2,hex_digits); |
361 | 15.1k | if (value < 0) |
362 | 95 | { |
363 | 95 | MagickFreeResourceLimitedMemory(unsigned char *,data); |
364 | 95 | ThrowReaderException(CorruptImageError,ImproperImageHeader,image); |
365 | 0 | } |
366 | 15.0k | *p++=(unsigned char) value; |
367 | 15.0k | } |
368 | | /* |
369 | | Convert X bitmap image to pixel packets. |
370 | | */ |
371 | 286 | p=data; |
372 | 97.4k | for (y=0; y < image->rows; y++) |
373 | 97.1k | { |
374 | 97.1k | q=SetImagePixels(image,0,y,image->columns,1); |
375 | 97.1k | if (q == (PixelPacket *) NULL) |
376 | 0 | break; |
377 | 97.1k | indexes=AccessMutableIndexes(image); |
378 | 97.1k | bit=0U; |
379 | 97.1k | byte=0U; |
380 | 41.8M | for (x=0; x < image->columns; x++) |
381 | 41.7M | { |
382 | 41.7M | if (bit == 0U) |
383 | 5.25M | byte=(*p++); |
384 | 41.7M | indexes[x]=byte & 0x01 ? 0x01 : 0x00; |
385 | 41.7M | bit++; |
386 | 41.7M | byte>>=1U; |
387 | 41.7M | if (bit == 8U) |
388 | 5.18M | bit=0U; |
389 | 41.7M | } |
390 | 97.1k | if (!SyncImagePixels(image)) |
391 | 0 | break; |
392 | 97.1k | if (QuantumTick(y,image->rows)) |
393 | 16.9k | if (!MagickMonitorFormatted(y,image->rows,exception, |
394 | 16.9k | LoadImageText,image->filename, |
395 | 16.9k | image->columns,image->rows)) |
396 | 0 | break; |
397 | 97.1k | } |
398 | 286 | MagickFreeResourceLimitedMemory(unsigned char *,data); |
399 | 286 | (void) SyncImage(image); |
400 | 286 | CloseBlob(image); |
401 | 286 | StopTimer(&image->timer); |
402 | 286 | return(image); |
403 | 437 | } |
404 | | |
405 | | /* |
406 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
407 | | % % |
408 | | % % |
409 | | % % |
410 | | % R e g i s t e r X B M I m a g e % |
411 | | % % |
412 | | % % |
413 | | % % |
414 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
415 | | % |
416 | | % Method RegisterXBMImage adds attributes for the XBM image format to |
417 | | % the list of supported formats. The attributes include the image format |
418 | | % tag, a method to read and/or write the format, whether the format |
419 | | % supports the saving of more than one frame to the same file or blob, |
420 | | % whether the format supports native in-memory I/O, and a brief |
421 | | % description of the format. |
422 | | % |
423 | | % The format of the RegisterXBMImage method is: |
424 | | % |
425 | | % RegisterXBMImage(void) |
426 | | % |
427 | | */ |
428 | | ModuleExport void RegisterXBMImage(void) |
429 | 4 | { |
430 | 4 | MagickInfo |
431 | 4 | *entry; |
432 | | |
433 | 4 | entry=SetMagickInfo("XBM"); |
434 | 4 | entry->decoder=(DecoderHandler) ReadXBMImage; |
435 | 4 | entry->encoder=(EncoderHandler) WriteXBMImage; |
436 | 4 | entry->magick=(MagickHandler) IsXBM; |
437 | 4 | entry->adjoin=False; |
438 | 4 | entry->description="X Windows system bitmap (black/white)"; |
439 | 4 | entry->module="XBM"; |
440 | 4 | (void) RegisterMagickInfo(entry); |
441 | 4 | } |
442 | | |
443 | | /* |
444 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
445 | | % % |
446 | | % % |
447 | | % % |
448 | | % U n r e g i s t e r X B M I m a g e % |
449 | | % % |
450 | | % % |
451 | | % % |
452 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
453 | | % |
454 | | % Method UnregisterXBMImage removes format registrations made by the |
455 | | % XBM module from the list of supported formats. |
456 | | % |
457 | | % The format of the UnregisterXBMImage method is: |
458 | | % |
459 | | % UnregisterXBMImage(void) |
460 | | % |
461 | | */ |
462 | | ModuleExport void UnregisterXBMImage(void) |
463 | 0 | { |
464 | 0 | (void) UnregisterMagickInfo("XBM"); |
465 | 0 | } |
466 | | |
467 | | /* |
468 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
469 | | % % |
470 | | % % |
471 | | % % |
472 | | % W r i t e X B M I m a g e % |
473 | | % % |
474 | | % % |
475 | | % % |
476 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
477 | | % |
478 | | % Procedure WriteXBMImage writes an image to a file in the X bitmap format. |
479 | | % |
480 | | % The format of the WriteXBMImage method is: |
481 | | % |
482 | | % unsigned int WriteXBMImage(const ImageInfo *image_info,Image *image) |
483 | | % |
484 | | % A description of each parameter follows. |
485 | | % |
486 | | % o status: Method WriteXBMImage return True if the image is written. |
487 | | % False is returned is there is a memory shortage or if the image file |
488 | | % fails to write. |
489 | | % |
490 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
491 | | % |
492 | | % o image: A pointer to an Image structure. |
493 | | % |
494 | | % |
495 | | */ |
496 | | static unsigned int WriteXBMImage(const ImageInfo *image_info,Image *image) |
497 | 279 | { |
498 | 279 | char |
499 | 279 | basename[MaxTextExtent], |
500 | 279 | buffer[MaxTextExtent]; |
501 | | |
502 | 279 | int |
503 | 279 | y; |
504 | | |
505 | 279 | register const PixelPacket |
506 | 279 | *p; |
507 | | |
508 | 279 | register long |
509 | 279 | x; |
510 | | |
511 | 279 | register const IndexPacket |
512 | 279 | *indexes; |
513 | | |
514 | 279 | unsigned char |
515 | 279 | bit, |
516 | 279 | byte, |
517 | 279 | polarity; |
518 | | |
519 | 279 | unsigned int |
520 | 279 | status; |
521 | | |
522 | 279 | unsigned long |
523 | 279 | count; |
524 | | |
525 | | /* |
526 | | Open output image file. |
527 | | */ |
528 | 279 | assert(image_info != (const ImageInfo *) NULL); |
529 | 279 | assert(image_info->signature == MagickSignature); |
530 | 279 | assert(image != (Image *) NULL); |
531 | 279 | assert(image->signature == MagickSignature); |
532 | 279 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); |
533 | 279 | if (status == False) |
534 | 279 | ThrowWriterException(FileOpenError,UnableToOpenFile,image); |
535 | 279 | (void) TransformColorspace(image,RGBColorspace); |
536 | | /* |
537 | | Write X bitmap header. |
538 | | */ |
539 | 279 | GetPathComponent(image->filename,BasePath,basename); |
540 | 279 | FormatString(buffer,"#define %.1024s_width %lu\n",basename,image->columns); |
541 | 279 | (void) WriteBlob(image,strlen(buffer),buffer); |
542 | 279 | FormatString(buffer,"#define %.1024s_height %lu\n",basename,image->rows); |
543 | 279 | (void) WriteBlob(image,strlen(buffer),buffer); |
544 | 279 | FormatString(buffer,"static char %.1024s_bits[] = {\n",basename); |
545 | 279 | (void) WriteBlob(image,strlen(buffer),buffer); |
546 | 279 | (void) strlcpy(buffer," ",sizeof(buffer)); |
547 | 279 | (void) WriteBlob(image,strlen(buffer),buffer); |
548 | | /* |
549 | | Convert MIFF to X bitmap pixels. |
550 | | */ |
551 | 279 | (void) SetImageType(image,BilevelType); |
552 | 279 | polarity=(PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2)); |
553 | 279 | if (image->colors == 2) |
554 | 279 | polarity=(PixelIntensityToQuantum(&image->colormap[0]) < |
555 | 279 | PixelIntensityToQuantum(&image->colormap[1])); |
556 | 279 | bit=0; |
557 | 279 | byte=0; |
558 | 279 | count=0; |
559 | 279 | x=0; |
560 | 279 | y=0; |
561 | 279 | (void) strlcpy(buffer," ",sizeof(buffer)); |
562 | 279 | (void) WriteBlob(image,strlen(buffer),buffer); |
563 | 97.4k | for (y=0; y < (long) image->rows; y++) |
564 | 97.1k | { |
565 | 97.1k | p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); |
566 | 97.1k | if (p == (const PixelPacket *) NULL) |
567 | 0 | break; |
568 | 97.1k | indexes=AccessImmutableIndexes(image); |
569 | 41.8M | for (x=0; x < (long) image->columns; x++) |
570 | 41.7M | { |
571 | 41.7M | byte>>=1; |
572 | 41.7M | if (indexes[x] != polarity) |
573 | 7.84M | byte|=0x80; |
574 | 41.7M | bit++; |
575 | 41.7M | if (bit == 8) |
576 | 5.18M | { |
577 | | /* |
578 | | Write a bitmap byte to the image file. |
579 | | */ |
580 | 5.18M | FormatString(buffer,"0x%02X, ",(unsigned int) (byte & 0xff)); |
581 | 5.18M | (void) WriteBlob(image,strlen(buffer),buffer); |
582 | 5.18M | count++; |
583 | 5.18M | if (count == 12) |
584 | 425k | { |
585 | 425k | (void) strlcpy(buffer,"\n ",sizeof(buffer)); |
586 | 425k | (void) WriteBlob(image,strlen(buffer),buffer); |
587 | 425k | count=0; |
588 | 425k | }; |
589 | 5.18M | bit=0; |
590 | 5.18M | byte=0; |
591 | 5.18M | } |
592 | 41.7M | p++; |
593 | 41.7M | } |
594 | 97.1k | if (bit != 0) |
595 | 69.9k | { |
596 | | /* |
597 | | Write a bitmap byte to the image file. |
598 | | */ |
599 | 69.9k | byte>>=(8-bit); |
600 | 69.9k | FormatString(buffer,"0x%02X, ",(unsigned int) (byte & 0xff)); |
601 | 69.9k | (void) WriteBlob(image,strlen(buffer),buffer); |
602 | 69.9k | count++; |
603 | 69.9k | if (count == 12) |
604 | 12.5k | { |
605 | 12.5k | (void) strlcpy(buffer,"\n ",sizeof(buffer)); |
606 | 12.5k | (void) WriteBlob(image,strlen(buffer),buffer); |
607 | 12.5k | count=0; |
608 | 12.5k | }; |
609 | 69.9k | bit=0; |
610 | 69.9k | byte=0; |
611 | 69.9k | }; |
612 | 97.1k | if (QuantumTick(y,image->rows)) |
613 | 16.9k | if (!MagickMonitorFormatted(y,image->rows,&image->exception, |
614 | 16.9k | SaveImageText,image->filename, |
615 | 16.9k | image->columns,image->rows)) |
616 | 0 | break; |
617 | 97.1k | } |
618 | 279 | (void) strlcpy(buffer,"};\n",sizeof(buffer)); |
619 | 279 | (void) WriteBlob(image,strlen(buffer),buffer); |
620 | 279 | status &= CloseBlob(image); |
621 | 279 | return(status); |
622 | 279 | } |