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-2019 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 % https://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 if (length > ((~0UL)/sizeof(*colors))) 330 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 331 colors=(XColor *) AcquireQuantumMemory(length,sizeof(*colors)); 332 if (colors == (XColor *) NULL) 333 { 334 ximage=(XImage *) RelinquishMagickMemory(ximage); 335 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 336 } 337 for (i=0; i < (ssize_t) header.ncolors; i++) 338 { 339 count=ReadBlob(image,sz_XWDColor,(unsigned char *) &color); 340 if (count != sz_XWDColor) 341 { 342 colors=(XColor *) RelinquishMagickMemory(colors); 343 ximage=(XImage *) RelinquishMagickMemory(ximage); 344 ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); 345 } 346 colors[i].pixel=color.pixel; 347 colors[i].red=color.red; 348 colors[i].green=color.green; 349 colors[i].blue=color.blue; 350 colors[i].flags=(char) color.flags; 351 if (color.flags != 0) 352 authentic_colormap=MagickTrue; 353 } 354 /* 355 Ensure the header byte-order is most-significant byte first. 356 */ 357 lsb_first=1; 358 if ((int) (*(char *) &lsb_first) != 0) 359 for (i=0; i < (ssize_t) header.ncolors; i++) 360 { 361 MSBOrderLong((unsigned char *) &colors[i].pixel, 362 sizeof(colors[i].pixel)); 363 MSBOrderShort((unsigned char *) &colors[i].red,3* 364 sizeof(colors[i].red)); 365 } 366 } 367 /* 368 Allocate the pixel buffer. 369 */ 370 length=(size_t) ximage->bytes_per_line*ximage->height; 371 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height)) 372 { 373 if (header.ncolors != 0) 374 colors=(XColor *) RelinquishMagickMemory(colors); 375 ximage=(XImage *) RelinquishMagickMemory(ximage); 376 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 377 } 378 if (ximage->format != ZPixmap) 379 { 380 size_t 381 extent; 382 383 extent=length; 384 length*=ximage->depth; 385 if (CheckOverflowException(length,extent,ximage->depth)) 386 { 387 if (header.ncolors != 0) 388 colors=(XColor *) RelinquishMagickMemory(colors); 389 ximage=(XImage *) RelinquishMagickMemory(ximage); 390 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 391 } 392 } 393 ximage->data=(char *) AcquireQuantumMemory(length,sizeof(*ximage->data)); 394 if (ximage->data == (char *) NULL) 395 { 396 if (header.ncolors != 0) 397 colors=(XColor *) RelinquishMagickMemory(colors); 398 ximage=(XImage *) RelinquishMagickMemory(ximage); 399 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 400 } 401 count=ReadBlob(image,length,(unsigned char *) ximage->data); 402 if (count != (ssize_t) length) 403 { 404 if (header.ncolors != 0) 405 colors=(XColor *) RelinquishMagickMemory(colors); 406 ximage->data=DestroyString(ximage->data); 407 ximage=(XImage *) RelinquishMagickMemory(ximage); 408 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 409 } 410 /* 411 Convert image to MIFF format. 412 */ 413 image->columns=(size_t) ximage->width; 414 image->rows=(size_t) ximage->height; 415 image->depth=8; 416 status=SetImageExtent(image,image->columns,image->rows,exception); 417 if (status == MagickFalse) 418 { 419 if (header.ncolors != 0) 420 colors=(XColor *) RelinquishMagickMemory(colors); 421 ximage->data=DestroyString(ximage->data); 422 ximage=(XImage *) RelinquishMagickMemory(ximage); 423 return(DestroyImageList(image)); 424 } 425 if ((header.ncolors == 0U) || (ximage->red_mask != 0) || 426 (ximage->green_mask != 0) || (ximage->blue_mask != 0)) 427 image->storage_class=DirectClass; 428 else 429 image->storage_class=PseudoClass; 430 image->colors=header.ncolors; 431 if (image_info->ping == MagickFalse) 432 switch (image->storage_class) 433 { 434 case DirectClass: 435 default: 436 { 437 register size_t 438 color; 439 440 size_t 441 blue_mask, 442 blue_shift, 443 green_mask, 444 green_shift, 445 red_mask, 446 red_shift; 447 448 /* 449 Determine shift and mask for red, green, and blue. 450 */ 451 red_mask=ximage->red_mask; 452 red_shift=0; 453 while ((red_mask != 0) && ((red_mask & 0x01) == 0)) 454 { 455 red_mask>>=1; 456 red_shift++; 457 } 458 green_mask=ximage->green_mask; 459 green_shift=0; 460 while ((green_mask != 0) && ((green_mask & 0x01) == 0)) 461 { 462 green_mask>>=1; 463 green_shift++; 464 } 465 blue_mask=ximage->blue_mask; 466 blue_shift=0; 467 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0)) 468 { 469 blue_mask>>=1; 470 blue_shift++; 471 } 472 /* 473 Convert X image to DirectClass packets. 474 */ 475 if ((image->colors != 0) && (authentic_colormap != MagickFalse)) 476 for (y=0; y < (ssize_t) image->rows; y++) 477 { 478 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 479 if (q == (Quantum *) NULL) 480 break; 481 for (x=0; x < (ssize_t) image->columns; x++) 482 { 483 pixel=XGetPixel(ximage,(int) x,(int) y); 484 index=(Quantum) ((pixel >> red_shift) & red_mask); 485 if (index < header.ncolors) 486 SetPixelRed(image,ScaleShortToQuantum( 487 colors[(ssize_t) index].red),q); 488 index=(Quantum) ((pixel >> green_shift) & green_mask); 489 if (index < header.ncolors) 490 SetPixelGreen(image,ScaleShortToQuantum( 491 colors[(ssize_t) index].green),q); 492 index=(Quantum) ((pixel >> blue_shift) & blue_mask); 493 if (index < header.ncolors) 494 SetPixelBlue(image,ScaleShortToQuantum( 495 colors[(ssize_t) index].blue),q); 496 q+=GetPixelChannels(image); 497 } 498 if (SyncAuthenticPixels(image,exception) == MagickFalse) 499 break; 500 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 501 image->rows); 502 if (status == MagickFalse) 503 break; 504 } 505 else 506 for (y=0; y < (ssize_t) image->rows; y++) 507 { 508 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 509 if (q == (Quantum *) NULL) 510 break; 511 for (x=0; x < (ssize_t) image->columns; x++) 512 { 513 pixel=XGetPixel(ximage,(int) x,(int) y); 514 color=(pixel >> red_shift) & red_mask; 515 if (red_mask != 0) 516 color=(color*65535UL)/red_mask; 517 SetPixelRed(image,ScaleShortToQuantum((unsigned short) color),q); 518 color=(pixel >> green_shift) & green_mask; 519 if (green_mask != 0) 520 color=(color*65535UL)/green_mask; 521 SetPixelGreen(image,ScaleShortToQuantum((unsigned short) color), 522 q); 523 color=(pixel >> blue_shift) & blue_mask; 524 if (blue_mask != 0) 525 color=(color*65535UL)/blue_mask; 526 SetPixelBlue(image,ScaleShortToQuantum((unsigned short) color),q); 527 q+=GetPixelChannels(image); 528 } 529 if (SyncAuthenticPixels(image,exception) == MagickFalse) 530 break; 531 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 532 image->rows); 533 if (status == MagickFalse) 534 break; 535 } 536 break; 537 } 538 case PseudoClass: 539 { 540 /* 541 Convert X image to PseudoClass packets. 542 */ 543 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) 544 { 545 if (header.ncolors != 0) 546 colors=(XColor *) RelinquishMagickMemory(colors); 547 ximage->data=DestroyString(ximage->data); 548 ximage=(XImage *) RelinquishMagickMemory(ximage); 549 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 550 } 551 for (i=0; i < (ssize_t) image->colors; i++) 552 { 553 image->colormap[i].red=(MagickRealType) ScaleShortToQuantum( 554 colors[i].red); 555 image->colormap[i].green=(MagickRealType) ScaleShortToQuantum( 556 colors[i].green); 557 image->colormap[i].blue=(MagickRealType) ScaleShortToQuantum( 558 colors[i].blue); 559 } 560 for (y=0; y < (ssize_t) image->rows; y++) 561 { 562 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 563 if (q == (Quantum *) NULL) 564 break; 565 for (x=0; x < (ssize_t) image->columns; x++) 566 { 567 index=ConstrainColormapIndex(image,XGetPixel(ximage,(int) x, 568 (int) y),exception); 569 SetPixelIndex(image,index,q); 570 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 571 q+=GetPixelChannels(image); 572 } 573 if (SyncAuthenticPixels(image,exception) == MagickFalse) 574 break; 575 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 576 image->rows); 577 if (status == MagickFalse) 578 break; 579 } 580 break; 581 } 582 } 583 /* 584 Free image and colormap. 585 */ 586 if (header.ncolors != 0) 587 colors=(XColor *) RelinquishMagickMemory(colors); 588 ximage->data=DestroyString(ximage->data); 589 ximage=(XImage *) RelinquishMagickMemory(ximage); 590 if (EOFBlob(image) != MagickFalse) 591 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 592 image->filename); 593 (void) CloseBlob(image); 594 return(GetFirstImageInList(image)); 595 } 596 #endif 597 598 /* 600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 601 % % 602 % % 603 % % 604 % R e g i s t e r X W D I m a g e % 605 % % 606 % % 607 % % 608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 609 % 610 % RegisterXWDImage() adds properties for the XWD image format to 611 % the list of supported formats. The properties include the image format 612 % tag, a method to read and/or write the format, whether the format 613 % supports the saving of more than one frame to the same file or blob, 614 % whether the format supports native in-memory I/O, and a brief 615 % description of the format. 616 % 617 % The format of the RegisterXWDImage method is: 618 % 619 % size_t RegisterXWDImage(void) 620 % 621 */ 622 ModuleExport size_t RegisterXWDImage(void) 623 { 624 MagickInfo 625 *entry; 626 627 entry=AcquireMagickInfo("XWD","XWD","X Windows system window dump (color)"); 628 #if defined(MAGICKCORE_X11_DELEGATE) 629 entry->decoder=(DecodeImageHandler *) ReadXWDImage; 630 entry->encoder=(EncodeImageHandler *) WriteXWDImage; 631 #endif 632 entry->magick=(IsImageFormatHandler *) IsXWD; 633 entry->flags^=CoderAdjoinFlag; 634 (void) RegisterMagickInfo(entry); 635 return(MagickImageCoderSignature); 636 } 637 638 /* 640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 641 % % 642 % % 643 % % 644 % U n r e g i s t e r X W D I m a g e % 645 % % 646 % % 647 % % 648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 649 % 650 % UnregisterXWDImage() removes format registrations made by the 651 % XWD module from the list of supported formats. 652 % 653 % The format of the UnregisterXWDImage method is: 654 % 655 % UnregisterXWDImage(void) 656 % 657 */ 658 ModuleExport void UnregisterXWDImage(void) 659 { 660 (void) UnregisterMagickInfo("XWD"); 661 } 662 663 #if defined(MAGICKCORE_X11_DELEGATE) 665 /* 666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 667 % % 668 % % 669 % % 670 % W r i t e X W D I m a g e % 671 % % 672 % % 673 % % 674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 675 % 676 % WriteXWDImage() writes an image to a file in X window dump 677 % rasterfile format. 678 % 679 % The format of the WriteXWDImage method is: 680 % 681 % MagickBooleanType WriteXWDImage(const ImageInfo *image_info, 682 % Image *image,ExceptionInfo *exception) 683 % 684 % A description of each parameter follows. 685 % 686 % o image_info: the image info. 687 % 688 % o image: The image. 689 % 690 % o exception: return any errors or warnings in this structure. 691 % 692 */ 693 static MagickBooleanType WriteXWDImage(const ImageInfo *image_info,Image *image, 694 ExceptionInfo *exception) 695 { 696 const char 697 *value; 698 699 MagickBooleanType 700 status; 701 702 register const Quantum 703 *p; 704 705 register ssize_t 706 x; 707 708 register unsigned char 709 *q; 710 711 size_t 712 bits_per_pixel, 713 bytes_per_line, 714 length, 715 scanline_pad; 716 717 ssize_t 718 y; 719 720 unsigned char 721 *pixels; 722 723 unsigned long 724 lsb_first; 725 726 XWDFileHeader 727 xwd_info; 728 729 /* 730 Open output image file. 731 */ 732 assert(image_info != (const ImageInfo *) NULL); 733 assert(image_info->signature == MagickCoreSignature); 734 assert(image != (Image *) NULL); 735 assert(image->signature == MagickCoreSignature); 736 if (image->debug != MagickFalse) 737 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 738 assert(exception != (ExceptionInfo *) NULL); 739 assert(exception->signature == MagickCoreSignature); 740 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 741 if (status == MagickFalse) 742 return(status); 743 (void) TransformImageColorspace(image,sRGBColorspace,exception); 744 /* 745 Initialize XWD file header. 746 */ 747 (void) memset(&xwd_info,0,sizeof(xwd_info)); 748 xwd_info.header_size=(CARD32) sz_XWDheader; 749 value=GetImageProperty(image,"comment",exception); 750 if (value != (const char *) NULL) 751 xwd_info.header_size+=(CARD32) strlen(value); 752 xwd_info.header_size++; 753 xwd_info.file_version=(CARD32) XWD_FILE_VERSION; 754 xwd_info.pixmap_format=(CARD32) ZPixmap; 755 xwd_info.pixmap_depth=(CARD32) (image->storage_class == DirectClass ? 24 : 8); 756 xwd_info.pixmap_width=(CARD32) image->columns; 757 xwd_info.pixmap_height=(CARD32) image->rows; 758 xwd_info.xoffset=(CARD32) 0; 759 xwd_info.byte_order=(CARD32) MSBFirst; 760 xwd_info.bitmap_unit=(CARD32) (image->storage_class == DirectClass ? 32 : 8); 761 xwd_info.bitmap_bit_order=(CARD32) MSBFirst; 762 xwd_info.bitmap_pad=(CARD32) (image->storage_class == DirectClass ? 32 : 8); 763 bits_per_pixel=(size_t) (image->storage_class == DirectClass ? 24 : 8); 764 xwd_info.bits_per_pixel=(CARD32) bits_per_pixel; 765 bytes_per_line=(CARD32) ((((xwd_info.bits_per_pixel* 766 xwd_info.pixmap_width)+((xwd_info.bitmap_pad)-1))/ 767 (xwd_info.bitmap_pad))*((xwd_info.bitmap_pad) >> 3)); 768 xwd_info.bytes_per_line=(CARD32) bytes_per_line; 769 xwd_info.visual_class=(CARD32) 770 (image->storage_class == DirectClass ? DirectColor : PseudoColor); 771 xwd_info.red_mask=(CARD32) 772 (image->storage_class == DirectClass ? 0xff0000 : 0); 773 xwd_info.green_mask=(CARD32) 774 (image->storage_class == DirectClass ? 0xff00 : 0); 775 xwd_info.blue_mask=(CARD32) (image->storage_class == DirectClass ? 0xff : 0); 776 xwd_info.bits_per_rgb=(CARD32) (image->storage_class == DirectClass ? 24 : 8); 777 xwd_info.colormap_entries=(CARD32) 778 (image->storage_class == DirectClass ? 256 : image->colors); 779 xwd_info.ncolors=(unsigned int) 780 (image->storage_class == DirectClass ? 0 : image->colors); 781 xwd_info.window_width=(CARD32) image->columns; 782 xwd_info.window_height=(CARD32) image->rows; 783 xwd_info.window_x=0; 784 xwd_info.window_y=0; 785 xwd_info.window_bdrwidth=(CARD32) 0; 786 /* 787 Write XWD header. 788 */ 789 lsb_first=1; 790 if ((int) (*(char *) &lsb_first) != 0) 791 MSBOrderLong((unsigned char *) &xwd_info,sizeof(xwd_info)); 792 (void) WriteBlob(image,sz_XWDheader,(unsigned char *) &xwd_info); 793 if (value != (const char *) NULL) 794 (void) WriteBlob(image,strlen(value),(unsigned char *) value); 795 (void) WriteBlob(image,1,(const unsigned char *) "\0"); 796 if (image->storage_class == PseudoClass) 797 { 798 register ssize_t 799 i; 800 801 XColor 802 *colors; 803 804 XWDColor 805 color; 806 807 /* 808 Dump colormap to file. 809 */ 810 (void) memset(&color,0,sizeof(color)); 811 colors=(XColor *) AcquireQuantumMemory((size_t) image->colors, 812 sizeof(*colors)); 813 if (colors == (XColor *) NULL) 814 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 815 for (i=0; i < (ssize_t) image->colors; i++) 816 { 817 colors[i].pixel=(unsigned long) i; 818 colors[i].red=ScaleQuantumToShort(ClampToQuantum( 819 image->colormap[i].red)); 820 colors[i].green=ScaleQuantumToShort(ClampToQuantum( 821 image->colormap[i].green)); 822 colors[i].blue=ScaleQuantumToShort(ClampToQuantum( 823 image->colormap[i].blue)); 824 colors[i].flags=(char) (DoRed | DoGreen | DoBlue); 825 colors[i].pad='\0'; 826 if ((int) (*(char *) &lsb_first) != 0) 827 { 828 MSBOrderLong((unsigned char *) &colors[i].pixel, 829 sizeof(colors[i].pixel)); 830 MSBOrderShort((unsigned char *) &colors[i].red, 831 3*sizeof(colors[i].red)); 832 } 833 } 834 for (i=0; i < (ssize_t) image->colors; i++) 835 { 836 color.pixel=(CARD32) colors[i].pixel; 837 color.red=colors[i].red; 838 color.green=colors[i].green; 839 color.blue=colors[i].blue; 840 color.flags=(CARD8) colors[i].flags; 841 (void) WriteBlob(image,sz_XWDColor,(unsigned char *) &color); 842 } 843 colors=(XColor *) RelinquishMagickMemory(colors); 844 } 845 /* 846 Allocate memory for pixels. 847 */ 848 length=3*bytes_per_line; 849 if (image->storage_class == PseudoClass) 850 length=bytes_per_line; 851 pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels)); 852 if (pixels == (unsigned char *) NULL) 853 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 854 (void) memset(pixels,0,length); 855 /* 856 Convert MIFF to XWD raster pixels. 857 */ 858 scanline_pad=(bytes_per_line-((image->columns*bits_per_pixel) >> 3)); 859 for (y=0; y < (ssize_t) image->rows; y++) 860 { 861 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 862 if (p == (const Quantum *) NULL) 863 break; 864 q=pixels; 865 if (image->storage_class == PseudoClass) 866 { 867 for (x=0; x < (ssize_t) image->columns; x++) 868 { 869 *q++=(unsigned char) GetPixelIndex(image,p); 870 p+=GetPixelChannels(image); 871 } 872 } 873 else 874 for (x=0; x < (ssize_t) image->columns; x++) 875 { 876 *q++=ScaleQuantumToChar(GetPixelRed(image,p)); 877 *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); 878 *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); 879 p+=GetPixelChannels(image); 880 } 881 for (x=0; x < (ssize_t) scanline_pad; x++) 882 *q++='\0'; 883 (void) WriteBlob(image,(size_t) (q-pixels),pixels); 884 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 885 image->rows); 886 if (status == MagickFalse) 887 break; 888 } 889 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 890 (void) CloseBlob(image); 891 return(MagickTrue); 892 } 893 #endif 894