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