1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % DDDD IIIII BBBB %
7 % D D I B B %
8 % D D I BBBB %
9 % D D I B B %
10 % DDDD IIIII BBBB %
11 % %
12 % %
13 % Read/Write Windows DIB Image Format %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2016 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 % http://www.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.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colormap.h"
50 #include "MagickCore/colormap-private.h"
51 #include "MagickCore/colorspace.h"
52 #include "MagickCore/colorspace-private.h"
53 #include "MagickCore/draw.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image.h"
58 #include "MagickCore/image-private.h"
59 #include "MagickCore/list.h"
60 #include "MagickCore/log.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/monitor.h"
64 #include "MagickCore/monitor-private.h"
65 #include "MagickCore/pixel-accessor.h"
66 #include "MagickCore/quantum-private.h"
67 #include "MagickCore/static.h"
68 #include "MagickCore/string_.h"
69 #include "MagickCore/module.h"
70 #include "MagickCore/transform.h"
71
72 /*
73 Typedef declarations.
74 */
75 typedef struct _DIBInfo
76 {
77 size_t
78 size;
79
80 ssize_t
81 width,
82 height;
83
84 unsigned short
85 planes,
86 bits_per_pixel;
87
88 size_t
89 compression,
90 image_size,
91 x_pixels,
92 y_pixels,
93 number_colors,
94 red_mask,
95 green_mask,
96 blue_mask,
97 alpha_mask,
98 colors_important;
99
100 ssize_t
101 colorspace;
102
103 PointInfo
104 red_primary,
105 green_primary,
106 blue_primary,
107 gamma_scale;
108 } DIBInfo;
109
110 /*
111 Forward declarations.
112 */
113 static MagickBooleanType
114 WriteDIBImage(const ImageInfo *,Image *,ExceptionInfo *);
115
116 /*
117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118 % %
119 % %
120 % %
121 % D e c o d e I m a g e %
122 % %
123 % %
124 % %
125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126 %
127 % DecodeImage unpacks the packed image pixels into runlength-encoded
128 % pixel packets.
129 %
130 % The format of the DecodeImage method is:
131 %
132 % MagickBooleanType DecodeImage(Image *image,
133 % const MagickBooleanType compression,unsigned char *pixels)
134 %
135 % A description of each parameter follows:
136 %
137 % o image: the address of a structure of type Image.
138 %
139 % o compression: A value of 1 means the compressed pixels are runlength
140 % encoded for a 256-color bitmap. A value of 2 means a 16-color bitmap.
141 %
142 % o pixels: The address of a byte (8 bits) array of pixel data created by
143 % the decoding process.
144 %
145 */
DecodeImage(Image * image,const MagickBooleanType compression,unsigned char * pixels)146 static MagickBooleanType DecodeImage(Image *image,
147 const MagickBooleanType compression,unsigned char *pixels)
148 {
149 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__) || defined(__MINGW64__)
150 #define BI_RGB 0
151 #define BI_RLE8 1
152 #define BI_RLE4 2
153 #define BI_BITFIELDS 3
154 #undef BI_JPEG
155 #define BI_JPEG 4
156 #undef BI_PNG
157 #define BI_PNG 5
158 #endif
159
160 int
161 count;
162
163 ssize_t
164 y;
165
166 register ssize_t
167 i,
168 x;
169
170 register unsigned char
171 *p,
172 *q;
173
174 unsigned char
175 byte;
176
177 assert(image != (Image *) NULL);
178 assert(image->signature == MagickCoreSignature);
179 if (image->debug != MagickFalse)
180 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
181 assert(pixels != (unsigned char *) NULL);
182 (void) ResetMagickMemory(pixels,0,(size_t) image->columns*image->rows*
183 sizeof(*pixels));
184 byte=0;
185 x=0;
186 p=pixels;
187 q=pixels+(size_t) image->columns*image->rows;
188 for (y=0; y < (ssize_t) image->rows; )
189 {
190 if ((p < pixels) || (p >= q))
191 break;
192 count=ReadBlobByte(image);
193 if (count == EOF)
194 break;
195 if (count != 0)
196 {
197 count=(int) MagickMin((size_t) count,(size_t) (q-p));
198 /*
199 Encoded mode.
200 */
201 byte=(unsigned char) ReadBlobByte(image);
202 if (compression == BI_RLE8)
203 {
204 for (i=0; i < count; i++)
205 *p++=(unsigned char) byte;
206 }
207 else
208 {
209 for (i=0; i < count; i++)
210 *p++=(unsigned char)
211 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
212 }
213 x+=count;
214 }
215 else
216 {
217 /*
218 Escape mode.
219 */
220 count=ReadBlobByte(image);
221 if (count == 0x01)
222 return(MagickTrue);
223 switch (count)
224 {
225 case 0x00:
226 {
227 /*
228 End of line.
229 */
230 x=0;
231 y++;
232 p=pixels+y*image->columns;
233 break;
234 }
235 case 0x02:
236 {
237 /*
238 Delta mode.
239 */
240 x+=ReadBlobByte(image);
241 y+=ReadBlobByte(image);
242 p=pixels+y*image->columns+x;
243 break;
244 }
245 default:
246 {
247 /*
248 Absolute mode.
249 */
250 count=(int) MagickMin((size_t) count,(size_t) (q-p));
251 if (compression == BI_RLE8)
252 for (i=0; i < count; i++)
253 *p++=(unsigned char) ReadBlobByte(image);
254 else
255 for (i=0; i < count; i++)
256 {
257 if ((i & 0x01) == 0)
258 byte=(unsigned char) ReadBlobByte(image);
259 *p++=(unsigned char)
260 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
261 }
262 x+=count;
263 /*
264 Read pad byte.
265 */
266 if (compression == BI_RLE8)
267 {
268 if ((count & 0x01) != 0)
269 (void) ReadBlobByte(image);
270 }
271 else
272 if (((count & 0x03) == 1) || ((count & 0x03) == 2))
273 (void) ReadBlobByte(image);
274 break;
275 }
276 }
277 }
278 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
279 break;
280 }
281 (void) ReadBlobByte(image); /* end of line */
282 (void) ReadBlobByte(image);
283 return(MagickTrue);
284 }
285
286 /*
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 % %
289 % %
290 % %
291 % E n c o d e I m a g e %
292 % %
293 % %
294 % %
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 %
297 % EncodeImage compresses pixels using a runlength encoded format.
298 %
299 % The format of the EncodeImage method is:
300 %
301 % static MagickBooleanType EncodeImage(Image *image,
302 % const size_t bytes_per_line,const unsigned char *pixels,
303 % unsigned char *compressed_pixels)
304 %
305 % A description of each parameter follows:
306 %
307 % o image: The image.
308 %
309 % o bytes_per_line: the number of bytes in a scanline of compressed pixels
310 %
311 % o pixels: The address of a byte (8 bits) array of pixel data created by
312 % the compression process.
313 %
314 % o compressed_pixels: The address of a byte (8 bits) array of compressed
315 % pixel data.
316 %
317 */
EncodeImage(Image * image,const size_t bytes_per_line,const unsigned char * pixels,unsigned char * compressed_pixels)318 static size_t EncodeImage(Image *image,const size_t bytes_per_line,
319 const unsigned char *pixels,unsigned char *compressed_pixels)
320 {
321 ssize_t
322 y;
323
324 register const unsigned char
325 *p;
326
327 register ssize_t
328 i,
329 x;
330
331 register unsigned char
332 *q;
333
334 /*
335 Runlength encode pixels.
336 */
337 assert(image != (Image *) NULL);
338 assert(image->signature == MagickCoreSignature);
339 if (image->debug != MagickFalse)
340 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
341 assert(pixels != (const unsigned char *) NULL);
342 assert(compressed_pixels != (unsigned char *) NULL);
343 p=pixels;
344 q=compressed_pixels;
345 i=0;
346 for (y=0; y < (ssize_t) image->rows; y++)
347 {
348 for (x=0; x < (ssize_t) bytes_per_line; x+=i)
349 {
350 /*
351 Determine runlength.
352 */
353 for (i=1; ((x+i) < (ssize_t) bytes_per_line); i++)
354 if ((*(p+i) != *p) || (i == 255))
355 break;
356 *q++=(unsigned char) i;
357 *q++=(*p);
358 p+=i;
359 }
360 /*
361 End of line.
362 */
363 *q++=0x00;
364 *q++=0x00;
365 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
366 break;
367 }
368 /*
369 End of bitmap.
370 */
371 *q++=0;
372 *q++=0x01;
373 return((size_t) (q-compressed_pixels));
374 }
375
376 /*
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378 % %
379 % %
380 % %
381 % I s D I B %
382 % %
383 % %
384 % %
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386 %
387 % IsDIB() returns MagickTrue if the image format type, identified by the
388 % magick string, is DIB.
389 %
390 % The format of the IsDIB method is:
391 %
392 % MagickBooleanType IsDIB(const unsigned char *magick,const size_t length)
393 %
394 % A description of each parameter follows:
395 %
396 % o magick: compare image format pattern against these bytes.
397 %
398 % o length: Specifies the length of the magick string.
399 %
400 */
IsDIB(const unsigned char * magick,const size_t length)401 static MagickBooleanType IsDIB(const unsigned char *magick,const size_t length)
402 {
403 if (length < 2)
404 return(MagickFalse);
405 if (memcmp(magick,"\050\000",2) == 0)
406 return(MagickTrue);
407 return(MagickFalse);
408 }
409
410 /*
411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
412 % %
413 % %
414 % %
415 % R e a d D I B I m a g e %
416 % %
417 % %
418 % %
419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 %
421 % ReadDIBImage() reads a Microsoft Windows bitmap image file and
422 % returns it. It allocates the memory necessary for the new Image structure
423 % and returns a pointer to the new image.
424 %
425 % The format of the ReadDIBImage method is:
426 %
427 % image=ReadDIBImage(image_info)
428 %
429 % A description of each parameter follows:
430 %
431 % o image_info: the image info.
432 %
433 % o exception: return any errors or warnings in this structure.
434 %
435 */
ReadDIBImage(const ImageInfo * image_info,ExceptionInfo * exception)436 static Image *ReadDIBImage(const ImageInfo *image_info,ExceptionInfo *exception)
437 {
438 DIBInfo
439 dib_info;
440
441 Image
442 *image;
443
444 MagickBooleanType
445 status;
446
447 MemoryInfo
448 *pixel_info;
449
450 Quantum
451 index;
452
453 register ssize_t
454 x;
455
456 register Quantum
457 *q;
458
459 register ssize_t
460 i;
461
462 register unsigned char
463 *p;
464
465 size_t
466 bytes_per_line,
467 length;
468
469 ssize_t
470 bit,
471 count,
472 y;
473
474
475 unsigned char
476 *pixels;
477
478 /*
479 Open image file.
480 */
481 assert(image_info != (const ImageInfo *) NULL);
482 assert(image_info->signature == MagickCoreSignature);
483 if (image_info->debug != MagickFalse)
484 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
485 image_info->filename);
486 assert(exception != (ExceptionInfo *) NULL);
487 assert(exception->signature == MagickCoreSignature);
488 image=AcquireImage(image_info,exception);
489 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
490 if (status == MagickFalse)
491 {
492 image=DestroyImageList(image);
493 return((Image *) NULL);
494 }
495 /*
496 Determine if this a DIB file.
497 */
498 (void) ResetMagickMemory(&dib_info,0,sizeof(dib_info));
499 dib_info.size=ReadBlobLSBLong(image);
500 if (dib_info.size != 40)
501 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
502 /*
503 Microsoft Windows 3.X DIB image file.
504 */
505 dib_info.width=ReadBlobLSBSignedLong(image);
506 dib_info.height=ReadBlobLSBSignedLong(image);
507 dib_info.planes=ReadBlobLSBShort(image);
508 dib_info.bits_per_pixel=ReadBlobLSBShort(image);
509 if (dib_info.bits_per_pixel > 32)
510 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
511 dib_info.compression=ReadBlobLSBLong(image);
512 dib_info.image_size=ReadBlobLSBLong(image);
513 dib_info.x_pixels=ReadBlobLSBLong(image);
514 dib_info.y_pixels=ReadBlobLSBLong(image);
515 dib_info.number_colors=ReadBlobLSBLong(image);
516 dib_info.colors_important=ReadBlobLSBLong(image);
517 if ((dib_info.bits_per_pixel != 1) && (dib_info.bits_per_pixel != 4) &&
518 (dib_info.bits_per_pixel != 8) && (dib_info.bits_per_pixel != 16) &&
519 (dib_info.bits_per_pixel != 24) && (dib_info.bits_per_pixel != 32))
520 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
521 if ((dib_info.compression == BI_BITFIELDS) &&
522 ((dib_info.bits_per_pixel == 16) || (dib_info.bits_per_pixel == 32)))
523 {
524 dib_info.red_mask=ReadBlobLSBLong(image);
525 dib_info.green_mask=ReadBlobLSBLong(image);
526 dib_info.blue_mask=ReadBlobLSBLong(image);
527 }
528 if (EOFBlob(image) != MagickFalse)
529 ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
530 if (dib_info.width <= 0)
531 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
532 if (dib_info.height == 0)
533 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
534 if (dib_info.planes != 1)
535 ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne");
536 if ((dib_info.bits_per_pixel != 1) && (dib_info.bits_per_pixel != 4) &&
537 (dib_info.bits_per_pixel != 8) && (dib_info.bits_per_pixel != 16) &&
538 (dib_info.bits_per_pixel != 24) && (dib_info.bits_per_pixel != 32))
539 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
540 if (dib_info.bits_per_pixel < 16 &&
541 dib_info.number_colors > (size_t) (1UL << dib_info.bits_per_pixel))
542 ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors");
543 if ((dib_info.compression == 1) && (dib_info.bits_per_pixel != 8))
544 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
545 if ((dib_info.compression == 2) && (dib_info.bits_per_pixel != 4))
546 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
547 if ((dib_info.compression == 3) && (dib_info.bits_per_pixel < 16))
548 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
549 switch (dib_info.compression)
550 {
551 case BI_RGB:
552 case BI_RLE8:
553 case BI_RLE4:
554 case BI_BITFIELDS:
555 break;
556 case BI_JPEG:
557 ThrowReaderException(CoderError,"JPEGCompressNotSupported");
558 case BI_PNG:
559 ThrowReaderException(CoderError,"PNGCompressNotSupported");
560 default:
561 ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
562 }
563 image->columns=(size_t) MagickAbsoluteValue(dib_info.width);
564 image->rows=(size_t) MagickAbsoluteValue(dib_info.height);
565 image->depth=8;
566 image->alpha_trait=dib_info.bits_per_pixel == 32 ? BlendPixelTrait :
567 UndefinedPixelTrait;
568 if ((dib_info.number_colors > 256) || (dib_info.colors_important > 256))
569 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
570 if ((dib_info.number_colors != 0) || (dib_info.bits_per_pixel < 16))
571 {
572 size_t
573 one;
574
575 image->storage_class=PseudoClass;
576 image->colors=dib_info.number_colors;
577 one=1;
578 if (image->colors == 0)
579 image->colors=one << dib_info.bits_per_pixel;
580 }
581 if (image_info->size)
582 {
583 RectangleInfo
584 geometry;
585
586 MagickStatusType
587 flags;
588
589 flags=ParseAbsoluteGeometry(image_info->size,&geometry);
590 if (flags & WidthValue)
591 if ((geometry.width != 0) && (geometry.width < image->columns))
592 image->columns=geometry.width;
593 if (flags & HeightValue)
594 if ((geometry.height != 0) && (geometry.height < image->rows))
595 image->rows=geometry.height;
596 }
597 status=SetImageExtent(image,image->columns,image->rows,exception);
598 if (status == MagickFalse)
599 return(DestroyImageList(image));
600 if (image->storage_class == PseudoClass)
601 {
602 size_t
603 length,
604 packet_size;
605
606 unsigned char
607 *dib_colormap;
608
609 /*
610 Read DIB raster colormap.
611 */
612 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
613 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
614 length=(size_t) image->colors;
615 dib_colormap=(unsigned char *) AcquireQuantumMemory(length,
616 4*sizeof(*dib_colormap));
617 if (dib_colormap == (unsigned char *) NULL)
618 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
619 packet_size=4;
620 count=ReadBlob(image,packet_size*image->colors,dib_colormap);
621 if (count != (ssize_t) (packet_size*image->colors))
622 ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
623 p=dib_colormap;
624 for (i=0; i < (ssize_t) image->colors; i++)
625 {
626 image->colormap[i].blue=ScaleCharToQuantum(*p++);
627 image->colormap[i].green=ScaleCharToQuantum(*p++);
628 image->colormap[i].red=ScaleCharToQuantum(*p++);
629 if (packet_size == 4)
630 p++;
631 }
632 dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
633 }
634 /*
635 Read image data.
636 */
637 if (dib_info.compression == BI_RLE4)
638 dib_info.bits_per_pixel<<=1;
639 bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
640 length=bytes_per_line*image->rows;
641 pixel_info=AcquireVirtualMemory((size_t) image->rows,MagickMax(
642 bytes_per_line,image->columns+256UL)*sizeof(*pixels));
643 if (pixel_info == (MemoryInfo *) NULL)
644 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
645 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
646 if ((dib_info.compression == BI_RGB) ||
647 (dib_info.compression == BI_BITFIELDS))
648 {
649 count=ReadBlob(image,length,pixels);
650 if (count != (ssize_t) (length))
651 ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
652 }
653 else
654 {
655 /*
656 Convert run-length encoded raster pixels.
657 */
658 status=DecodeImage(image,dib_info.compression ? MagickTrue : MagickFalse,
659 pixels);
660 if (status == MagickFalse)
661 ThrowReaderException(CorruptImageError,"UnableToRunlengthDecodeImage");
662 }
663 /*
664 Initialize image structure.
665 */
666 image->units=PixelsPerCentimeterResolution;
667 image->resolution.x=(double) dib_info.x_pixels/100.0;
668 image->resolution.y=(double) dib_info.y_pixels/100.0;
669 /*
670 Convert DIB raster image to pixel packets.
671 */
672 switch (dib_info.bits_per_pixel)
673 {
674 case 1:
675 {
676 /*
677 Convert bitmap scanline.
678 */
679 for (y=(ssize_t) image->rows-1; y >= 0; y--)
680 {
681 p=pixels+(image->rows-y-1)*bytes_per_line;
682 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
683 if (q == (Quantum *) NULL)
684 break;
685 for (x=0; x < ((ssize_t) image->columns-7); x+=8)
686 {
687 for (bit=0; bit < 8; bit++)
688 {
689 index=(Quantum) ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
690 SetPixelIndex(image,index,q);
691 q+=GetPixelChannels(image);
692 }
693 p++;
694 }
695 if ((image->columns % 8) != 0)
696 {
697 for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
698 {
699 index=(Quantum) ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
700 SetPixelIndex(image,index,q);
701 q+=GetPixelChannels(image);
702 }
703 p++;
704 }
705 if (SyncAuthenticPixels(image,exception) == MagickFalse)
706 break;
707 if (image->previous == (Image *) NULL)
708 {
709 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
710 image->rows);
711 if (status == MagickFalse)
712 break;
713 }
714 }
715 (void) SyncImage(image,exception);
716 break;
717 }
718 case 4:
719 {
720 /*
721 Convert PseudoColor scanline.
722 */
723 for (y=(ssize_t) image->rows-1; y >= 0; y--)
724 {
725 p=pixels+(image->rows-y-1)*bytes_per_line;
726 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
727 if (q == (Quantum *) NULL)
728 break;
729 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
730 {
731 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);
732 SetPixelIndex(image,index,q);
733 q+=GetPixelChannels(image);
734 index=ConstrainColormapIndex(image,*p & 0xf,exception);
735 SetPixelIndex(image,index,q);
736 p++;
737 q+=GetPixelChannels(image);
738 }
739 if ((image->columns % 2) != 0)
740 {
741 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);
742 SetPixelIndex(image,index,q);
743 q+=GetPixelChannels(image);
744 p++;
745 }
746 if (SyncAuthenticPixels(image,exception) == MagickFalse)
747 break;
748 if (image->previous == (Image *) NULL)
749 {
750 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
751 image->rows);
752 if (status == MagickFalse)
753 break;
754 }
755 }
756 (void) SyncImage(image,exception);
757 break;
758 }
759 case 8:
760 {
761 /*
762 Convert PseudoColor scanline.
763 */
764 if ((dib_info.compression == BI_RLE8) ||
765 (dib_info.compression == BI_RLE4))
766 bytes_per_line=image->columns;
767 for (y=(ssize_t) image->rows-1; y >= 0; y--)
768 {
769 p=pixels+(image->rows-y-1)*bytes_per_line;
770 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
771 if (q == (Quantum *) NULL)
772 break;
773 for (x=0; x < (ssize_t) image->columns; x++)
774 {
775 index=ConstrainColormapIndex(image,*p,exception);
776 SetPixelIndex(image,index,q);
777 p++;
778 q+=GetPixelChannels(image);
779 }
780 if (SyncAuthenticPixels(image,exception) == MagickFalse)
781 break;
782 if (image->previous == (Image *) NULL)
783 {
784 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
785 image->rows);
786 if (status == MagickFalse)
787 break;
788 }
789 }
790 (void) SyncImage(image,exception);
791 break;
792 }
793 case 16:
794 {
795 unsigned short
796 word;
797
798 /*
799 Convert PseudoColor scanline.
800 */
801 image->storage_class=DirectClass;
802 if (dib_info.compression == BI_RLE8)
803 bytes_per_line=2*image->columns;
804 for (y=(ssize_t) image->rows-1; y >= 0; y--)
805 {
806 p=pixels+(image->rows-y-1)*bytes_per_line;
807 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
808 if (q == (Quantum *) NULL)
809 break;
810 for (x=0; x < (ssize_t) image->columns; x++)
811 {
812 word=(*p++);
813 word|=(*p++ << 8);
814 if (dib_info.red_mask == 0)
815 {
816 SetPixelRed(image,ScaleCharToQuantum(ScaleColor5to8(
817 (unsigned char) ((word >> 10) & 0x1f))),q);
818 SetPixelGreen(image,ScaleCharToQuantum(ScaleColor5to8(
819 (unsigned char) ((word >> 5) & 0x1f))),q);
820 SetPixelBlue(image,ScaleCharToQuantum(ScaleColor5to8(
821 (unsigned char) (word & 0x1f))),q);
822 }
823 else
824 {
825 SetPixelRed(image,ScaleCharToQuantum(ScaleColor5to8(
826 (unsigned char) ((word >> 11) & 0x1f))),q);
827 SetPixelGreen(image,ScaleCharToQuantum(ScaleColor6to8(
828 (unsigned char) ((word >> 5) & 0x3f))),q);
829 SetPixelBlue(image,ScaleCharToQuantum(ScaleColor5to8(
830 (unsigned char) (word & 0x1f))),q);
831 }
832 q+=GetPixelChannels(image);
833 }
834 if (SyncAuthenticPixels(image,exception) == MagickFalse)
835 break;
836 if (image->previous == (Image *) NULL)
837 {
838 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
839 image->rows);
840 if (status == MagickFalse)
841 break;
842 }
843 }
844 break;
845 }
846 case 24:
847 case 32:
848 {
849 /*
850 Convert DirectColor scanline.
851 */
852 for (y=(ssize_t) image->rows-1; y >= 0; y--)
853 {
854 p=pixels+(image->rows-y-1)*bytes_per_line;
855 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
856 if (q == (Quantum *) NULL)
857 break;
858 for (x=0; x < (ssize_t) image->columns; x++)
859 {
860 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
861 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
862 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
863 if (image->alpha_trait != UndefinedPixelTrait)
864 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
865 q+=GetPixelChannels(image);
866 }
867 if (SyncAuthenticPixels(image,exception) == MagickFalse)
868 break;
869 if (image->previous == (Image *) NULL)
870 {
871 status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
872 image->rows);
873 if (status == MagickFalse)
874 break;
875 }
876 }
877 break;
878 }
879 default:
880 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
881 }
882 pixel_info=RelinquishVirtualMemory(pixel_info);
883 if (EOFBlob(image) != MagickFalse)
884 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
885 image->filename);
886 if (dib_info.height < 0)
887 {
888 Image
889 *flipped_image;
890
891 /*
892 Correct image orientation.
893 */
894 flipped_image=FlipImage(image,exception);
895 if (flipped_image != (Image *) NULL)
896 {
897 DuplicateBlob(flipped_image,image);
898 image=DestroyImage(image);
899 image=flipped_image;
900 }
901 }
902 (void) CloseBlob(image);
903 return(GetFirstImageInList(image));
904 }
905
906 /*
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 % %
909 % %
910 % %
911 % R e g i s t e r D I B I m a g e %
912 % %
913 % %
914 % %
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916 %
917 % RegisterDIBImage() adds attributes for the DIB image format to
918 % the list of supported formats. The attributes include the image format
919 % tag, a method to read and/or write the format, whether the format
920 % supports the saving of more than one frame to the same file or blob,
921 % whether the format supports native in-memory I/O, and a brief
922 % description of the format.
923 %
924 % The format of the RegisterDIBImage method is:
925 %
926 % size_t RegisterDIBImage(void)
927 %
928 */
RegisterDIBImage(void)929 ModuleExport size_t RegisterDIBImage(void)
930 {
931 MagickInfo
932 *entry;
933
934 entry=AcquireMagickInfo("DIB","DIB",
935 "Microsoft Windows 3.X Packed Device-Independent Bitmap");
936 entry->decoder=(DecodeImageHandler *) ReadDIBImage;
937 entry->encoder=(EncodeImageHandler *) WriteDIBImage;
938 entry->magick=(IsImageFormatHandler *) IsDIB;
939 entry->flags^=CoderAdjoinFlag;
940 entry->flags|=CoderStealthFlag;
941 (void) RegisterMagickInfo(entry);
942 return(MagickImageCoderSignature);
943 }
944
945 /*
946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
947 % %
948 % %
949 % %
950 % U n r e g i s t e r D I B I m a g e %
951 % %
952 % %
953 % %
954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 %
956 % UnregisterDIBImage() removes format registrations made by the
957 % DIB module from the list of supported formats.
958 %
959 % The format of the UnregisterDIBImage method is:
960 %
961 % UnregisterDIBImage(void)
962 %
963 */
UnregisterDIBImage(void)964 ModuleExport void UnregisterDIBImage(void)
965 {
966 (void) UnregisterMagickInfo("DIB");
967 }
968
969 /*
970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 % %
972 % %
973 % %
974 % W r i t e D I B I m a g e %
975 % %
976 % %
977 % %
978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979 %
980 % WriteDIBImage() writes an image in Microsoft Windows bitmap encoded
981 % image format.
982 %
983 % The format of the WriteDIBImage method is:
984 %
985 % MagickBooleanType WriteDIBImage(const ImageInfo *image_info,
986 % Image *image,ExceptionInfo *exception)
987 %
988 % A description of each parameter follows.
989 %
990 % o image_info: the image info.
991 %
992 % o image: The image.
993 %
994 % o exception: return any errors or warnings in this structure.
995 %
996 */
WriteDIBImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)997 static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image,
998 ExceptionInfo *exception)
999 {
1000 DIBInfo
1001 dib_info;
1002
1003 MagickBooleanType
1004 status;
1005
1006 register const Quantum
1007 *p;
1008
1009 register ssize_t
1010 i,
1011 x;
1012
1013 register unsigned char
1014 *q;
1015
1016 size_t
1017 bytes_per_line;
1018
1019 ssize_t
1020 y;
1021
1022 unsigned char
1023 *dib_data,
1024 *pixels;
1025
1026 /*
1027 Open output image file.
1028 */
1029 assert(image_info != (const ImageInfo *) NULL);
1030 assert(image_info->signature == MagickCoreSignature);
1031 assert(image != (Image *) NULL);
1032 assert(image->signature == MagickCoreSignature);
1033 if (image->debug != MagickFalse)
1034 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1035 assert(exception != (ExceptionInfo *) NULL);
1036 assert(exception->signature == MagickCoreSignature);
1037 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1038 if (status == MagickFalse)
1039 return(status);
1040 /*
1041 Initialize DIB raster file header.
1042 */
1043 (void) TransformImageColorspace(image,sRGBColorspace,exception);
1044 if (image->storage_class == DirectClass)
1045 {
1046 /*
1047 Full color DIB raster.
1048 */
1049 dib_info.number_colors=0;
1050 dib_info.bits_per_pixel=(unsigned short) (image->alpha_trait ? 32 : 24);
1051 }
1052 else
1053 {
1054 /*
1055 Colormapped DIB raster.
1056 */
1057 dib_info.bits_per_pixel=8;
1058 if (image_info->depth > 8)
1059 dib_info.bits_per_pixel=16;
1060 if (SetImageMonochrome(image,exception) != MagickFalse)
1061 dib_info.bits_per_pixel=1;
1062 dib_info.number_colors=(dib_info.bits_per_pixel == 16) ? 0 :
1063 (1UL << dib_info.bits_per_pixel);
1064 }
1065 bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
1066 dib_info.size=40;
1067 dib_info.width=(ssize_t) image->columns;
1068 dib_info.height=(ssize_t) image->rows;
1069 dib_info.planes=1;
1070 dib_info.compression=(size_t) (dib_info.bits_per_pixel == 16 ?
1071 BI_BITFIELDS : BI_RGB);
1072 dib_info.image_size=bytes_per_line*image->rows;
1073 dib_info.x_pixels=75*39;
1074 dib_info.y_pixels=75*39;
1075 switch (image->units)
1076 {
1077 case UndefinedResolution:
1078 case PixelsPerInchResolution:
1079 {
1080 dib_info.x_pixels=(size_t) (100.0*image->resolution.x/2.54);
1081 dib_info.y_pixels=(size_t) (100.0*image->resolution.y/2.54);
1082 break;
1083 }
1084 case PixelsPerCentimeterResolution:
1085 {
1086 dib_info.x_pixels=(size_t) (100.0*image->resolution.x);
1087 dib_info.y_pixels=(size_t) (100.0*image->resolution.y);
1088 break;
1089 }
1090 }
1091 dib_info.colors_important=dib_info.number_colors;
1092 /*
1093 Convert MIFF to DIB raster pixels.
1094 */
1095 pixels=(unsigned char *) AcquireQuantumMemory(dib_info.image_size,
1096 sizeof(*pixels));
1097 if (pixels == (unsigned char *) NULL)
1098 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1099 (void) ResetMagickMemory(pixels,0,dib_info.image_size);
1100 switch (dib_info.bits_per_pixel)
1101 {
1102 case 1:
1103 {
1104 register unsigned char
1105 bit,
1106 byte;
1107
1108 /*
1109 Convert PseudoClass image to a DIB monochrome image.
1110 */
1111 for (y=0; y < (ssize_t) image->rows; y++)
1112 {
1113 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1114 if (p == (const Quantum *) NULL)
1115 break;
1116 q=pixels+(image->rows-y-1)*bytes_per_line;
1117 bit=0;
1118 byte=0;
1119 for (x=0; x < (ssize_t) image->columns; x++)
1120 {
1121 byte<<=1;
1122 byte|=GetPixelIndex(image,p) != 0 ? 0x01 : 0x00;
1123 bit++;
1124 if (bit == 8)
1125 {
1126 *q++=byte;
1127 bit=0;
1128 byte=0;
1129 }
1130 p+=GetPixelChannels(image);
1131 }
1132 if (bit != 0)
1133 {
1134 *q++=(unsigned char) (byte << (8-bit));
1135 x++;
1136 }
1137 for (x=(ssize_t) (image->columns+7)/8; x < (ssize_t) bytes_per_line; x++)
1138 *q++=0x00;
1139 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1140 image->rows);
1141 if (status == MagickFalse)
1142 break;
1143 }
1144 break;
1145 }
1146 case 8:
1147 {
1148 /*
1149 Convert PseudoClass packet to DIB pixel.
1150 */
1151 for (y=0; y < (ssize_t) image->rows; y++)
1152 {
1153 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1154 if (p == (const Quantum *) NULL)
1155 break;
1156 q=pixels+(image->rows-y-1)*bytes_per_line;
1157 for (x=0; x < (ssize_t) image->columns; x++)
1158 {
1159 *q++=(unsigned char) GetPixelIndex(image,p);
1160 p+=GetPixelChannels(image);
1161 }
1162 for ( ; x < (ssize_t) bytes_per_line; x++)
1163 *q++=0x00;
1164 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1165 image->rows);
1166 if (status == MagickFalse)
1167 break;
1168 }
1169 break;
1170 }
1171 case 16:
1172 {
1173 unsigned short
1174 word;
1175 /*
1176 Convert PseudoClass packet to DIB pixel.
1177 */
1178 for (y=0; y < (ssize_t) image->rows; y++)
1179 {
1180 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1181 if (p == (const Quantum *) NULL)
1182 break;
1183 q=pixels+(image->rows-y-1)*bytes_per_line;
1184 for (x=0; x < (ssize_t) image->columns; x++)
1185 {
1186 word=(unsigned short) ((ScaleColor8to5((unsigned char)
1187 ScaleQuantumToChar(GetPixelRed(image,p))) << 11) | (ScaleColor8to6(
1188 (unsigned char) ScaleQuantumToChar(GetPixelGreen(image,p))) << 5) |
1189 (ScaleColor8to5((unsigned char) ScaleQuantumToChar((unsigned char)
1190 GetPixelBlue(image,p)) << 0)));
1191 *q++=(unsigned char)(word & 0xff);
1192 *q++=(unsigned char)(word >> 8);
1193 p+=GetPixelChannels(image);
1194 }
1195 for (x=(ssize_t) (2*image->columns); x < (ssize_t) bytes_per_line; x++)
1196 *q++=0x00;
1197 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1198 image->rows);
1199 if (status == MagickFalse)
1200 break;
1201 }
1202 break;
1203 }
1204 case 24:
1205 case 32:
1206 {
1207 /*
1208 Convert DirectClass packet to DIB RGB pixel.
1209 */
1210 for (y=0; y < (ssize_t) image->rows; y++)
1211 {
1212 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1213 if (p == (const Quantum *) NULL)
1214 break;
1215 q=pixels+(image->rows-y-1)*bytes_per_line;
1216 for (x=0; x < (ssize_t) image->columns; x++)
1217 {
1218 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1219 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1220 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1221 if (image->alpha_trait != UndefinedPixelTrait)
1222 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
1223 p+=GetPixelChannels(image);
1224 }
1225 if (dib_info.bits_per_pixel == 24)
1226 for (x=(ssize_t) (3*image->columns); x < (ssize_t) bytes_per_line; x++)
1227 *q++=0x00;
1228 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1229 image->rows);
1230 if (status == MagickFalse)
1231 break;
1232 }
1233 break;
1234 }
1235 }
1236 if (dib_info.bits_per_pixel == 8)
1237 if (image_info->compression != NoCompression)
1238 {
1239 size_t
1240 length;
1241
1242 /*
1243 Convert run-length encoded raster pixels.
1244 */
1245 length=2UL*(bytes_per_line+2UL)+2UL;
1246 dib_data=(unsigned char *) AcquireQuantumMemory(length,
1247 (image->rows+2UL)*sizeof(*dib_data));
1248 if (dib_data == (unsigned char *) NULL)
1249 {
1250 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1251 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1252 }
1253 dib_info.image_size=(size_t) EncodeImage(image,bytes_per_line,
1254 pixels,dib_data);
1255 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1256 pixels=dib_data;
1257 dib_info.compression = BI_RLE8;
1258 }
1259 /*
1260 Write DIB header.
1261 */
1262 (void) WriteBlobLSBLong(image,(unsigned int) dib_info.size);
1263 (void) WriteBlobLSBLong(image,dib_info.width);
1264 (void) WriteBlobLSBLong(image,(unsigned short) dib_info.height);
1265 (void) WriteBlobLSBShort(image,(unsigned short) dib_info.planes);
1266 (void) WriteBlobLSBShort(image,dib_info.bits_per_pixel);
1267 (void) WriteBlobLSBLong(image,(unsigned int) dib_info.compression);
1268 (void) WriteBlobLSBLong(image,(unsigned int) dib_info.image_size);
1269 (void) WriteBlobLSBLong(image,(unsigned int) dib_info.x_pixels);
1270 (void) WriteBlobLSBLong(image,(unsigned int) dib_info.y_pixels);
1271 (void) WriteBlobLSBLong(image,(unsigned int) dib_info.number_colors);
1272 (void) WriteBlobLSBLong(image,(unsigned int) dib_info.colors_important);
1273 if (image->storage_class == PseudoClass)
1274 {
1275 if (dib_info.bits_per_pixel <= 8)
1276 {
1277 unsigned char
1278 *dib_colormap;
1279
1280 /*
1281 Dump colormap to file.
1282 */
1283 dib_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
1284 (1UL << dib_info.bits_per_pixel),4*sizeof(*dib_colormap));
1285 if (dib_colormap == (unsigned char *) NULL)
1286 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1287 q=dib_colormap;
1288 for (i=0; i < (ssize_t) MagickMin(image->colors,dib_info.number_colors); i++)
1289 {
1290 *q++=ScaleQuantumToChar(image->colormap[i].blue);
1291 *q++=ScaleQuantumToChar(image->colormap[i].green);
1292 *q++=ScaleQuantumToChar(image->colormap[i].red);
1293 *q++=(Quantum) 0x0;
1294 }
1295 for ( ; i < (ssize_t) (1L << dib_info.bits_per_pixel); i++)
1296 {
1297 *q++=(Quantum) 0x0;
1298 *q++=(Quantum) 0x0;
1299 *q++=(Quantum) 0x0;
1300 *q++=(Quantum) 0x0;
1301 }
1302 (void) WriteBlob(image,(size_t) (4*(1 << dib_info.bits_per_pixel)),
1303 dib_colormap);
1304 dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
1305 }
1306 else
1307 if ((dib_info.bits_per_pixel == 16) &&
1308 (dib_info.compression == BI_BITFIELDS))
1309 {
1310 (void) WriteBlobLSBLong(image,0xf800);
1311 (void) WriteBlobLSBLong(image,0x07e0);
1312 (void) WriteBlobLSBLong(image,0x001f);
1313 }
1314 }
1315 (void) WriteBlob(image,dib_info.image_size,pixels);
1316 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1317 (void) CloseBlob(image);
1318 return(MagickTrue);
1319 }
1320