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