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