root/ImageMagick/trunk/coders/dib.c

Revision 137, 39.4 KB (checked in by cristy, 2 months ago)
Line 
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%                                John Cristy                                  %
17%                                 July 1992                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2009 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 "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/blob-private.h"
45#include "magick/cache.h"
46#include "magick/color.h"
47#include "magick/colormap-private.h"
48#include "magick/color-private.h"
49#include "magick/colorspace.h"
50#include "magick/draw.h"
51#include "magick/exception.h"
52#include "magick/exception-private.h"
53#include "magick/geometry.h"
54#include "magick/image.h"
55#include "magick/image-private.h"
56#include "magick/list.h"
57#include "magick/log.h"
58#include "magick/magick.h"
59#include "magick/memory_.h"
60#include "magick/monitor.h"
61#include "magick/monitor-private.h"
62#include "magick/quantum-private.h"
63#include "magick/static.h"
64#include "magick/string_.h"
65#include "magick/module.h"
66#include "magick/transform.h"
67
68/*
69  Typedef declarations.
70*/
71typedef struct _DIBInfo
72{
73  unsigned long
74    size;
75
76  long
77    width,
78    height;
79
80  unsigned short
81    planes,
82    bits_per_pixel;
83
84  unsigned long
85    compression,
86    image_size,
87    x_pixels,
88    y_pixels,
89    number_colors,
90    red_mask,
91    green_mask,
92    blue_mask,
93    alpha_mask,
94    colors_important;
95
96  long
97    colorspace;
98
99  PointInfo
100    red_primary,
101    green_primary,
102    blue_primary,
103    gamma_scale;
104} DIBInfo;
105
106/*
107  Forward declarations.
108*/
109static MagickBooleanType
110  WriteDIBImage(const ImageInfo *,Image *);
111
112/*
113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114%                                                                             %
115%                                                                             %
116%                                                                             %
117%   D e c o d e I m a g e                                                     %
118%                                                                             %
119%                                                                             %
120%                                                                             %
121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122%
123%  DecodeImage unpacks the packed image pixels into runlength-encoded
124%  pixel packets.
125%
126%  The format of the DecodeImage method is:
127%
128%      MagickBooleanType DecodeImage(Image *image,
129%        const MagickBooleanType compression,unsigned char *pixels)
130%
131%  A description of each parameter follows:
132%
133%    o image: the address of a structure of type Image.
134%
135%    o compression:  A value of 1 means the compressed pixels are runlength
136%      encoded for a 256-color bitmap.  A value of 2 means a 16-color bitmap.
137%
138%    o pixels:  The address of a byte (8 bits) array of pixel data created by
139%      the decoding process.
140%
141*/
142
143static inline size_t MagickMin(const size_t x,const size_t y)
144{
145  if (x < y)
146    return(x);
147  return(y);
148}
149
150static MagickBooleanType DecodeImage(Image *image,
151  const MagickBooleanType compression,unsigned char *pixels)
152{
153#if !defined(__WINDOWS__) || defined(__MINGW32__)
154#define BI_RGB  0
155#define BI_RLE8  1
156#define BI_RLE4  2
157#define BI_BITFIELDS  3
158#endif
159
160  int
161    count;
162
163  long
164    y;
165
166  register long
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 == MagickSignature);
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 < (long) 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 unsigned long 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*/
318static size_t EncodeImage(Image *image,const unsigned long bytes_per_line,
319  const unsigned char *pixels,unsigned char *compressed_pixels)
320{
321  long
322    y;
323
324  register const unsigned char
325    *p;
326
327  register long
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 == MagickSignature);
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 < (long) image->rows; y++)
347  {
348    for (x=0; x < (long) bytes_per_line; x+=i)
349    {
350      /*
351        Determine runlength.
352      */
353      for (i=1; ((x+i) < (long) 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*/
401static 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*/
436
437static inline long MagickAbsoluteValue(const long x)
438{
439  if (x < 0)
440    return(-x);
441  return(x);
442}
443
444static inline size_t MagickMax(const size_t x,const size_t y)
445{
446  if (x > y)
447    return(x);
448  return(y);
449}
450
451static Image *ReadDIBImage(const ImageInfo *image_info,ExceptionInfo *exception)
452{
453  DIBInfo
454    dib_info;
455
456  Image
457    *image;
458
459  IndexPacket
460    index;
461
462  long
463    bit,
464    y;
465
466  MagickBooleanType
467    status;
468
469  register IndexPacket
470    *indexes;
471
472  register long
473    x;
474
475  register PixelPacket
476    *q;
477
478  register long
479    i;
480
481  register unsigned char
482    *p;
483
484  size_t
485    length;
486
487  ssize_t
488    count;
489
490  unsigned char
491    *pixels;
492
493  unsigned long
494    bytes_per_line;
495
496  /*
497    Open image file.
498  */
499  assert(image_info != (const ImageInfo *) NULL);
500  assert(image_info->signature == MagickSignature);
501  if (image_info->debug != MagickFalse)
502    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
503      image_info->filename);
504  assert(exception != (ExceptionInfo *) NULL);
505  assert(exception->signature == MagickSignature);
506  image=AcquireImage(image_info);
507  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
508  if (status == MagickFalse)
509    {
510      image=DestroyImageList(image);
511      return((Image *) NULL);
512    }
513  /*
514    Determine if this a DIB file.
515  */
516  (void) ResetMagickMemory(&dib_info,0,sizeof(dib_info));
517  dib_info.size=ReadBlobLSBLong(image);
518  if (dib_info.size!=40)
519    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
520  /*
521    Microsoft Windows 3.X DIB image file.
522  */
523  dib_info.width=(short) ReadBlobLSBLong(image);
524  dib_info.height=(short) ReadBlobLSBLong(image);
525  dib_info.planes=ReadBlobLSBShort(image);
526  dib_info.bits_per_pixel=ReadBlobLSBShort(image);
527  dib_info.compression=ReadBlobLSBLong(image);
528  dib_info.image_size=ReadBlobLSBLong(image);
529  dib_info.x_pixels=ReadBlobLSBLong(image);
530  dib_info.y_pixels=ReadBlobLSBLong(image);
531  dib_info.number_colors=ReadBlobLSBLong(image);
532  dib_info.colors_important=ReadBlobLSBLong(image);
533  if ((dib_info.compression == BI_BITFIELDS) &&
534      ((dib_info.bits_per_pixel == 16) || (dib_info.bits_per_pixel == 32)))
535    {
536      dib_info.red_mask=ReadBlobLSBLong(image);
537      dib_info.green_mask=ReadBlobLSBLong(image);
538      dib_info.blue_mask=ReadBlobLSBLong(image);
539    }
540  image->matte=dib_info.bits_per_pixel == 32 ? MagickTrue : MagickFalse;
541  image->columns=(unsigned long) MagickAbsoluteValue(dib_info.width);
542  image->rows=(unsigned long) MagickAbsoluteValue(dib_info.height);
543  image->depth=8;
544  if ((dib_info.number_colors != 0) || (dib_info.bits_per_pixel < 16))
545    {
546      image->storage_class=PseudoClass;
547      image->colors=dib_info.number_colors;
548      if (image->colors == 0)
549        image->colors=1L << dib_info.bits_per_pixel;
550    }
551  if (image_info->size)
552    {
553      RectangleInfo
554        geometry;
555
556      MagickStatusType
557        flags;
558
559      flags=ParseAbsoluteGeometry(image_info->size,&geometry);
560      if (flags & WidthValue)
561        if ((geometry.width != 0) && (geometry.width < image->columns))
562          image->columns=geometry.width;
563      if (flags & HeightValue)
564        if ((geometry.height != 0) && (geometry.height < image->rows))
565          image->rows=geometry.height;
566    }
567  if (image->storage_class == PseudoClass)
568    {
569      size_t
570        length,
571        packet_size;
572
573      unsigned char
574        *dib_colormap;
575
576      /*
577        Read DIB raster colormap.
578      */
579      if (AcquireImageColormap(image,image->colors) == MagickFalse)
580        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
581      length=(size_t) image->colors;
582      dib_colormap=(unsigned char *) AcquireQuantumMemory(length,
583        4*sizeof(*dib_colormap));
584      if (dib_colormap == (unsigned char *) NULL)
585        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
586      packet_size=4;
587      count=ReadBlob(image,packet_size*image->colors,dib_colormap);
588      if (count != (ssize_t) (packet_size*image->colors))
589        ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
590      p=dib_colormap;
591      for (i=0; i < (long) image->colors; i++)
592      {
593        image->colormap[i].blue=ScaleCharToQuantum(*p++);
594        image->colormap[i].green=ScaleCharToQuantum(*p++);
595        image->colormap[i].red=ScaleCharToQuantum(*p++);
596        if (packet_size == 4)
597          p++;
598      }
599      dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
600    }
601  /*
602    Read image data.
603  */
604  if (dib_info.compression == BI_RLE4)
605    dib_info.bits_per_pixel<<=1;
606  bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
607  length=bytes_per_line*image->rows;
608  pixels=(unsigned char *) AcquireQuantumMemory((size_t) image->rows,
609    MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));
610  if (pixels == (unsigned char *) NULL)
611    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
612  if ((dib_info.compression == BI_RGB) ||
613      (dib_info.compression == BI_BITFIELDS))
614    {
615      count=ReadBlob(image,length,pixels);
616      if (count != (ssize_t) (length))
617        ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
618    }
619  else
620    {
621      /*
622        Convert run-length encoded raster pixels.
623      */
624      status=DecodeImage(image,dib_info.compression ? MagickTrue : MagickFalse,
625        pixels);
626      if (status == MagickFalse)
627        ThrowReaderException(CorruptImageError,"UnableToRunlengthDecodeImage");
628    }
629  /*
630    Initialize image structure.
631  */
632  image->units=PixelsPerCentimeterResolution;
633  image->x_resolution=(double) dib_info.x_pixels/100.0;
634  image->y_resolution=(double) dib_info.y_pixels/100.0;
635  /*
636    Convert DIB raster image to pixel packets.
637  */
638  switch (dib_info.bits_per_pixel)
639  {
640    case 1:
641    {
642      /*
643        Convert bitmap scanline.
644      */
645      for (y=(long) image->rows-1; y >= 0; y--)
646      {
647        p=pixels+(image->rows-y-1)*bytes_per_line;
648        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
649        if (q == (PixelPacket *) NULL)
650          break;
651        indexes=GetAuthenticIndexQueue(image);
652        for (x=0; x < ((long) image->columns-7); x+=8)
653        {
654          for (bit=0; bit < 8; bit++)
655          {
656            index=(IndexPacket) ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
657            indexes[x+bit]=index;
658            *q++=image->colormap[(long) index];
659          }
660          p++;
661        }
662        if ((image->columns % 8) != 0)
663          {
664            for (bit=0; bit < (long) (image->columns % 8); bit++)
665            {
666              index=(IndexPacket) ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
667              indexes[x+bit]=index;
668              *q++=image->colormap[(long) index];
669            }
670            p++;
671          }
672        if (SyncAuthenticPixels(image,exception) == MagickFalse)
673          break;
674        if (image->previous == (Image *) NULL)
675          {
676            status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
677              image->rows);
678            if (status == MagickFalse)
679              break;
680          }
681      }
682      break;
683    }
684    case 4:
685    {
686      /*
687        Convert PseudoColor scanline.
688      */
689      for (y=(long) image->rows-1; y >= 0; y--)
690      {
691        p=pixels+(image->rows-y-1)*bytes_per_line;
692        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
693        if (q == (PixelPacket *) NULL)
694          break;
695        indexes=GetAuthenticIndexQueue(image);
696        for (x=0; x < ((long) image->columns-1); x+=2)
697        {
698          index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
699          indexes[x]=index;
700          *q++=image->colormap[(long) index];
701          index=ConstrainColormapIndex(image,*p & 0xf);
702          indexes[x+1]=index;
703          *q++=image->colormap[(long) index];
704          p++;
705        }
706        if ((image->columns % 2) != 0)
707          {
708            index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
709            indexes[x]=index;
710            *q++=image->colormap[(long) index];
711            p++;
712          }
713        if (SyncAuthenticPixels(image,exception) == MagickFalse)
714          break;
715        if (image->previous == (Image *) NULL)
716          {
717            status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
718              image->rows);
719            if (status == MagickFalse)
720              break;
721          }
722      }
723      break;
724    }
725    case 8:
726    {
727      /*
728        Convert PseudoColor scanline.
729      */
730      if ((dib_info.compression == BI_RLE8) ||
731          (dib_info.compression == BI_RLE4))
732        bytes_per_line=image->columns;
733      for (y=(long) image->rows-1; y >= 0; y--)
734      {
735        p=pixels+(image->rows-y-1)*bytes_per_line;
736        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
737        if (q == (PixelPacket *) NULL)
738          break;
739        indexes=GetAuthenticIndexQueue(image);
740        for (x=0; x < (long) image->columns; x++)
741        {
742          index=ConstrainColormapIndex(image,*p);
743          indexes[x]=index;
744          *q=image->colormap[(long) index];
745          p++;
746          q++;
747        }
748        if (SyncAuthenticPixels(image,exception) == MagickFalse)
749          break;
750        if (image->previous == (Image *) NULL)
751          {
752            status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
753              image->rows);
754            if (status == MagickFalse)
755              break;
756          }
757      }
758      break;
759    }
760    case 16:
761    {
762      unsigned short
763        word;
764
765      /*
766        Convert PseudoColor scanline.
767      */
768      image->storage_class=DirectClass;
769      if (dib_info.compression == BI_RLE8)
770        bytes_per_line=2*image->columns;
771      for (y=(long) image->rows-1; y >= 0; y--)
772      {
773        p=pixels+(image->rows-y-1)*bytes_per_line;
774        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
775        if (q == (PixelPacket *) NULL)
776          break;
777        for (x=0; x < (long) image->columns; x++)
778        {
779          word=(*p++);
780          word|=(*p++ << 8);
781          if (dib_info.red_mask == 0)
782            {
783              q->red=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
784                ((word >> 10) & 0x1f)));
785              q->green=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
786                ((word >> 5) & 0x1f)));
787              q->blue=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
788                (word & 0x1f)));
789            }
790          else
791            {
792              q->red=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
793                ((word >> 11) & 0x1f)));
794              q->green=ScaleCharToQuantum(ScaleColor6to8((unsigned char)
795                ((word >> 5) & 0x3f)));
796              q->blue=ScaleCharToQuantum(ScaleColor5to8((unsigned char)
797                (word & 0x1f)));
798            }
799          q++;
800        }
801        if (SyncAuthenticPixels(image,exception) == MagickFalse)
802          break;
803        if (image->previous == (Image *) NULL)
804          {
805            status=SetImageProgress(image,LoadImageTag,image->rows-y-1,
806              image->rows);
807            if (status == MagickFalse)
808              break;
809          }
810      }
811      break;
812    }
813    case 24:
814    case 32:
815    {
816      /*
817        Convert DirectColor scanline.
818      */
819      for (y=(long) image->rows-1; y >= 0; y--)
820      {
821        p=pixels+(image->rows-y-1)*bytes_per_line;
822        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
823        if (q == (PixelPacket *) NULL)
824          break;
825        for (x=0; x < (long) image->columns; x++)
826        {
827          q->blue=ScaleCharToQuantum(*p++);
828          q->green=ScaleCharToQuantum(*p++);
829          q->red=ScaleCharToQuantum(*p++);
830          if (image->matte != MagickFalse)
831            q->opacity=ScaleCharToQuantum(*p++);
832          q++;
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    default:
847      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
848  }
849  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
850  if (EOFBlob(image) != MagickFalse)
851    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
852      image->filename);
853  if (dib_info.height < 0)
854    {
855      Image
856        *flipped_image;
857
858      /*
859        Correct image orientation.
860      */
861      flipped_image=FlipImage(image,exception);
862      if (flipped_image == (Image *) NULL)
863        {
864          image=DestroyImageList(image);
865          return((Image *) NULL);
866        }
867      DuplicateBlob(flipped_image,image);
868      image=DestroyImage(image);
869      image=flipped_image;
870    }
871  (void) CloseBlob(image);
872  return(GetFirstImageInList(image));
873}
874
875/*
876%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
877%                                                                             %
878%                                                                             %
879%                                                                             %
880%   R e g i s t e r D I B I m a g e                                           %
881%                                                                             %
882%                                                                             %
883%                                                                             %
884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885%
886%  RegisterDIBImage() adds attributes for the DIB image format to
887%  the list of supported formats.  The attributes include the image format
888%  tag, a method to read and/or write the format, whether the format
889%  supports the saving of more than one frame to the same file or blob,
890%  whether the format supports native in-memory I/O, and a brief
891%  description of the format.
892%
893%  The format of the RegisterDIBImage method is:
894%
895%      unsigned long RegisterDIBImage(void)
896%
897*/
898ModuleExport unsigned long RegisterDIBImage(void)
899{
900  MagickInfo
901    *entry;
902
903  entry=SetMagickInfo("DIB");
904  entry->decoder=(DecodeImageHandler *) ReadDIBImage;
905  entry->encoder=(EncodeImageHandler *) WriteDIBImage;
906  entry->magick=(IsImageFormatHandler *) IsDIB;
907  entry->adjoin=MagickFalse;
908  entry->stealth=MagickTrue;
909  entry->description=ConstantString(
910    "Microsoft Windows 3.X Packed Device-Independent Bitmap");
911  entry->module=ConstantString("DIB");
912  (void) RegisterMagickInfo(entry);
913  return(MagickImageCoderSignature);
914}
915
916/*
917%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
918%                                                                             %
919%                                                                             %
920%                                                                             %
921%   U n r e g i s t e r D I B I m a g e                                       %
922%                                                                             %
923%                                                                             %
924%                                                                             %
925%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
926%
927%  UnregisterDIBImage() removes format registrations made by the
928%  DIB module from the list of supported formats.
929%
930%  The format of the UnregisterDIBImage method is:
931%
932%      UnregisterDIBImage(void)
933%
934*/
935ModuleExport void UnregisterDIBImage(void)
936{
937  (void) UnregisterMagickInfo("DIB");
938}
939
940/*
941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942%                                                                             %
943%                                                                             %
944%                                                                             %
945%   W r i t e D I B I m a g e                                                 %
946%                                                                             %
947%                                                                             %
948%                                                                             %
949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
950%
951%  WriteDIBImage() writes an image in Microsoft Windows bitmap encoded
952%  image format.
953%
954%  The format of the WriteDIBImage method is:
955%
956%      MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image)
957%
958%  A description of each parameter follows.
959%
960%    o image_info: the image info.
961%
962%    o image:  The image.
963%
964*/
965static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image)
966{
967  DIBInfo
968    dib_info;
969
970  long
971    y;
972
973  MagickBooleanType
974    status;
975
976  register const IndexPacket
977    *indexes;
978
979  register const PixelPacket
980    *p;
981
982  register long
983    i,
984    x;
985
986  register unsigned char
987    *q;
988
989  unsigned char
990    *dib_data,
991    *pixels;
992
993  unsigned long
994    bytes_per_line;
995
996  /*
997    Open output image file.
998  */
999  assert(image_info != (const ImageInfo *) NULL);
1000  assert(image_info->signature == MagickSignature);
1001  assert(image != (Image *) NULL);
1002  assert(image->signature == MagickSignature);
1003  if (image->debug != MagickFalse)
1004    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1005  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1006  if (status == MagickFalse)
1007    return(status);
1008  /*
1009    Initialize DIB raster file header.
1010  */
1011  if (image->colorspace != RGBColorspace)
1012    (void) TransformImageColorspace(image,RGBColorspace);
1013  if (image->storage_class == DirectClass)
1014    {
1015      /*
1016        Full color DIB raster.
1017      */
1018      dib_info.number_colors=0;
1019      dib_info.bits_per_pixel=(unsigned short) (image->matte ? 32 : 24);
1020    }
1021  else
1022    {
1023      /*
1024        Colormapped DIB raster.
1025      */
1026      dib_info.bits_per_pixel=8;
1027      if (image_info->depth > 8)
1028        dib_info.bits_per_pixel=16;
1029      if (IsMonochromeImage(image,&image->exception) != MagickFalse)
1030        dib_info.bits_per_pixel=1;
1031      dib_info.number_colors=(dib_info.bits_per_pixel == 16) ? 0 :
1032        (1UL << dib_info.bits_per_pixel);
1033    }
1034  bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
1035  dib_info.size=40;
1036  dib_info.width=(long) image->columns;
1037  dib_info.height=(long) image->rows;
1038  dib_info.planes=1;
1039  dib_info.compression=(unsigned long) (dib_info.bits_per_pixel == 16 ?
1040    BI_BITFIELDS : BI_RGB);
1041  dib_info.image_size=bytes_per_line*image->rows;
1042  dib_info.x_pixels=75*39;
1043  dib_info.y_pixels=75*39;
1044  switch (image->units)
1045  {
1046    case UndefinedResolution:
1047    case PixelsPerInchResolution:
1048    {
1049      dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution/2.54);
1050      dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution/2.54);
1051      break;
1052    }
1053    case PixelsPerCentimeterResolution:
1054    {
1055      dib_info.x_pixels=(unsigned long) (100.0*image->x_resolution);
1056      dib_info.y_pixels=(unsigned long) (100.0*image->y_resolution);
1057      break;
1058    }
1059  }
1060  dib_info.colors_important=dib_info.number_colors;
1061  /*
1062    Convert MIFF to DIB raster pixels.
1063  */
1064  pixels=(unsigned char *) AcquireQuantumMemory(dib_info.image_size,
1065    sizeof(*pixels));
1066  if (pixels == (unsigned char *) NULL)
1067    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1068  (void) ResetMagickMemory(pixels,0,dib_info.image_size);
1069  switch (dib_info.bits_per_pixel)
1070  {
1071    case 1:
1072    {
1073      register unsigned char
1074        bit,
1075        byte;
1076
1077      /*
1078        Convert PseudoClass image to a DIB monochrome image.
1079      */
1080      for (y=0; y < (long) image->rows; y++)
1081      {
1082        p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1083        if (p == (const PixelPacket *) NULL)
1084          break;
1085        indexes=GetVirtualIndexQueue(image);
1086        q=pixels+(image->rows-y-1)*bytes_per_line;
1087        bit=0;
1088        byte=0;
1089        for (x=0; x < (long) image->columns; x++)
1090        {
1091          byte<<=1;
1092          byte|=indexes[x] != 0 ? 0x01 : 0x00;
1093          bit++;
1094          if (bit == 8)
1095            {
1096              *q++=byte;
1097              bit=0;
1098              byte=0;
1099            }
1100           p++;
1101         }
1102         if (bit != 0)
1103           {
1104             *q++=(unsigned char) (byte << (8-bit));
1105             x++;
1106           }
1107        for (x=(long) (image->columns+7)/8; x < (long) bytes_per_line; x++)
1108          *q++=0x00;
1109        status=SetImageProgress(image,SaveImageTag,y,image->rows);
1110        if (status == MagickFalse)
1111          break;
1112      }
1113      break;
1114    }
1115    case 8:
1116    {
1117      /*
1118        Convert PseudoClass packet to DIB pixel.
1119      */
1120      for (y=0; y < (long) image->rows; y++)
1121      {
1122        p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1123        if (p == (const PixelPacket *) NULL)
1124          break;
1125        indexes=GetVirtualIndexQueue(image);
1126        q=pixels+(image->rows-y-1)*bytes_per_line;
1127        for (x=0; x < (long) image->columns; x++)
1128          *q++=(unsigned char) indexes[x];
1129        for ( ; x < (long) bytes_per_line; x++)
1130          *q++=0x00;
1131        status=SetImageProgress(image,SaveImageTag,y,image->rows);
1132        if (status == MagickFalse)
1133          break;
1134      }
1135      break;
1136    }
1137    case 16:
1138    {
1139      unsigned short
1140        word;
1141      /*
1142        Convert PseudoClass packet to DIB pixel.
1143      */
1144      for (y=0; y < (long) image->rows; y++)
1145      {
1146        p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1147        if (p == (const PixelPacket *) NULL)
1148          break;
1149        q=pixels+(image->rows-y-1)*bytes_per_line;
1150        for (x=0; x < (long) image->columns; x++)
1151        {
1152          word=(unsigned short) ((ScaleColor8to5((unsigned char)
1153            ScaleQuantumToChar(p->red)) << 11) | (ScaleColor8to6((unsigned char)
1154            ScaleQuantumToChar(p->green)) << 5) | (ScaleColor8to5(
1155            (unsigned char) ScaleQuantumToChar((unsigned char) p->blue) << 0)));
1156          *q++=(unsigned char)(word & 0xff);
1157          *q++=(unsigned char)(word >> 8);
1158          p++;
1159        }
1160        for (x=2L*image->columns; x < (long) bytes_per_line; x++)
1161          *q++=0x00;
1162        status=SetImageProgress(image,SaveImageTag,y,image->rows);
1163        if (status == MagickFalse)
1164          break;
1165      }
1166      break;
1167    }
1168    case 24:
1169    case 32:
1170    {
1171      /*
1172        Convert DirectClass packet to DIB RGB pixel.
1173      */
1174      for (y=0; y < (long) image->rows; y++)
1175      {
1176        p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1177        if (p == (const PixelPacket *) NULL)
1178          break;
1179        q=pixels+(image->rows-y-1)*bytes_per_line;
1180        for (x=0; x < (long) image->columns; x++)
1181        {
1182          *q++=ScaleQuantumToChar(p->blue);
1183          *q++=ScaleQuantumToChar(p->green);
1184          *q++=ScaleQuantumToChar(p->red);
1185          if (image->matte != MagickFalse)
1186            *q++=ScaleQuantumToChar(p->opacity);
1187          p++;
1188        }
1189        if (dib_info.bits_per_pixel == 24)
1190          for (x=3L*image->columns; x < (long) bytes_per_line; x++)
1191            *q++=0x00;
1192        status=SetImageProgress(image,SaveImageTag,y,image->rows);
1193        if (status == MagickFalse)
1194          break;
1195      }
1196      break;
1197    }
1198  }
1199  if (dib_info.bits_per_pixel == 8)
1200    if (image_info->compression != NoCompression)
1201      {
1202        size_t
1203          length;
1204
1205        /*
1206          Convert run-length encoded raster pixels.
1207        */
1208        length=2UL*(bytes_per_line+2UL)+2UL;
1209        dib_data=(unsigned char *) AcquireQuantumMemory(length,
1210          (image->rows+2UL)*sizeof(*dib_data));
1211        if (pixels == (unsigned char *) NULL)
1212          {
1213            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1214            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1215          }
1216        dib_info.image_size=(unsigned long) EncodeImage(image,bytes_per_line,
1217          pixels,dib_data);
1218        pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1219        pixels=dib_data;
1220        dib_info.compression = BI_RLE8;
1221      }
1222  /*
1223    Write DIB header.
1224  */
1225  (void) WriteBlobLSBLong(image,dib_info.size);
1226  (void) WriteBlobLSBLong(image,(unsigned long) dib_info.width);
1227  (void) WriteBlobLSBLong(image,(unsigned short) dib_info.height);
1228  (void) WriteBlobLSBShort(image,(unsigned short) dib_info.planes);
1229  (void) WriteBlobLSBShort(image,dib_info.bits_per_pixel);
1230  (void) WriteBlobLSBLong(image,dib_info.compression);
1231  (void) WriteBlobLSBLong(image,dib_info.image_size);
1232  (void) WriteBlobLSBLong(image,dib_info.x_pixels);
1233  (void) WriteBlobLSBLong(image,dib_info.y_pixels);
1234  (void) WriteBlobLSBLong(image,dib_info.number_colors);
1235  (void) WriteBlobLSBLong(image,dib_info.colors_important);
1236  if (image->storage_class == PseudoClass)
1237    {
1238      if (dib_info.bits_per_pixel <= 8)
1239        {
1240          unsigned char
1241            *dib_colormap;
1242
1243          /*
1244            Dump colormap to file.
1245          */
1246          dib_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
1247            (1UL << dib_info.bits_per_pixel),4*sizeof(dib_colormap));
1248          if (dib_colormap == (unsigned char *) NULL)
1249            ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1250          q=dib_colormap;
1251          for (i=0; i < (long) MagickMin(image->colors,dib_info.number_colors); i++)
1252          {
1253            *q++=ScaleQuantumToChar(image->colormap[i].blue);
1254            *q++=ScaleQuantumToChar(image->colormap[i].green);
1255            *q++=ScaleQuantumToChar(image->colormap[i].red);
1256            *q++=(Quantum) 0x0;
1257          }
1258          for ( ; i < (long) (1L << dib_info.bits_per_pixel); i++)
1259          {
1260            *q++=(Quantum) 0x0;
1261            *q++=(Quantum) 0x0;
1262            *q++=(Quantum) 0x0;
1263            *q++=(Quantum) 0x0;
1264          }
1265          (void) WriteBlob(image,(size_t) (4*(1 << dib_info.bits_per_pixel)),
1266            dib_colormap);
1267          dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
1268        }
1269      else
1270        if ((dib_info.bits_per_pixel == 16) &&
1271            (dib_info.compression == BI_BITFIELDS))
1272          {
1273            (void) WriteBlobLSBLong(image,0xf800);
1274            (void) WriteBlobLSBLong(image,0x07e0);
1275            (void) WriteBlobLSBLong(image,0x001f);
1276          }
1277    }
1278  (void) WriteBlob(image,dib_info.image_size,pixels);
1279  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1280  (void) CloseBlob(image);
1281  return(MagickTrue);
1282}
Note: See TracBrowser for help on using the browser.