]> granicus.if.org Git - imagemagick/blob - coders/xwd.c
(no commit message)
[imagemagick] / coders / xwd.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            X   X  W   W  DDDD                               %
7 %                             X X   W   W  D   D                              %
8 %                              X    W   W  D   D                              %
9 %                             X X   W W W  D   D                              %
10 %                            X   X   W W   DDDD                               %
11 %                                                                             %
12 %                                                                             %
13 %                Read/Write X Windows System Window Dump Format               %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2010 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 \f
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-private.h"
47 #include "magick/colormap-private.h"
48 #include "magick/colorspace.h"
49 #include "magick/exception.h"
50 #include "magick/exception-private.h"
51 #include "magick/image.h"
52 #include "magick/image-private.h"
53 #include "magick/list.h"
54 #include "magick/magick.h"
55 #include "magick/memory_.h"
56 #include "magick/monitor.h"
57 #include "magick/monitor-private.h"
58 #include "magick/property.h"
59 #include "magick/quantum-private.h"
60 #include "magick/static.h"
61 #include "magick/string_.h"
62 #include "magick/module.h"
63 #if defined(MAGICKCORE_X11_DELEGATE)
64 #include "magick/xwindow-private.h"
65 #if !defined(vms)
66 #include <X11/XWDFile.h>
67 #else
68 #include "XWDFile.h"
69 #endif
70 #endif
71 \f
72 /*
73   Forward declarations.
74 */
75 #if defined(MAGICKCORE_X11_DELEGATE)
76 static MagickBooleanType
77   WriteXWDImage(const ImageInfo *,Image *);
78 #endif
79 \f
80 /*
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 %                                                                             %
83 %                                                                             %
84 %                                                                             %
85 %   I s X W D                                                                 %
86 %                                                                             %
87 %                                                                             %
88 %                                                                             %
89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90 %
91 %  IsXWD() returns MagickTrue if the image format type, identified by the
92 %  magick string, is XWD.
93 %
94 %  The format of the IsXWD method is:
95 %
96 %      MagickBooleanType IsXWD(const unsigned char *magick,const size_t length)
97 %
98 %  A description of each parameter follows:
99 %
100 %    o magick: compare image format pattern against these bytes.
101 %
102 %    o length: Specifies the length of the magick string.
103 %
104 */
105 static MagickBooleanType IsXWD(const unsigned char *magick,const size_t length)
106 {
107   if (length < 8)
108     return(MagickFalse);
109   if (memcmp(magick+1,"\000\000",2) == 0)
110     {
111       if (memcmp(magick+4,"\007\000\000",3) == 0)
112         return(MagickTrue);
113       if (memcmp(magick+5,"\000\000\007",3) == 0)
114         return(MagickTrue);
115     }
116   return(MagickFalse);
117 }
118 \f
119 #if defined(MAGICKCORE_X11_DELEGATE)
120 /*
121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122 %                                                                             %
123 %                                                                             %
124 %                                                                             %
125 %   R e a d X W D I m a g e                                                   %
126 %                                                                             %
127 %                                                                             %
128 %                                                                             %
129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130 %
131 %  ReadXWDImage() reads an X Window System window dump image file and
132 %  returns it.  It allocates the memory necessary for the new Image structure
133 %  and returns a pointer to the new image.
134 %
135 %  The format of the ReadXWDImage method is:
136 %
137 %      Image *ReadXWDImage(const ImageInfo *image_info,ExceptionInfo *exception)
138 %
139 %  A description of each parameter follows:
140 %
141 %    o image_info: the image info.
142 %
143 %    o exception: return any errors or warnings in this structure.
144 %
145 */
146
147 static Image *ReadXWDImage(const ImageInfo *image_info,ExceptionInfo *exception)
148 {
149 #define CheckOverflowException(length,width,height) \
150   (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
151
152   char
153     *comment;
154
155   Image
156     *image;
157
158   IndexPacket
159     index;
160
161   int
162     x_status;
163
164   long
165     y;
166
167   MagickBooleanType
168     authentic_colormap;
169
170   MagickStatusType
171     status;
172
173   register IndexPacket
174     *indexes;
175
176   register long
177     x;
178
179   register PixelPacket
180     *q;
181
182   register long
183     i;
184
185   register unsigned long
186     pixel;
187
188   size_t
189     length;
190
191   ssize_t
192     count;
193
194   unsigned long
195     lsb_first;
196
197   XColor
198     *colors;
199
200   XImage
201     *ximage;
202
203   XWDFileHeader
204     header;
205
206   /*
207     Open image file.
208   */
209   assert(image_info != (const ImageInfo *) NULL);
210   assert(image_info->signature == MagickSignature);
211   if (image_info->debug != MagickFalse)
212     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
213       image_info->filename);
214   assert(exception != (ExceptionInfo *) NULL);
215   assert(exception->signature == MagickSignature);
216   image=AcquireImage(image_info);
217   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
218   if (status == MagickFalse)
219     {
220       image=DestroyImageList(image);
221       return((Image *) NULL);
222     }
223   /*
224      Read in header information.
225   */
226   count=ReadBlob(image,sz_XWDheader,(unsigned char *) &header);
227   if (count == 0)
228     ThrowReaderException(CorruptImageError,"UnableToReadImageHeader");
229   image->columns=header.pixmap_width;
230   image->rows=header.pixmap_height;
231   image->depth=8;
232   /*
233     Ensure the header byte-order is most-significant byte first.
234   */
235   lsb_first=1;
236   if ((int) (*(char *) &lsb_first) != 0)
237     MSBOrderLong((unsigned char *) &header,sz_XWDheader);
238   /*
239     Check to see if the dump file is in the proper format.
240   */
241   if (header.file_version != XWD_FILE_VERSION)
242     ThrowReaderException(CorruptImageError,"FileFormatVersionMismatch");
243   if (header.header_size < sz_XWDheader)
244     ThrowReaderException(CorruptImageError,"CorruptImage");
245   length=(size_t) header.header_size-sz_XWDheader;
246   comment=(char *) AcquireQuantumMemory(length+1,sizeof(*comment));
247   if (comment == (char *) NULL)
248     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
249   count=ReadBlob(image,length,(unsigned char *) comment);
250   comment[length]='\0';
251   (void) SetImageProperty(image,"comment",comment);
252   comment=DestroyString(comment);
253   if (count != (ssize_t) length)
254     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
255   /*
256     Initialize the X image.
257   */
258   ximage=(XImage *) AcquireAlignedMemory(1,sizeof(*ximage));
259   if (ximage == (XImage *) NULL)
260     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
261   ximage->depth=(int) header.pixmap_depth;
262   ximage->format=(int) header.pixmap_format;
263   ximage->xoffset=(int) header.xoffset;
264   ximage->data=(char *) NULL;
265   ximage->width=(int) header.pixmap_width;
266   ximage->height=(int) header.pixmap_height;
267   ximage->bitmap_pad=(int) header.bitmap_pad;
268   ximage->bytes_per_line=(int) header.bytes_per_line;
269   ximage->byte_order=(int) header.byte_order;
270   ximage->bitmap_unit=(int) header.bitmap_unit;
271   ximage->bitmap_bit_order=(int) header.bitmap_bit_order;
272   ximage->bits_per_pixel=(int) header.bits_per_pixel;
273   ximage->red_mask=header.red_mask;
274   ximage->green_mask=header.green_mask;
275   ximage->blue_mask=header.blue_mask;
276   if ((ximage->depth < 0) || (ximage->width < 0) || (ximage->height < 0) ||
277       (ximage->bitmap_pad < 0) || (ximage->bytes_per_line < 0))
278     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
279   if ((ximage->bits_per_pixel > 32) || (ximage->bitmap_unit > 32))
280     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
281   x_status=XInitImage(ximage);
282   if (x_status == 0)
283     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
284   /*
285     Read colormap.
286   */
287   authentic_colormap=MagickFalse;
288   colors=(XColor *) NULL;
289   if (header.ncolors != 0)
290     {
291       XWDColor
292         color;
293
294       length=(size_t) header.ncolors;
295       colors=(XColor *) AcquireQuantumMemory(length,sizeof(*colors));
296       if (colors == (XColor *) NULL)
297         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
298       for (i=0; i < (long) header.ncolors; i++)
299       {
300         count=ReadBlob(image,sz_XWDColor,(unsigned char *) &color);
301         if (count == 0)
302           ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
303         colors[i].pixel=color.pixel;
304         colors[i].red=color.red;
305         colors[i].green=color.green;
306         colors[i].blue=color.blue;
307         colors[i].flags=(char) color.flags;
308         if (color.flags != 0)
309          authentic_colormap=MagickTrue;
310       }
311       /*
312         Ensure the header byte-order is most-significant byte first.
313       */
314       lsb_first=1;
315       if ((int) (*(char *) &lsb_first) != 0)
316         for (i=0; i < (long) header.ncolors; i++)
317         {
318           MSBOrderLong((unsigned char *) &colors[i].pixel,
319             sizeof(colors[i].pixel));
320           MSBOrderShort((unsigned char *) &colors[i].red,3*
321             sizeof(colors[i].red));
322         }
323     }
324   /*
325     Allocate the pixel buffer.
326   */
327   length=(size_t) ximage->bytes_per_line*ximage->height;
328   if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
329     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
330   if (ximage->format != ZPixmap)
331     {
332       size_t
333         extent;
334
335       extent=length;
336       length*=ximage->depth;
337       if (CheckOverflowException(length,extent,ximage->depth))
338         ThrowReaderException(CorruptImageError,"ImproperImageHeader");
339     }
340   ximage->data=(char *) AcquireQuantumMemory(length,sizeof(*ximage->data));
341   if (ximage->data == (char *) NULL)
342     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
343   count=ReadBlob(image,length,(unsigned char *) ximage->data);
344   if (count == 0)
345     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
346   /*
347     Convert image to MIFF format.
348   */
349   image->columns=(unsigned long) ximage->width;
350   image->rows=(unsigned long) ximage->height;
351   if ((colors == (XColor *) NULL) || (ximage->red_mask != 0) ||
352       (ximage->green_mask != 0) || (ximage->blue_mask != 0))
353     image->storage_class=DirectClass;
354   else
355     image->storage_class=PseudoClass;
356   image->colors=header.ncolors;
357   if (image_info->ping == MagickFalse)
358     switch (image->storage_class)
359     {
360       case DirectClass:
361       default:
362       {
363         register unsigned long
364           color;
365
366         unsigned long
367           blue_mask,
368           blue_shift,
369           green_mask,
370           green_shift,
371           red_mask,
372           red_shift;
373
374         /*
375           Determine shift and mask for red, green, and blue.
376         */
377         red_mask=ximage->red_mask;
378         red_shift=0;
379         while ((red_mask != 0) && ((red_mask & 0x01) == 0))
380         {
381           red_mask>>=1;
382           red_shift++;
383         }
384         green_mask=ximage->green_mask;
385         green_shift=0;
386         while ((green_mask != 0) && ((green_mask & 0x01) == 0))
387         {
388           green_mask>>=1;
389           green_shift++;
390         }
391         blue_mask=ximage->blue_mask;
392         blue_shift=0;
393         while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
394         {
395           blue_mask>>=1;
396           blue_shift++;
397         }
398         /*
399           Convert X image to DirectClass packets.
400         */
401         if ((image->colors != 0) && (authentic_colormap != MagickFalse))
402           for (y=0; y < (long) image->rows; y++)
403           {
404             q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
405             if (q == (PixelPacket *) NULL)
406               break;
407             for (x=0; x < (long) image->columns; x++)
408             {
409               pixel=XGetPixel(ximage,(int) x,(int) y);
410               index=(IndexPacket) ((pixel >> red_shift) & red_mask);
411               q->red=ScaleShortToQuantum(colors[(long) index].red);
412               index=(IndexPacket) ((pixel >> green_shift) & green_mask);
413               q->green=ScaleShortToQuantum(colors[(long) index].green);
414               index=(IndexPacket) ((pixel >> blue_shift) & blue_mask);
415               q->blue=ScaleShortToQuantum(colors[(long) index].blue);
416               q++;
417             }
418             if (SyncAuthenticPixels(image,exception) == MagickFalse)
419               break;
420             status=SetImageProgress(image,LoadImageTag,y,image->rows);
421             if (status == MagickFalse)
422               break;
423           }
424         else
425           for (y=0; y < (long) image->rows; y++)
426           {
427             q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
428             if (q == (PixelPacket *) NULL)
429               break;
430             for (x=0; x < (long) image->columns; x++)
431             {
432               pixel=XGetPixel(ximage,(int) x,(int) y);
433               color=(pixel >> red_shift) & red_mask;
434               color=(color*65535UL)/red_mask;
435               q->red=ScaleShortToQuantum((unsigned short) color);
436               color=(pixel >> green_shift) & green_mask;
437               color=(color*65535UL)/green_mask;
438               q->green=ScaleShortToQuantum((unsigned short) color);
439               color=(pixel >> blue_shift) & blue_mask;
440               color=(color*65535UL)/blue_mask;
441               q->blue=ScaleShortToQuantum((unsigned short) color);
442               q++;
443             }
444             if (SyncAuthenticPixels(image,exception) == MagickFalse)
445               break;
446             status=SetImageProgress(image,LoadImageTag,y,image->rows);
447             if (status == MagickFalse)
448               break;
449           }
450         break;
451       }
452       case PseudoClass:
453       {
454         /*
455           Convert X image to PseudoClass packets.
456         */
457         if (AcquireImageColormap(image,image->colors) == MagickFalse)
458           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
459         for (i=0; i < (long) image->colors; i++)
460         {
461           image->colormap[i].red=ScaleShortToQuantum(colors[i].red);
462           image->colormap[i].green=ScaleShortToQuantum(colors[i].green);
463           image->colormap[i].blue=ScaleShortToQuantum(colors[i].blue);
464         }
465         for (y=0; y < (long) image->rows; y++)
466         {
467           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
468           if (q == (PixelPacket *) NULL)
469             break;
470           indexes=GetAuthenticIndexQueue(image);
471           for (x=0; x < (long) image->columns; x++)
472           {
473             index=ConstrainColormapIndex(image,XGetPixel(ximage,(int) x,
474               (int) y));
475             indexes[x]=index;
476             *q++=image->colormap[(long) index];
477           }
478           if (SyncAuthenticPixels(image,exception) == MagickFalse)
479             break;
480           status=SetImageProgress(image,LoadImageTag,y,image->rows);
481           if (status == MagickFalse)
482             break;
483         }
484         break;
485       }
486     }
487   /*
488     Free image and colormap.
489   */
490   if (header.ncolors != 0)
491     colors=(XColor *) RelinquishMagickMemory(colors);
492   ximage->data=DestroyString(ximage->data);
493   ximage=(XImage *) RelinquishMagickMemory(ximage);
494   if (EOFBlob(image) != MagickFalse)
495     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
496       image->filename);
497   (void) CloseBlob(image);
498   return(GetFirstImageInList(image));
499 }
500 #endif
501 \f
502 /*
503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504 %                                                                             %
505 %                                                                             %
506 %                                                                             %
507 %   R e g i s t e r X W D I m a g e                                           %
508 %                                                                             %
509 %                                                                             %
510 %                                                                             %
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512 %
513 %  RegisterXWDImage() adds properties for the XWD image format to
514 %  the list of supported formats.  The properties include the image format
515 %  tag, a method to read and/or write the format, whether the format
516 %  supports the saving of more than one frame to the same file or blob,
517 %  whether the format supports native in-memory I/O, and a brief
518 %  description of the format.
519 %
520 %  The format of the RegisterXWDImage method is:
521 %
522 %      unsigned long RegisterXWDImage(void)
523 %
524 */
525 ModuleExport unsigned long RegisterXWDImage(void)
526 {
527   MagickInfo
528     *entry;
529
530   entry=SetMagickInfo("XWD");
531 #if defined(MAGICKCORE_X11_DELEGATE)
532   entry->decoder=(DecodeImageHandler *) ReadXWDImage;
533   entry->encoder=(EncodeImageHandler *) WriteXWDImage;
534 #endif
535   entry->magick=(IsImageFormatHandler *) IsXWD;
536   entry->adjoin=MagickFalse;
537   entry->description=ConstantString("X Windows system window dump (color)");
538   entry->module=ConstantString("XWD");
539   (void) RegisterMagickInfo(entry);
540   return(MagickImageCoderSignature);
541 }
542 \f
543 /*
544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
545 %                                                                             %
546 %                                                                             %
547 %                                                                             %
548 %   U n r e g i s t e r X W D I m a g e                                       %
549 %                                                                             %
550 %                                                                             %
551 %                                                                             %
552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
553 %
554 %  UnregisterXWDImage() removes format registrations made by the
555 %  XWD module from the list of supported formats.
556 %
557 %  The format of the UnregisterXWDImage method is:
558 %
559 %      UnregisterXWDImage(void)
560 %
561 */
562 ModuleExport void UnregisterXWDImage(void)
563 {
564   (void) UnregisterMagickInfo("XWD");
565 }
566 \f
567 #if defined(MAGICKCORE_X11_DELEGATE)
568 /*
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %                                                                             %
571 %                                                                             %
572 %                                                                             %
573 %   W r i t e X W D I m a g e                                                 %
574 %                                                                             %
575 %                                                                             %
576 %                                                                             %
577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578 %
579 %  WriteXWDImage() writes an image to a file in X window dump
580 %  rasterfile format.
581 %
582 %  The format of the WriteXWDImage method is:
583 %
584 %      MagickBooleanType WriteXWDImage(const ImageInfo *image_info,Image *image)
585 %
586 %  A description of each parameter follows.
587 %
588 %    o image_info: the image info.
589 %
590 %    o image:  The image.
591 %
592 */
593 static MagickBooleanType WriteXWDImage(const ImageInfo *image_info,Image *image)
594 {
595   const char
596     *value;
597
598   long
599     y;
600
601   MagickBooleanType
602     status;
603
604   register const IndexPacket
605     *indexes;
606
607   register const PixelPacket
608     *p;
609
610   register long
611     x;
612
613   register long
614     i;
615
616   register unsigned char
617     *q;
618
619   size_t
620     length;
621
622   unsigned char
623     *pixels;
624
625   unsigned long
626     bits_per_pixel,
627     bytes_per_line,
628     lsb_first,
629     scanline_pad;
630
631   XWDFileHeader
632     xwd_info;
633
634   /*
635     Open output image file.
636   */
637   assert(image_info != (const ImageInfo *) NULL);
638   assert(image_info->signature == MagickSignature);
639   assert(image != (Image *) NULL);
640   assert(image->signature == MagickSignature);
641   if (image->debug != MagickFalse)
642     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
643   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
644   if (status == MagickFalse)
645     return(status);
646   if (image->colorspace != RGBColorspace)
647     (void) TransformImageColorspace(image,RGBColorspace);
648   /*
649     Initialize XWD file header.
650   */
651   (void) ResetMagickMemory(&xwd_info,0,sizeof(xwd_info));
652   xwd_info.header_size=(CARD32) sz_XWDheader;
653   value=GetImageProperty(image,"comment");
654   if (value != (const char *) NULL)
655     xwd_info.header_size+=(CARD32) strlen(value);
656   xwd_info.header_size++;
657   xwd_info.file_version=(CARD32) XWD_FILE_VERSION;
658   xwd_info.pixmap_format=(CARD32) ZPixmap;
659   xwd_info.pixmap_depth=(CARD32) (image->storage_class == DirectClass ? 24 : 8);
660   xwd_info.pixmap_width=(CARD32) image->columns;
661   xwd_info.pixmap_height=(CARD32) image->rows;
662   xwd_info.xoffset=(CARD32) 0;
663   xwd_info.byte_order=(CARD32) MSBFirst;
664   xwd_info.bitmap_unit=(CARD32) (image->storage_class == DirectClass ? 32 : 8);
665   xwd_info.bitmap_bit_order=(CARD32) MSBFirst;
666   xwd_info.bitmap_pad=(CARD32) (image->storage_class == DirectClass ? 32 : 8);
667   bits_per_pixel=(unsigned long) (image->storage_class == DirectClass ? 24 : 8);
668   xwd_info.bits_per_pixel=(CARD32) bits_per_pixel;
669   bytes_per_line=(CARD32) ((((xwd_info.bits_per_pixel*
670     xwd_info.pixmap_width)+((xwd_info.bitmap_pad)-1))/
671     (xwd_info.bitmap_pad))*((xwd_info.bitmap_pad) >> 3));
672   xwd_info.bytes_per_line=(CARD32) bytes_per_line;
673   xwd_info.visual_class=(CARD32)
674     (image->storage_class == DirectClass ? DirectColor : PseudoColor);
675   xwd_info.red_mask=(CARD32)
676     (image->storage_class == DirectClass ? 0xff0000 : 0);
677   xwd_info.green_mask=(CARD32)
678     (image->storage_class == DirectClass ? 0xff00 : 0);
679   xwd_info.blue_mask=(CARD32) (image->storage_class == DirectClass ? 0xff : 0);
680   xwd_info.bits_per_rgb=(CARD32) (image->storage_class == DirectClass ? 24 : 8);
681   xwd_info.colormap_entries=(CARD32)
682     (image->storage_class == DirectClass ? 256 : image->colors);
683   xwd_info.ncolors=(unsigned int)
684     (image->storage_class == DirectClass ? 0 : image->colors);
685   xwd_info.window_width=(CARD32) image->columns;
686   xwd_info.window_height=(CARD32) image->rows;
687   xwd_info.window_x=0;
688   xwd_info.window_y=0;
689   xwd_info.window_bdrwidth=(CARD32) 0;
690   /*
691     Write XWD header.
692   */
693   lsb_first=1;
694   if ((int) (*(char *) &lsb_first) != 0)
695     MSBOrderLong((unsigned char *) &xwd_info,sizeof(xwd_info));
696   (void) WriteBlob(image,sz_XWDheader,(unsigned char *) &xwd_info);
697   if (value != (const char *) NULL)
698     (void) WriteBlob(image,strlen(value),(unsigned char *) value);
699   (void) WriteBlob(image,1,(const unsigned char *) "\0");
700   if (image->storage_class == PseudoClass)
701     {
702       XColor
703         *colors;
704
705       XWDColor
706         color;
707
708       /*
709         Dump colormap to file.
710       */
711       (void) ResetMagickMemory(&color,0,sizeof(color));
712       colors=(XColor *) AcquireQuantumMemory((size_t) image->colors,
713         sizeof(*colors));
714       if (colors == (XColor *) NULL)
715         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
716       for (i=0; i < (long) image->colors; i++)
717       {
718         colors[i].pixel=(unsigned long) i;
719         colors[i].red=ScaleQuantumToShort(image->colormap[i].red);
720         colors[i].green=ScaleQuantumToShort(image->colormap[i].green);
721         colors[i].blue=ScaleQuantumToShort(image->colormap[i].blue);
722         colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
723         colors[i].pad='\0';
724         if ((int) (*(char *) &lsb_first) != 0)
725           {
726             MSBOrderLong((unsigned char *) &colors[i].pixel,
727               sizeof(colors[i].pixel));
728             MSBOrderShort((unsigned char *) &colors[i].red,
729               3*sizeof(colors[i].red));
730           }
731       }
732       for (i=0; i < (long) image->colors; i++)
733       {
734         color.pixel=(CARD32) colors[i].pixel;
735         color.red=colors[i].red;
736         color.green=colors[i].green;
737         color.blue=colors[i].blue;
738         color.flags=(CARD8) colors[i].flags;
739         (void) WriteBlob(image,sz_XWDColor,(unsigned char *) &color);
740       }
741       colors=(XColor *) RelinquishMagickMemory(colors);
742     }
743   /*
744     Allocate memory for pixels.
745   */
746   length=3*bytes_per_line;
747   if (image->storage_class == PseudoClass)
748     length=bytes_per_line;
749   pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
750   if (pixels == (unsigned char *) NULL)
751     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
752   (void) ResetMagickMemory(pixels,0,length);
753   /*
754     Convert MIFF to XWD raster pixels.
755   */
756   scanline_pad=(bytes_per_line-((image->columns*bits_per_pixel) >> 3));
757   for (y=0; y < (long) image->rows; y++)
758   {
759     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
760     if (p == (const PixelPacket *) NULL)
761       break;
762     q=pixels;
763     if (image->storage_class == PseudoClass)
764       {
765         indexes=GetVirtualIndexQueue(image);
766         for (x=0; x < (long) image->columns; x++)
767           *q++=(unsigned char) indexes[x];
768       }
769     else
770       for (x=0; x < (long) image->columns; x++)
771       {
772         *q++=ScaleQuantumToChar(GetRedPixelComponent(p));
773         *q++=ScaleQuantumToChar(GetGreenPixelComponent(p));
774         *q++=ScaleQuantumToChar(GetBluePixelComponent(p));
775         p++;
776       }
777     for (x=0; x < (long) scanline_pad; x++)
778       *q++='\0';
779     (void) WriteBlob(image,(size_t) (q-pixels),pixels);
780     status=SetImageProgress(image,SaveImageTag,y,image->rows);
781     if (status == MagickFalse)
782       break;
783   }
784   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
785   (void) CloseBlob(image);
786   return(MagickTrue);
787 }
788 #endif