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