2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % AAA N N IIIII M M AAA TTTTT EEEEE %
7 % A A NN N I MM MM A A T E %
8 % AAAAA N N N I M M M AAAAA T EEE %
9 % A A N NN I M M A A T E %
10 % A A N N IIIII M M A A T EEEEE %
13 % Methods to Interactively Animate an Image Sequence %
20 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % https://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/animate.h"
44 #include "MagickCore/animate-private.h"
45 #include "MagickCore/attribute.h"
46 #include "MagickCore/client.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/delegate.h"
53 #include "MagickCore/exception.h"
54 #include "MagickCore/exception-private.h"
55 #include "MagickCore/geometry.h"
56 #include "MagickCore/image-private.h"
57 #include "MagickCore/layer.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/log.h"
60 #include "MagickCore/image.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/monitor.h"
63 #include "MagickCore/monitor-private.h"
64 #include "MagickCore/option.h"
65 #include "MagickCore/pixel-accessor.h"
66 #include "MagickCore/property.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/string_.h"
69 #include "MagickCore/string-private.h"
70 #include "MagickCore/transform.h"
71 #include "MagickCore/utility.h"
72 #include "MagickCore/utility-private.h"
73 #include "MagickCore/version.h"
74 #include "MagickCore/widget.h"
75 #include "MagickCore/widget-private.h"
76 #include "MagickCore/xwindow.h"
77 #include "MagickCore/xwindow-private.h"
79 #if defined(MAGICKCORE_X11_DELEGATE)
81 Animate state declarations.
83 #define AutoReverseAnimationState 0x0004
84 #define ForwardAnimationState 0x0008
85 #define HighlightState 0x0010
86 #define PlayAnimationState 0x0020
87 #define RepeatAnimationState 0x0040
88 #define StepAnimationState 0x0080
98 " Press any button to map or unmap the Command widget.",
101 " The Command widget lists a number of sub-menus and commands.",
119 " Browse Documentation",
124 " Menu items with a indented triangle have a sub-menu. They",
125 " are represented above as the indented items. To access a",
126 " sub-menu item, move the pointer to the appropriate menu and",
127 " press a button and drag. When you find the desired sub-menu",
128 " item, release the button and the command is executed. Move",
129 " the pointer away from the sub-menu if you decide not to",
130 " execute a particular command.",
132 "KEYBOARD ACCELERATORS",
133 " Accelerators are one or two key presses that effect a",
134 " particular command. The keyboard accelerators that",
135 " animate(1) understands is:",
137 " Ctl+O Press to open an image from a file.",
139 " space Press to display the next image in the sequence.",
141 " < Press to speed-up the display of the images. Refer to",
142 " -delay for more information.",
144 " > Press to slow the display of the images. Refer to",
145 " -delay for more information.",
147 " F1 Press to display helpful information about animate(1).",
149 " Find Press to browse documentation about ImageMagick.",
151 " ? Press to display information about the image. Press",
152 " any key or button to erase the information.",
154 " This information is printed: image name; image size;",
155 " and the total number of unique colors in the image.",
157 " Ctl-q Press to discard all images and exit program.",
162 Constant declarations.
184 static const unsigned char
187 (unsigned char) 0xaa,
188 (unsigned char) 0x55,
189 (unsigned char) 0xaa,
190 (unsigned char) 0x55,
191 (unsigned char) 0xaa,
192 (unsigned char) 0x55,
193 (unsigned char) 0xaa,
198 (unsigned char) 0x00,
199 (unsigned char) 0x00,
200 (unsigned char) 0x00,
201 (unsigned char) 0x00,
202 (unsigned char) 0x00,
203 (unsigned char) 0x00,
204 (unsigned char) 0x00,
209 Enumeration declarations.
224 BrowseDocumentationCommand,
236 #define HighlightWidth 8
237 #define HighlightHeight 8
238 #define ShadowWidth 8
239 #define ShadowHeight 8
242 Forward declarations.
245 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
246 Image **,MagickStatusType *,ExceptionInfo *);
248 static MagickBooleanType
249 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 % A n i m a t e I m a g e s %
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 % AnimateImages() repeatedly displays an image sequence to any X window
263 % screen. It returns a value other than 0 if successful. Check the
264 % exception member of image to determine the reason for any failure.
266 % The format of the AnimateImages method is:
268 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
269 % Image *images,ExceptionInfo *exception)
271 % A description of each parameter follows:
273 % o image_info: the image info.
275 % o image: the image.
277 % o exception: return any errors or warnings in this structure.
280 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
281 Image *images,ExceptionInfo *exception)
298 assert(image_info != (const ImageInfo *) NULL);
299 assert(image_info->signature == MagickCoreSignature);
300 assert(images != (Image *) NULL);
301 assert(images->signature == MagickCoreSignature);
302 if (images->debug != MagickFalse)
303 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
304 display=XOpenDisplay(image_info->server_name);
305 if (display == (Display *) NULL)
307 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
308 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
311 if (exception->severity != UndefinedException)
312 CatchException(exception);
313 (void) XSetErrorHandler(XError);
314 resource_database=XGetResourceDatabase(display,GetClientName());
315 (void) memset(&resource_info,0,sizeof(XResourceInfo));
316 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
317 if (image_info->page != (char *) NULL)
318 resource_info.image_geometry=AcquireString(image_info->page);
319 resource_info.immutable=MagickTrue;
320 argv[0]=AcquireString(GetClientName());
321 (void) XAnimateImages(display,&resource_info,argv,1,images,exception);
322 (void) SetErrorHandler((ErrorHandler) NULL);
323 (void) SetWarningHandler((WarningHandler) NULL);
324 argv[0]=DestroyString(argv[0]);
325 (void) XCloseDisplay(display);
326 XDestroyResourceInfo(&resource_info);
327 status=exception->severity == UndefinedException ? MagickTrue : MagickFalse;
328 return(status != 0 ? MagickTrue : MagickFalse);
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336 + X M a g i c k C o m m a n d %
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 % XMagickCommand() makes a transform to the image or Image window as specified
343 % by a user menu button or keyboard command.
345 % The format of the XMagickCommand method is:
347 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
348 % XWindows *windows,const CommandType command_type,Image **image,
349 % MagickStatusType *state,ExceptionInfo *exception)
351 % A description of each parameter follows:
353 % o display: Specifies a connection to an X server; returned from
356 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
358 % o windows: Specifies a pointer to a XWindows structure.
360 % o image: the image; XMagickCommand
361 % may transform the image and return a new image pointer.
363 % o state: Specifies a MagickStatusType; XMagickCommand may return a
366 % o exception: return any errors or warnings in this structure.
370 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
371 XWindows *windows,const CommandType command_type,Image **image,
372 MagickStatusType *state,ExceptionInfo *exception)
387 Process user command.
389 nexus=NewImageList();
390 switch (command_type)
411 filenames[MagickPathExtent] = "*";
413 if (resource_info->immutable != MagickFalse)
416 Request file name from user.
418 XFileBrowserWidget(display,windows,"Animate",filenames);
419 if (*filenames == '\0')
420 return((Image *) NULL);
422 Expand the filenames.
424 filelist=(char **) AcquireMagickMemory(sizeof(char *));
425 if (filelist == (char **) NULL)
427 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
429 return((Image *) NULL);
432 filelist[0]=filenames;
433 status=ExpandFilenames(&number_files,&filelist);
434 if ((status == MagickFalse) || (number_files == 0))
436 for (i=0; i < number_files; i++)
437 filelist[i]=DestroyString(filelist[i]);
438 filelist=(char **) RelinquishMagickMemory(filelist);
439 if (number_files == 0)
441 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
442 return((Image *) NULL);
444 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
446 return((Image *) NULL);
448 read_info=CloneImageInfo(resource_info->image_info);
449 images=NewImageList();
450 XSetCursorState(display,windows,MagickTrue);
451 XCheckRefreshWindows(display,windows);
452 for (i=0; i < number_files; i++)
454 (void) CopyMagickString(read_info->filename,filelist[i],MagickPathExtent);
455 filelist[i]=DestroyString(filelist[i]);
456 *read_info->magick='\0';
457 next=ReadImage(read_info,exception);
458 CatchException(exception);
459 if (next != (Image *) NULL)
460 AppendImageToList(&images,next);
461 if (number_files <= 5)
463 proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
465 if (proceed == MagickFalse)
468 filelist=(char **) RelinquishMagickMemory(filelist);
469 read_info=DestroyImageInfo(read_info);
470 if (images == (Image *) NULL)
472 XSetCursorState(display,windows,MagickFalse);
473 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
474 return((Image *) NULL);
476 nexus=GetFirstImageInList(images);
483 basename[MagickPathExtent];
489 Window name is the base of the filename.
491 *state|=PlayAnimationState;
492 *state&=(~AutoReverseAnimationState);
493 GetPathComponent((*image)->magick_filename,BasePath,basename);
494 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
495 "%s: %s",MagickPackageName,basename);
496 if (resource_info->title != (char *) NULL)
501 title=InterpretImageProperties(resource_info->image_info,*image,
502 resource_info->title,exception);
503 (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
504 title=DestroyString(title);
506 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
509 XSetWMName(display,windows->image.id,&window_name);
510 (void) XFree((void *) window_name.value);
514 case StepBackwardCommand:
515 case StepForwardCommand:
517 *state|=StepAnimationState;
518 *state&=(~PlayAnimationState);
519 if (command_type == StepBackwardCommand)
520 *state&=(~ForwardAnimationState);
521 if (command_type == StepForwardCommand)
522 *state|=ForwardAnimationState;
523 if (resource_info->title != (char *) NULL)
529 *state|=RepeatAnimationState;
530 *state&=(~AutoReverseAnimationState);
531 *state|=PlayAnimationState;
534 case AutoReverseCommand:
536 *state|=AutoReverseAnimationState;
537 *state&=(~RepeatAnimationState);
538 *state|=PlayAnimationState;
546 status=XSaveImage(display,resource_info,windows,*image,exception);
547 if (status == MagickFalse)
550 message[MagickPathExtent];
552 (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
553 exception->reason != (char *) NULL ? exception->reason : "",
554 exception->description != (char *) NULL ? exception->description :
556 XNoticeWidget(display,windows,"Unable to save file:",message);
563 resource_info->delay++;
568 if (resource_info->delay == 0)
570 resource_info->delay--;
575 *state=ForwardAnimationState;
576 *state&=(~AutoReverseAnimationState);
581 *state&=(~ForwardAnimationState);
582 *state&=(~AutoReverseAnimationState);
587 XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image,
596 XTextViewWidget(display,resource_info,windows,MagickFalse,
597 "Help Viewer - Animate",AnimateHelp);
600 case BrowseDocumentationCommand:
610 Browse the ImageMagick documentation.
612 root_window=XRootWindow(display,XDefaultScreen(display));
613 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
614 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
615 if (mozilla_window != (Window) NULL)
618 command[MagickPathExtent],
622 Display documentation using Netscape remote control.
624 url=GetMagickHomeURL();
625 (void) FormatLocaleString(command,MagickPathExtent,
626 "openurl(%s,new-tab)",url);
627 url=DestroyString(url);
628 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
629 (void) XChangeProperty(display,mozilla_window,mozilla_atom,
630 XA_STRING,8,PropModeReplace,(unsigned char *) command,
631 (int) strlen(command));
632 XSetCursorState(display,windows,MagickFalse);
635 XSetCursorState(display,windows,MagickTrue);
636 XCheckRefreshWindows(display,windows);
637 status=InvokeDelegate(resource_info->image_info,*image,"browse",
638 (char *) NULL,exception);
639 if (status == MagickFalse)
640 XNoticeWidget(display,windows,"Unable to browse documentation",
642 XDelay(display,1500);
643 XSetCursorState(display,windows,MagickFalse);
648 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
649 GetMagickCopyright());
657 if (resource_info->confirm_exit == MagickFalse)
658 XClientMessage(display,windows->image.id,windows->im_protocols,
659 windows->im_exit,CurrentTime);
666 Confirm program exit.
668 status=XConfirmWidget(display,windows,"Do you really want to exit",
669 resource_info->client_name);
671 XClientMessage(display,windows->image.id,windows->im_protocols,
672 windows->im_exit,CurrentTime);
683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687 + X A n i m a t e B a c k g r o u n d I m a g e %
691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
693 % XAnimateBackgroundImage() animates an image sequence in the background of
696 % The format of the XAnimateBackgroundImage method is:
698 % void XAnimateBackgroundImage(Display *display,
699 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
701 % A description of each parameter follows:
703 % o display: Specifies a connection to an X server; returned from
706 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
708 % o images: the image list.
710 % o exception: return any errors or warnings in this structure.
714 #if defined(__cplusplus) || defined(c_plusplus)
718 static int SceneCompare(const void *x,const void *y)
724 image_1=(const Image **) x;
725 image_2=(const Image **) y;
726 return((int) ((*image_1)->scene-(*image_2)->scene));
729 #if defined(__cplusplus) || defined(c_plusplus)
733 MagickExport void XAnimateBackgroundImage(Display *display,
734 XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
737 geometry[MagickPathExtent],
738 visual_type[MagickPathExtent];
767 static XStandardColormap
771 *visual_info = (XVisualInfo *) NULL;
796 Determine target window.
798 assert(images != (Image *) NULL);
799 assert(images->signature == MagickCoreSignature);
800 if (images->debug != MagickFalse)
801 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
802 resources=(*resource_info);
803 window_info.id=(Window) NULL;
804 root_window=XRootWindow(display,XDefaultScreen(display));
805 if (LocaleCompare(resources.window_id,"root") == 0)
806 window_info.id=root_window;
809 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
810 window_info.id=XWindowByID(display,root_window,
811 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
812 if (window_info.id == (Window) NULL)
814 XWindowByName(display,root_window,resources.window_id);
816 if (window_info.id == (Window) NULL)
818 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
819 resources.window_id);
823 Determine window visual id.
825 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
826 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
827 (void) CopyMagickString(visual_type,"default",MagickPathExtent);
828 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
829 MagickTrue : MagickFalse;
830 if (status != MagickFalse)
831 (void) FormatLocaleString(visual_type,MagickPathExtent,"0x%lx",
832 XVisualIDFromVisual(window_attributes.visual));
833 if (visual_info == (XVisualInfo *) NULL)
836 Allocate standard colormap.
838 map_info=XAllocStandardColormap();
839 if (map_info == (XStandardColormap *) NULL)
840 ThrowXWindowFatalException(ResourceLimitFatalError,
841 "MemoryAllocationFailed",images->filename);
842 map_info->colormap=(Colormap) NULL;
843 pixel.pixels=(unsigned long *) NULL;
845 Initialize visual info.
847 resources.map_type=(char *) NULL;
848 resources.visual_type=visual_type;
849 visual_info=XBestVisualInfo(display,map_info,&resources);
850 if (visual_info == (XVisualInfo *) NULL)
851 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
854 Initialize window info.
856 window_info.ximage=(XImage *) NULL;
857 window_info.matte_image=(XImage *) NULL;
858 window_info.pixmap=(Pixmap) NULL;
859 window_info.matte_pixmap=(Pixmap) NULL;
862 Free previous root colors.
864 if (window_info.id == root_window)
865 XDestroyWindowColors(display,root_window);
866 coalesce_image=CoalesceImages(images,exception);
867 if (coalesce_image == (Image *) NULL)
868 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
870 images=coalesce_image;
871 if (resources.map_type == (char *) NULL)
872 if ((visual_info->klass != TrueColor) &&
873 (visual_info->klass != DirectColor))
879 Determine if the sequence of images has the identical colormap.
881 for (next=images; next != (Image *) NULL; )
883 next->alpha_trait=UndefinedPixelTrait;
884 if ((next->storage_class == DirectClass) ||
885 (next->colors != images->colors) ||
886 (next->colors > (size_t) visual_info->colormap_size))
888 for (i=0; i < (ssize_t) images->colors; i++)
889 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
891 if (i < (ssize_t) images->colors)
893 next=GetNextImageInList(next);
895 if (next != (Image *) NULL)
896 (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
900 Sort images by increasing scene number.
902 number_scenes=GetImageListLength(images);
903 image_list=ImageListToArray(images,exception);
904 if (image_list == (Image **) NULL)
905 ThrowXWindowFatalException(ResourceLimitFatalError,
906 "MemoryAllocationFailed",images->filename);
907 for (i=0; i < (ssize_t) number_scenes; i++)
908 if (image_list[i]->scene == 0)
910 if (i == (ssize_t) number_scenes)
911 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
913 Initialize Standard Colormap.
915 resources.colormap=SharedColormap;
916 display_image=image_list[0];
917 for (scene=0; scene < (int) number_scenes; scene++)
919 if ((resource_info->map_type != (char *) NULL) ||
920 (visual_info->klass == TrueColor) ||
921 (visual_info->klass == DirectColor))
922 (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
923 BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
924 if ((display_image->columns < image_list[scene]->columns) &&
925 (display_image->rows < image_list[scene]->rows))
926 display_image=image_list[scene];
928 if ((resource_info->map_type != (char *) NULL) ||
929 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
930 (void) SetImageType(display_image,display_image->alpha_trait !=
931 BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
932 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
935 Graphic context superclass.
937 context_values.background=pixel.background_color.pixel;
938 context_values.foreground=pixel.foreground_color.pixel;
939 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
940 (GCBackground | GCForeground),&context_values);
941 if (pixel.annotate_context == (GC) NULL)
942 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
945 Initialize Image window attributes.
947 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
948 &resources,&window_info);
952 window_info.width=(unsigned int) image_list[0]->columns;
953 window_info.height=(unsigned int) image_list[0]->rows;
954 if ((image_list[0]->columns != window_info.width) ||
955 (image_list[0]->rows != window_info.height))
956 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
957 image_list[0]->filename);
958 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>",
959 window_attributes.width,window_attributes.height);
960 geometry_info.width=window_info.width;
961 geometry_info.height=window_info.height;
962 geometry_info.x=(ssize_t) window_info.x;
963 geometry_info.y=(ssize_t) window_info.y;
964 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
965 &geometry_info.width,&geometry_info.height);
966 window_info.width=(unsigned int) geometry_info.width;
967 window_info.height=(unsigned int) geometry_info.height;
968 window_info.x=(int) geometry_info.x;
969 window_info.y=(int) geometry_info.y;
970 status=XMakeImage(display,&resources,&window_info,image_list[0],
971 window_info.width,window_info.height,exception);
972 if (status == MagickFalse)
973 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
977 if (display_image->debug != MagickFalse)
979 (void) LogMagickEvent(X11Event,GetMagickModule(),
980 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
981 image_list[0]->scene,(double) image_list[0]->columns,(double)
982 image_list[0]->rows);
983 if (image_list[0]->colors != 0)
984 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
985 image_list[0]->colors);
986 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
987 image_list[0]->magick);
990 Adjust image dimensions as specified by backdrop or geometry options.
992 width=window_info.width;
993 height=window_info.height;
994 if (resources.backdrop != MagickFalse)
997 Center image on window.
999 window_info.x=(int) (window_attributes.width/2)-
1000 (window_info.ximage->width/2);
1001 window_info.y=(int) (window_attributes.height/2)-
1002 (window_info.ximage->height/2);
1003 width=(unsigned int) window_attributes.width;
1004 height=(unsigned int) window_attributes.height;
1006 if (resources.image_geometry != (char *) NULL)
1009 default_geometry[MagickPathExtent];
1019 User specified geometry.
1021 size_hints=XAllocSizeHints();
1022 if (size_hints == (XSizeHints *) NULL)
1023 ThrowXWindowFatalException(ResourceLimitFatalError,
1024 "MemoryAllocationFailed",images->filename);
1025 size_hints->flags=0L;
1026 (void) FormatLocaleString(default_geometry,MagickPathExtent,"%ux%u",width,
1028 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1029 default_geometry,window_info.border_width,size_hints,&window_info.x,
1030 &window_info.y,(int *) &width,(int *) &height,&gravity);
1031 if (((flags & (XValue | YValue))) != 0)
1033 width=(unsigned int) window_attributes.width;
1034 height=(unsigned int) window_attributes.height;
1036 (void) XFree((void *) size_hints);
1039 Create the X pixmap.
1041 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1042 (unsigned int) height,window_info.depth);
1043 if (window_info.pixmap == (Pixmap) NULL)
1044 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1047 Display pixmap on the window.
1049 if (((unsigned int) width > window_info.width) ||
1050 ((unsigned int) height > window_info.height))
1051 (void) XFillRectangle(display,window_info.pixmap,
1052 window_info.annotate_context,0,0,(unsigned int) width,
1053 (unsigned int) height);
1054 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1055 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1056 window_info.height);
1057 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1058 (void) XClearWindow(display,window_info.id);
1060 Initialize image pixmaps structure.
1062 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1063 sizeof(*window_info.pixmaps));
1064 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1065 sizeof(*window_info.matte_pixmaps));
1066 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1067 (window_info.matte_pixmaps == (Pixmap *) NULL))
1068 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1070 window_info.pixmaps[0]=window_info.pixmap;
1071 window_info.matte_pixmaps[0]=window_info.pixmap;
1072 for (scene=1; scene < (int) number_scenes; scene++)
1081 window_info.pixmap=(Pixmap) NULL;
1082 window_info.matte_pixmap=(Pixmap) NULL;
1083 if ((resources.map_type != (char *) NULL) ||
1084 (visual_info->klass == TrueColor) ||
1085 (visual_info->klass == DirectColor))
1086 if (image_list[scene]->storage_class == PseudoClass)
1087 XGetPixelInfo(display,visual_info,map_info,&resources,
1088 image_list[scene],window_info.pixel_info);
1089 columns=(unsigned int) image_list[scene]->columns;
1090 rows=(unsigned int) image_list[scene]->rows;
1091 if ((image_list[scene]->columns != columns) ||
1092 (image_list[scene]->rows != rows))
1093 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1094 image_list[scene]->filename);
1095 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1096 columns,rows,exception);
1097 if (status == MagickFalse)
1098 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1100 if (display_image->debug != MagickFalse)
1102 (void) LogMagickEvent(X11Event,GetMagickModule(),
1103 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1104 image_list[scene]->filename,(double) columns,(double) rows);
1105 if (image_list[scene]->colors != 0)
1106 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1107 image_list[scene]->colors);
1108 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1109 image_list[scene]->magick);
1112 Create the X pixmap.
1114 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1116 if (window_info.pixmap == (Pixmap) NULL)
1117 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1120 Display pixmap on the window.
1122 if ((width > window_info.width) || (height > window_info.height))
1123 (void) XFillRectangle(display,window_info.pixmap,
1124 window_info.annotate_context,0,0,width,height);
1125 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1126 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1127 window_info.height);
1128 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1129 window_info.pixmap);
1130 (void) XClearWindow(display,window_info.id);
1131 window_info.pixmaps[scene]=window_info.pixmap;
1132 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1133 if (image_list[scene]->alpha_trait)
1134 (void) XClearWindow(display,window_info.id);
1135 delay=1000*image_list[scene]->delay/MagickMax(
1136 image_list[scene]->ticks_per_second,1L);
1137 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1139 window_info.pixel_info=(&pixel);
1141 Display pixmap on the window.
1143 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1148 for (scene=0; scene < (int) number_scenes; scene++)
1150 if (XEventsQueued(display,QueuedAfterFlush) > 0)
1152 (void) XNextEvent(display,&event);
1153 if (event.type == DestroyNotify)
1156 window_info.pixmap=window_info.pixmaps[scene];
1157 window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1158 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1159 window_info.pixmap);
1160 (void) XClearWindow(display,window_info.id);
1161 (void) XSync(display,MagickFalse);
1162 delay=1000*image_list[scene]->delay/MagickMax(
1163 image_list[scene]->ticks_per_second,1L);
1164 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1167 if (iterations == (ssize_t) image_list[0]->iterations)
1169 } while (event.type != DestroyNotify);
1170 (void) XSync(display,MagickFalse);
1171 image_list=(Image **) RelinquishMagickMemory(image_list);
1172 images=DestroyImageList(images);
1176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1180 + X A n i m a t e I m a g e s %
1184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1186 % XAnimateImages() displays an image via X11.
1188 % The format of the XAnimateImages method is:
1190 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1191 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1193 % A description of each parameter follows:
1195 % o display: Specifies a connection to an X server; returned from
1198 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1200 % o argv: Specifies the application's argument list.
1202 % o argc: Specifies the number of arguments.
1204 % o images: the image list.
1206 % o exception: return any errors or warnings in this structure.
1209 MagickExport Image *XAnimateImages(Display *display,
1210 XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1211 ExceptionInfo *exception)
1213 #define MagickMenus 4
1214 #define MaXWindows 8
1215 #define MagickTitle "Commands"
1253 "Browse Documentation",
1259 **Menus[MagickMenus]=
1267 static const CommandType
1291 DirectionCommands[]=
1299 BrowseDocumentationCommand,
1303 static const CommandType
1304 *Commands[MagickMenus]=
1313 command[MagickPathExtent],
1315 geometry[MagickPathExtent],
1316 resource_name[MagickPathExtent];
1353 working_directory[MagickPathExtent];
1359 *magick_windows[MaXWindows];
1413 assert(images != (Image *) NULL);
1414 assert(images->signature == MagickCoreSignature);
1415 if (images->debug != MagickFalse)
1416 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1417 warning_handler=(WarningHandler) NULL;
1418 windows=XSetWindows((XWindows *) ~0);
1419 if (windows != (XWindows *) NULL)
1424 if (*working_directory == '\0')
1425 (void) CopyMagickString(working_directory,".",MagickPathExtent);
1426 status=chdir(working_directory);
1428 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
1429 "UnableToOpenFile","%s",working_directory);
1430 warning_handler=resource_info->display_warnings ?
1431 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1432 warning_handler=resource_info->display_warnings ?
1433 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1441 Initialize window structure.
1443 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1445 if (p->storage_class == DirectClass)
1447 resource_info->colors=0;
1450 if (p->colors > resource_info->colors)
1451 resource_info->colors=p->colors;
1453 windows=XSetWindows(XInitializeWindows(display,resource_info));
1454 if (windows == (XWindows *) NULL)
1455 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1458 Initialize window id's.
1461 magick_windows[number_windows++]=(&windows->icon);
1462 magick_windows[number_windows++]=(&windows->backdrop);
1463 magick_windows[number_windows++]=(&windows->image);
1464 magick_windows[number_windows++]=(&windows->info);
1465 magick_windows[number_windows++]=(&windows->command);
1466 magick_windows[number_windows++]=(&windows->widget);
1467 magick_windows[number_windows++]=(&windows->popup);
1468 for (i=0; i < (ssize_t) number_windows; i++)
1469 magick_windows[i]->id=(Window) NULL;
1472 Initialize font info.
1474 if (windows->font_info != (XFontStruct *) NULL)
1475 (void) XFreeFont(display,windows->font_info);
1476 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1477 if (windows->font_info == (XFontStruct *) NULL)
1478 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1479 resource_info->font);
1481 Initialize Standard Colormap.
1483 map_info=windows->map_info;
1484 icon_map=windows->icon_map;
1485 visual_info=windows->visual_info;
1486 icon_visual=windows->icon_visual;
1487 pixel=windows->pixel_info;
1488 icon_pixel=windows->icon_pixel;
1489 font_info=windows->font_info;
1490 icon_resources=windows->icon_resources;
1491 class_hints=windows->class_hints;
1492 manager_hints=windows->manager_hints;
1493 root_window=XRootWindow(display,visual_info->screen);
1494 coalesce_image=CoalesceImages(images,exception);
1495 if (coalesce_image == (Image *) NULL)
1496 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1498 images=coalesce_image;
1499 if (resource_info->map_type == (char *) NULL)
1500 if ((visual_info->klass != TrueColor) &&
1501 (visual_info->klass != DirectColor))
1507 Determine if the sequence of images has the identical colormap.
1509 for (next=images; next != (Image *) NULL; )
1511 next->alpha_trait=UndefinedPixelTrait;
1512 if ((next->storage_class == DirectClass) ||
1513 (next->colors != images->colors) ||
1514 (next->colors > (size_t) visual_info->colormap_size))
1516 for (i=0; i < (ssize_t) images->colors; i++)
1517 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1519 if (i < (ssize_t) images->colors)
1521 next=GetNextImageInList(next);
1523 if (next != (Image *) NULL)
1524 (void) RemapImages(resource_info->quantize_info,images,
1525 (Image *) NULL,exception);
1528 Sort images by increasing scene number.
1530 number_scenes=GetImageListLength(images);
1531 image_list=ImageListToArray(images,exception);
1532 if (image_list == (Image **) NULL)
1533 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1535 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1536 if (image_list[scene]->scene == 0)
1538 if (scene == (ssize_t) number_scenes)
1539 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1541 Initialize Standard Colormap.
1543 nexus=NewImageList();
1544 display_image=image_list[0];
1545 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1547 if ((resource_info->map_type != (char *) NULL) ||
1548 (visual_info->klass == TrueColor) ||
1549 (visual_info->klass == DirectColor))
1550 (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
1551 BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
1552 if ((display_image->columns < image_list[scene]->columns) &&
1553 (display_image->rows < image_list[scene]->rows))
1554 display_image=image_list[scene];
1556 if (display_image->debug != MagickFalse)
1558 (void) LogMagickEvent(X11Event,GetMagickModule(),
1559 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1560 display_image->scene,(double) display_image->columns,(double)
1561 display_image->rows);
1562 if (display_image->colors != 0)
1563 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1564 display_image->colors);
1565 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1566 display_image->magick);
1568 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1569 map_info,pixel,exception);
1571 Initialize graphic context.
1573 windows->context.id=(Window) NULL;
1574 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1575 resource_info,&windows->context);
1576 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1577 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1578 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1579 manager_hints->flags=InputHint | StateHint;
1580 manager_hints->input=MagickFalse;
1581 manager_hints->initial_state=WithdrawnState;
1582 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1584 if (display_image->debug != MagickFalse)
1585 (void) LogMagickEvent(X11Event,GetMagickModule(),
1586 "Window id: 0x%lx (context)",windows->context.id);
1587 context_values.background=pixel->background_color.pixel;
1588 context_values.font=font_info->fid;
1589 context_values.foreground=pixel->foreground_color.pixel;
1590 context_values.graphics_exposures=MagickFalse;
1591 context_mask=(MagickStatusType)
1592 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1593 if (pixel->annotate_context != (GC) NULL)
1594 (void) XFreeGC(display,pixel->annotate_context);
1595 pixel->annotate_context=
1596 XCreateGC(display,windows->context.id,context_mask,&context_values);
1597 if (pixel->annotate_context == (GC) NULL)
1598 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1600 context_values.background=pixel->depth_color.pixel;
1601 if (pixel->widget_context != (GC) NULL)
1602 (void) XFreeGC(display,pixel->widget_context);
1603 pixel->widget_context=
1604 XCreateGC(display,windows->context.id,context_mask,&context_values);
1605 if (pixel->widget_context == (GC) NULL)
1606 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1608 context_values.background=pixel->foreground_color.pixel;
1609 context_values.foreground=pixel->background_color.pixel;
1610 context_values.plane_mask=
1611 context_values.background ^ context_values.foreground;
1612 if (pixel->highlight_context != (GC) NULL)
1613 (void) XFreeGC(display,pixel->highlight_context);
1614 pixel->highlight_context=XCreateGC(display,windows->context.id,
1615 (size_t) (context_mask | GCPlaneMask),&context_values);
1616 if (pixel->highlight_context == (GC) NULL)
1617 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1619 (void) XDestroyWindow(display,windows->context.id);
1621 Initialize icon window.
1623 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1624 icon_resources,&windows->icon);
1625 windows->icon.geometry=resource_info->icon_geometry;
1626 XBestIconSize(display,&windows->icon,display_image);
1627 windows->icon.attributes.colormap=
1628 XDefaultColormap(display,icon_visual->screen);
1629 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1630 manager_hints->flags=InputHint | StateHint;
1631 manager_hints->input=MagickFalse;
1632 manager_hints->initial_state=IconicState;
1633 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1635 if (display_image->debug != MagickFalse)
1636 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1639 Initialize graphic context for icon window.
1641 if (icon_pixel->annotate_context != (GC) NULL)
1642 (void) XFreeGC(display,icon_pixel->annotate_context);
1643 context_values.background=icon_pixel->background_color.pixel;
1644 context_values.foreground=icon_pixel->foreground_color.pixel;
1645 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1646 (size_t) (GCBackground | GCForeground),&context_values);
1647 if (icon_pixel->annotate_context == (GC) NULL)
1648 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1650 windows->icon.annotate_context=icon_pixel->annotate_context;
1652 Initialize Image window.
1654 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1655 resource_info,&windows->image);
1656 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1657 if (resource_info->use_shared_memory == MagickFalse)
1658 windows->image.shared_memory=MagickFalse;
1659 if (resource_info->title != (char *) NULL)
1664 title=InterpretImageProperties(resource_info->image_info,display_image,
1665 resource_info->title,exception);
1666 (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
1667 (void) CopyMagickString(windows->image.icon_name,title,MagickPathExtent);
1668 title=DestroyString(title);
1673 filename[MagickPathExtent];
1676 Window name is the base of the filename.
1678 GetPathComponent(display_image->magick_filename,TailPath,filename);
1679 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
1680 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1681 display_image->scene,(double) number_scenes);
1682 (void) CopyMagickString(windows->image.icon_name,filename,MagickPathExtent);
1684 if (resource_info->immutable != MagickFalse)
1685 windows->image.immutable=MagickTrue;
1686 windows->image.shape=MagickTrue;
1687 windows->image.geometry=resource_info->image_geometry;
1688 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
1689 XDisplayWidth(display,visual_info->screen),
1690 XDisplayHeight(display,visual_info->screen));
1691 geometry_info.width=display_image->columns;
1692 geometry_info.height=display_image->rows;
1695 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1696 &geometry_info.width,&geometry_info.height);
1697 windows->image.width=(unsigned int) geometry_info.width;
1698 windows->image.height=(unsigned int) geometry_info.height;
1699 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1700 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1701 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1702 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1703 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1704 resource_info,&windows->backdrop);
1705 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1708 Initialize backdrop window.
1710 windows->backdrop.x=0;
1711 windows->backdrop.y=0;
1712 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1713 windows->backdrop.flags=(size_t) (USSize | USPosition);
1714 windows->backdrop.width=(unsigned int)
1715 XDisplayWidth(display,visual_info->screen);
1716 windows->backdrop.height=(unsigned int)
1717 XDisplayHeight(display,visual_info->screen);
1718 windows->backdrop.border_width=0;
1719 windows->backdrop.immutable=MagickTrue;
1720 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1722 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1723 StructureNotifyMask;
1724 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1725 manager_hints->icon_window=windows->icon.id;
1726 manager_hints->input=MagickTrue;
1727 manager_hints->initial_state=
1728 resource_info->iconic ? IconicState : NormalState;
1729 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1730 &windows->backdrop);
1731 if (display_image->debug != MagickFalse)
1732 (void) LogMagickEvent(X11Event,GetMagickModule(),
1733 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1734 (void) XMapWindow(display,windows->backdrop.id);
1735 (void) XClearWindow(display,windows->backdrop.id);
1736 if (windows->image.id != (Window) NULL)
1738 (void) XDestroyWindow(display,windows->image.id);
1739 windows->image.id=(Window) NULL;
1742 Position image in the center the backdrop.
1744 windows->image.flags|=USPosition;
1745 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1746 (windows->image.width/2);
1747 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1748 (windows->image.height/2);
1750 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1751 manager_hints->icon_window=windows->icon.id;
1752 manager_hints->input=MagickTrue;
1753 manager_hints->initial_state=
1754 resource_info->iconic ? IconicState : NormalState;
1755 if (windows->group_leader.id != (Window) NULL)
1760 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1761 manager_hints->window_group=windows->group_leader.id;
1762 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1763 if (display_image->debug != MagickFalse)
1764 (void) LogMagickEvent(X11Event,GetMagickModule(),
1765 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1767 XMakeWindow(display,
1768 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1769 argv,argc,class_hints,manager_hints,&windows->image);
1770 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1771 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1772 if (windows->group_leader.id != (Window) NULL)
1773 (void) XSetTransientForHint(display,windows->image.id,
1774 windows->group_leader.id);
1775 if (display_image->debug != MagickFalse)
1776 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1779 Initialize Info widget.
1781 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1782 resource_info,&windows->info);
1783 (void) CloneString(&windows->info.name,"Info");
1784 (void) CloneString(&windows->info.icon_name,"Info");
1785 windows->info.border_width=1;
1788 windows->info.flags|=PPosition;
1789 windows->info.attributes.win_gravity=UnmapGravity;
1790 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1791 StructureNotifyMask;
1792 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1793 manager_hints->input=MagickFalse;
1794 manager_hints->initial_state=NormalState;
1795 manager_hints->window_group=windows->image.id;
1796 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1798 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1799 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1800 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1801 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1802 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1803 if (windows->image.mapped)
1804 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1805 if (display_image->debug != MagickFalse)
1806 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1809 Initialize Command widget.
1811 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1812 resource_info,&windows->command);
1813 windows->command.data=MagickMenus;
1814 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1815 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.command",
1816 resource_info->client_name);
1817 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1818 resource_name,"geometry",(char *) NULL);
1819 (void) CloneString(&windows->command.name,MagickTitle);
1820 windows->command.border_width=0;
1821 windows->command.flags|=PPosition;
1822 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1823 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1824 OwnerGrabButtonMask | StructureNotifyMask;
1825 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1826 manager_hints->input=MagickTrue;
1827 manager_hints->initial_state=NormalState;
1828 manager_hints->window_group=windows->image.id;
1829 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1831 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1832 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1834 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1835 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1836 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1837 if (display_image->debug != MagickFalse)
1838 (void) LogMagickEvent(X11Event,GetMagickModule(),
1839 "Window id: 0x%lx (command)",windows->command.id);
1841 Initialize Widget window.
1843 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1844 resource_info,&windows->widget);
1845 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.widget",
1846 resource_info->client_name);
1847 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1848 resource_name,"geometry",(char *) NULL);
1849 windows->widget.border_width=0;
1850 windows->widget.flags|=PPosition;
1851 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1852 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1853 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1854 StructureNotifyMask;
1855 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1856 manager_hints->input=MagickTrue;
1857 manager_hints->initial_state=NormalState;
1858 manager_hints->window_group=windows->image.id;
1859 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1861 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1862 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1863 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1864 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1865 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1866 if (display_image->debug != MagickFalse)
1867 (void) LogMagickEvent(X11Event,GetMagickModule(),
1868 "Window id: 0x%lx (widget)",windows->widget.id);
1870 Initialize popup window.
1872 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1873 resource_info,&windows->popup);
1874 windows->popup.border_width=0;
1875 windows->popup.flags|=PPosition;
1876 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1877 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1878 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1879 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1880 manager_hints->input=MagickTrue;
1881 manager_hints->initial_state=NormalState;
1882 manager_hints->window_group=windows->image.id;
1883 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1885 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1886 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1887 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1888 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1889 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1890 if (display_image->debug != MagickFalse)
1891 (void) LogMagickEvent(X11Event,GetMagickModule(),
1892 "Window id: 0x%lx (pop up)",windows->popup.id);
1894 Set out progress and warning handlers.
1896 if (warning_handler == (WarningHandler) NULL)
1898 warning_handler=resource_info->display_warnings ?
1899 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1900 warning_handler=resource_info->display_warnings ?
1901 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1904 Initialize X image structure.
1909 Initialize image pixmaps structure.
1911 window_changes.width=(int) windows->image.width;
1912 window_changes.height=(int) windows->image.height;
1913 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1914 (unsigned int) (CWWidth | CWHeight),&window_changes);
1915 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1916 sizeof(*windows->image.pixmaps));
1917 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1918 sizeof(*windows->image.pixmaps));
1919 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1920 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1921 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1923 if ((windows->image.mapped == MagickFalse) ||
1924 (windows->backdrop.id != (Window) NULL))
1925 (void) XMapWindow(display,windows->image.id);
1926 XSetCursorState(display,windows,MagickTrue);
1927 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1936 windows->image.pixmap=(Pixmap) NULL;
1937 windows->image.matte_pixmap=(Pixmap) NULL;
1938 if ((resource_info->map_type != (char *) NULL) ||
1939 (visual_info->klass == TrueColor) ||
1940 (visual_info->klass == DirectColor))
1941 if (image_list[scene]->storage_class == PseudoClass)
1942 XGetPixelInfo(display,visual_info,map_info,resource_info,
1943 image_list[scene],windows->image.pixel_info);
1944 columns=(unsigned int) image_list[scene]->columns;
1945 rows=(unsigned int) image_list[scene]->rows;
1946 if ((image_list[scene]->columns != columns) ||
1947 (image_list[scene]->rows != rows))
1948 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1949 image_list[scene]->filename);
1950 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1951 columns,rows,exception);
1952 if (status == MagickFalse)
1953 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1955 if (image_list[scene]->debug != MagickFalse)
1957 (void) LogMagickEvent(X11Event,GetMagickModule(),
1958 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1959 image_list[scene]->filename,(double) columns,(double) rows);
1960 if (image_list[scene]->colors != 0)
1961 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1962 image_list[scene]->colors);
1963 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1964 image_list[scene]->magick);
1967 Window name is the base of the filename.
1969 if (resource_info->title != (char *) NULL)
1974 title=InterpretImageProperties(resource_info->image_info,
1975 image_list[scene],resource_info->title,exception);
1976 (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
1977 title=DestroyString(title);
1981 p=image_list[scene]->magick_filename+
1982 strlen(image_list[scene]->magick_filename)-1;
1983 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1985 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
1986 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1987 (double) number_scenes);
1989 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1990 if (status != Success)
1992 XSetWMName(display,windows->image.id,&window_name);
1993 (void) XFree((void *) window_name.value);
1995 windows->image.pixmaps[scene]=windows->image.pixmap;
1996 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
2001 event.xexpose.width=(int) image_list[scene]->columns;
2002 event.xexpose.height=(int) image_list[scene]->rows;
2003 XRefreshWindow(display,&windows->image,&event);
2004 (void) XSync(display,MagickFalse);
2007 XSetCursorState(display,windows,MagickFalse);
2008 if (windows->command.mapped)
2009 (void) XMapRaised(display,windows->command.id);
2013 nexus=NewImageList();
2017 image=image_list[0];
2018 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2019 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2023 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2024 if ((state & PlayAnimationState) || (state & StepAnimationState))
2030 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2031 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2032 if (state & ForwardAnimationState)
2035 Forward animation: increment scene number.
2037 if (scene < ((ssize_t) number_scenes-1))
2042 if (iterations == (ssize_t) image_list[0]->iterations)
2047 if ((state & AutoReverseAnimationState) != 0)
2049 state&=(~ForwardAnimationState);
2054 if ((state & RepeatAnimationState) == 0)
2055 state&=(~PlayAnimationState);
2064 Reverse animation: decrement scene number.
2066 if (scene > first_scene)
2071 if (iterations == (ssize_t) image_list[0]->iterations)
2074 state&=(~RepeatAnimationState);
2076 if (state & AutoReverseAnimationState)
2078 state|=ForwardAnimationState;
2084 if ((state & RepeatAnimationState) == MagickFalse)
2085 state&=(~PlayAnimationState);
2086 scene=(ssize_t) number_scenes-1;
2090 scene=MagickMax(scene,0);
2091 image=image_list[scene];
2092 if ((image != (Image *) NULL) && (image->start_loop != 0))
2094 if ((state & StepAnimationState) ||
2095 (resource_info->title != (char *) NULL))
2098 Update window title.
2100 p=image_list[scene]->filename+
2101 strlen(image_list[scene]->filename)-1;
2102 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2104 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
2105 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2106 scene+1,(double) number_scenes);
2107 if (resource_info->title != (char *) NULL)
2112 title=InterpretImageProperties(resource_info->image_info,
2113 image,resource_info->title,exception);
2114 (void) CopyMagickString(windows->image.name,title,
2116 title=DestroyString(title);
2118 status=XStringListToTextProperty(&windows->image.name,1,
2120 if (status != Success)
2122 XSetWMName(display,windows->image.id,&window_name);
2123 (void) XFree((void *) window_name.value);
2127 Copy X pixmap to Image window.
2129 XGetPixelInfo(display,visual_info,map_info,resource_info,
2130 image_list[scene],windows->image.pixel_info);
2131 windows->image.ximage->width=(int) image->columns;
2132 windows->image.ximage->height=(int) image->rows;
2133 windows->image.pixmap=windows->image.pixmaps[scene];
2134 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2137 event.xexpose.width=(int) image->columns;
2138 event.xexpose.height=(int) image->rows;
2139 if ((state & ExitState) == 0)
2141 XRefreshWindow(display,&windows->image,&event);
2142 (void) XSync(display,MagickFalse);
2144 state&=(~StepAnimationState);
2145 if (pause != MagickFalse)
2146 for (i=0; i < (ssize_t) resource_info->pause; i++)
2151 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2158 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2159 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2160 *(command+length)='\0';
2161 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2163 XClientMessage(display,windows->image.id,
2164 windows->im_protocols,windows->im_exit,CurrentTime);
2173 Handle a window event.
2175 timestamp=time((time_t *) NULL);
2176 (void) XNextEvent(display,&event);
2177 if (windows->image.stasis == MagickFalse)
2178 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2179 MagickTrue : MagickFalse;
2180 if (event.xany.window == windows->command.id)
2186 Select a command from the Command widget.
2188 id=XCommandWidget(display,windows,CommandMenu,&event);
2191 (void) CopyMagickString(command,CommandMenu[id],MagickPathExtent);
2192 command_type=CommandMenus[id];
2193 if (id < MagickMenus)
2199 Select a command from a pop-up menu.
2201 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2205 (void) CopyMagickString(command,Menus[id][entry],MagickPathExtent);
2206 command_type=Commands[id][entry];
2208 if (command_type != NullCommand)
2209 nexus=XMagickCommand(display,resource_info,windows,
2210 command_type,&image,&state,exception);
2217 if (display_image->debug != MagickFalse)
2218 (void) LogMagickEvent(X11Event,GetMagickModule(),
2219 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2220 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2221 if ((event.xbutton.button == Button3) &&
2222 (event.xbutton.state & Mod1Mask))
2225 Convert Alt-Button3 to Button2.
2227 event.xbutton.button=Button2;
2228 event.xbutton.state&=(~Mod1Mask);
2230 if (event.xbutton.window == windows->backdrop.id)
2232 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2233 event.xbutton.time);
2236 if (event.xbutton.window == windows->image.id)
2238 if (resource_info->immutable != MagickFalse)
2244 Map/unmap Command widget.
2246 if (windows->command.mapped)
2247 (void) XWithdrawWindow(display,windows->command.id,
2248 windows->command.screen);
2251 (void) XCommandWidget(display,windows,CommandMenu,
2253 (void) XMapRaised(display,windows->command.id);
2260 if (display_image->debug != MagickFalse)
2261 (void) LogMagickEvent(X11Event,GetMagickModule(),
2262 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2263 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2268 if (display_image->debug != MagickFalse)
2269 (void) LogMagickEvent(X11Event,GetMagickModule(),
2270 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2271 event.xclient.window,(unsigned long) event.xclient.message_type,
2272 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2273 if (event.xclient.message_type == windows->im_protocols)
2275 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2278 Update graphic context and window colormap.
2280 for (i=0; i < (ssize_t) number_windows; i++)
2282 if (magick_windows[i]->id == windows->icon.id)
2284 context_values.background=pixel->background_color.pixel;
2285 context_values.foreground=pixel->foreground_color.pixel;
2286 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2287 context_mask,&context_values);
2288 (void) XChangeGC(display,magick_windows[i]->widget_context,
2289 context_mask,&context_values);
2290 context_values.background=pixel->foreground_color.pixel;
2291 context_values.foreground=pixel->background_color.pixel;
2292 context_values.plane_mask=
2293 context_values.background ^ context_values.foreground;
2294 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2295 (size_t) (context_mask | GCPlaneMask),
2297 magick_windows[i]->attributes.background_pixel=
2298 pixel->background_color.pixel;
2299 magick_windows[i]->attributes.border_pixel=
2300 pixel->border_color.pixel;
2301 magick_windows[i]->attributes.colormap=map_info->colormap;
2302 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2303 (unsigned long) magick_windows[i]->mask,
2304 &magick_windows[i]->attributes);
2306 if (windows->backdrop.id != (Window) NULL)
2307 (void) XInstallColormap(display,map_info->colormap);
2310 if (*event.xclient.data.l == (long) windows->im_exit)
2317 if (event.xclient.message_type == windows->dnd_protocols)
2335 Display image named by the Drag-and-Drop selection.
2337 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2339 selection=XInternAtom(display,"DndSelection",MagickFalse);
2340 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2341 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2343 if ((status != Success) || (length == 0))
2345 if (*event.xclient.data.l == 2)
2350 (void) CopyMagickString(resource_info->image_info->filename,
2351 (char *) data,MagickPathExtent);
2358 if (LocaleNCompare((char *) data,"file:",5) != 0)
2360 (void) XFree((void *) data);
2363 (void) CopyMagickString(resource_info->image_info->filename,
2364 ((char *) data)+5,MagickPathExtent);
2366 nexus=ReadImage(resource_info->image_info,exception);
2367 CatchException(exception);
2368 if (nexus != (Image *) NULL)
2370 (void) XFree((void *) data);
2374 If client window delete message, exit.
2376 if (event.xclient.message_type != windows->wm_protocols)
2378 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2380 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2381 (Time) event.xclient.data.l[1]);
2384 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2386 (void) XWithdrawWindow(display,event.xclient.window,
2387 visual_info->screen);
2388 if (event.xclient.window == windows->image.id)
2395 case ConfigureNotify:
2397 if (display_image->debug != MagickFalse)
2398 (void) LogMagickEvent(X11Event,GetMagickModule(),
2399 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2400 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2401 event.xconfigure.y,event.xconfigure.send_event);
2402 if (event.xconfigure.window == windows->image.id)
2404 if (event.xconfigure.send_event != 0)
2410 Position the transient windows relative of the Image window.
2412 if (windows->command.geometry == (char *) NULL)
2413 if (windows->command.mapped == MagickFalse)
2416 event.xconfigure.x-windows->command.width-25;
2417 windows->command.y=event.xconfigure.y;
2418 XConstrainWindowPosition(display,&windows->command);
2419 window_changes.x=windows->command.x;
2420 window_changes.y=windows->command.y;
2421 (void) XReconfigureWMWindow(display,windows->command.id,
2422 windows->command.screen,(unsigned int) (CWX | CWY),
2425 if (windows->widget.geometry == (char *) NULL)
2426 if (windows->widget.mapped == MagickFalse)
2429 event.xconfigure.x+event.xconfigure.width/10;
2431 event.xconfigure.y+event.xconfigure.height/10;
2432 XConstrainWindowPosition(display,&windows->widget);
2433 window_changes.x=windows->widget.x;
2434 window_changes.y=windows->widget.y;
2435 (void) XReconfigureWMWindow(display,windows->widget.id,
2436 windows->widget.screen,(unsigned int) (CWX | CWY),
2441 Image window has a new configuration.
2443 windows->image.width=(unsigned int) event.xconfigure.width;
2444 windows->image.height=(unsigned int) event.xconfigure.height;
2447 if (event.xconfigure.window == windows->icon.id)
2450 Icon window has a new configuration.
2452 windows->icon.width=(unsigned int) event.xconfigure.width;
2453 windows->icon.height=(unsigned int) event.xconfigure.height;
2461 Group leader has exited.
2463 if (display_image->debug != MagickFalse)
2464 (void) LogMagickEvent(X11Event,GetMagickModule(),
2465 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2466 if (event.xdestroywindow.window == windows->group_leader.id)
2476 Selectively install colormap.
2478 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2479 if (event.xcrossing.mode != NotifyUngrab)
2480 XInstallColormap(display,map_info->colormap);
2485 if (display_image->debug != MagickFalse)
2486 (void) LogMagickEvent(X11Event,GetMagickModule(),
2487 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2488 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2491 Repaint windows that are now exposed.
2493 if (event.xexpose.window == windows->image.id)
2495 windows->image.pixmap=windows->image.pixmaps[scene];
2496 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2497 XRefreshWindow(display,&windows->image,&event);
2500 if (event.xexpose.window == windows->icon.id)
2501 if (event.xexpose.count == 0)
2503 XRefreshWindow(display,&windows->icon,&event);
2514 Respond to a user key press.
2516 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2517 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2518 *(command+length)='\0';
2519 if (display_image->debug != MagickFalse)
2520 (void) LogMagickEvent(X11Event,GetMagickModule(),
2521 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2522 command_type=NullCommand;
2527 if ((event.xkey.state & ControlMask) == MagickFalse)
2529 command_type=OpenCommand;
2534 command_type=StepBackwardCommand;
2539 command_type=StepForwardCommand;
2544 command_type=FasterCommand;
2549 command_type=SlowerCommand;
2554 command_type=HelpCommand;
2559 command_type=BrowseDocumentationCommand;
2564 command_type=InfoCommand;
2570 command_type=QuitCommand;
2576 if (command_type != NullCommand)
2577 nexus=XMagickCommand(display,resource_info,windows,
2578 command_type,&image,&state,exception);
2584 Respond to a user key release.
2586 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2587 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2588 if (display_image->debug != MagickFalse)
2589 (void) LogMagickEvent(X11Event,GetMagickModule(),
2590 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2596 Selectively uninstall colormap.
2598 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2599 if (event.xcrossing.mode != NotifyUngrab)
2600 XUninstallColormap(display,map_info->colormap);
2605 if (display_image->debug != MagickFalse)
2606 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2608 if (event.xmap.window == windows->backdrop.id)
2610 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2612 windows->backdrop.mapped=MagickTrue;
2615 if (event.xmap.window == windows->image.id)
2617 if (windows->backdrop.id != (Window) NULL)
2618 (void) XInstallColormap(display,map_info->colormap);
2619 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2621 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2622 nexus=XMagickCommand(display,resource_info,windows,
2623 OpenCommand,&image,&state,exception);
2627 windows->image.mapped=MagickTrue;
2630 if (event.xmap.window == windows->info.id)
2632 windows->info.mapped=MagickTrue;
2635 if (event.xmap.window == windows->icon.id)
2638 Create an icon image.
2640 XMakeStandardColormap(display,icon_visual,icon_resources,
2641 display_image,icon_map,icon_pixel,exception);
2642 (void) XMakeImage(display,icon_resources,&windows->icon,
2643 display_image,windows->icon.width,windows->icon.height,
2645 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2646 windows->icon.pixmap);
2647 (void) XClearWindow(display,windows->icon.id);
2648 (void) XWithdrawWindow(display,windows->info.id,
2649 windows->info.screen);
2650 windows->icon.mapped=MagickTrue;
2653 if (event.xmap.window == windows->command.id)
2655 windows->command.mapped=MagickTrue;
2658 if (event.xmap.window == windows->popup.id)
2660 windows->popup.mapped=MagickTrue;
2663 if (event.xmap.window == windows->widget.id)
2665 windows->widget.mapped=MagickTrue;
2672 (void) XRefreshKeyboardMapping(&event.xmapping);
2677 case PropertyNotify:
2693 if (display_image->debug != MagickFalse)
2694 (void) LogMagickEvent(X11Event,GetMagickModule(),
2695 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2696 event.xproperty.window,(unsigned long) event.xproperty.atom,
2697 event.xproperty.state);
2698 if (event.xproperty.atom != windows->im_remote_command)
2701 Display image named by the remote command protocol.
2703 status=XGetWindowProperty(display,event.xproperty.window,
2704 event.xproperty.atom,0L,(long) MagickPathExtent,MagickFalse,(Atom)
2705 AnyPropertyType,&type,&format,&length,&after,&data);
2706 if ((status != Success) || (length == 0))
2708 (void) CopyMagickString(resource_info->image_info->filename,
2709 (char *) data,MagickPathExtent);
2710 nexus=ReadImage(resource_info->image_info,exception);
2711 CatchException(exception);
2712 if (nexus != (Image *) NULL)
2714 (void) XFree((void *) data);
2717 case ReparentNotify:
2719 if (display_image->debug != MagickFalse)
2720 (void) LogMagickEvent(X11Event,GetMagickModule(),
2721 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2722 event.xreparent.window);
2727 if (display_image->debug != MagickFalse)
2728 (void) LogMagickEvent(X11Event,GetMagickModule(),
2729 "Unmap Notify: 0x%lx",event.xunmap.window);
2730 if (event.xunmap.window == windows->backdrop.id)
2732 windows->backdrop.mapped=MagickFalse;
2735 if (event.xunmap.window == windows->image.id)
2737 windows->image.mapped=MagickFalse;
2740 if (event.xunmap.window == windows->info.id)
2742 windows->info.mapped=MagickFalse;
2745 if (event.xunmap.window == windows->icon.id)
2747 if (map_info->colormap == icon_map->colormap)
2748 XConfigureImageColormap(display,resource_info,windows,
2749 display_image,exception);
2750 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2752 windows->icon.mapped=MagickFalse;
2755 if (event.xunmap.window == windows->command.id)
2757 windows->command.mapped=MagickFalse;
2760 if (event.xunmap.window == windows->popup.id)
2762 if (windows->backdrop.id != (Window) NULL)
2763 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2765 windows->popup.mapped=MagickFalse;
2768 if (event.xunmap.window == windows->widget.id)
2770 if (windows->backdrop.id != (Window) NULL)
2771 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2773 windows->widget.mapped=MagickFalse;
2780 if (display_image->debug != MagickFalse)
2781 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2787 while (!(state & ExitState));
2788 image_list=(Image **) RelinquishMagickMemory(image_list);
2789 images=DestroyImageList(images);
2790 if ((windows->visual_info->klass == GrayScale) ||
2791 (windows->visual_info->klass == PseudoColor) ||
2792 (windows->visual_info->klass == DirectColor))
2797 if (windows->info.mapped)
2798 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2799 if (windows->command.mapped)
2800 (void) XWithdrawWindow(display,windows->command.id,
2801 windows->command.screen);
2803 if (resource_info->backdrop == MagickFalse)
2804 if (windows->backdrop.mapped)
2806 (void) XWithdrawWindow(display,windows->backdrop.id,\
2807 windows->backdrop.screen);
2808 (void) XDestroyWindow(display,windows->backdrop.id);
2809 windows->backdrop.id=(Window) NULL;
2810 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2811 (void) XDestroyWindow(display,windows->image.id);
2812 windows->image.id=(Window) NULL;
2814 XSetCursorState(display,windows,MagickTrue);
2815 XCheckRefreshWindows(display,windows);
2816 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2818 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2819 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2820 windows->image.pixmaps[scene]=(Pixmap) NULL;
2821 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2822 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2823 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2825 XSetCursorState(display,windows,MagickFalse);
2826 windows->image.pixmaps=(Pixmap *)
2827 RelinquishMagickMemory(windows->image.pixmaps);
2828 windows->image.matte_pixmaps=(Pixmap *)
2829 RelinquishMagickMemory(windows->image.matte_pixmaps);
2830 if (nexus == (Image *) NULL)
2835 if (windows->image.mapped != MagickFalse)
2836 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2837 XDelay(display,SuspendTime);
2838 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2839 if (resource_info->map_type == (char *) NULL)
2840 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2841 DestroyXResources();
2843 (void) XSync(display,MagickFalse);
2845 Restore our progress monitor and warning handlers.
2847 (void) SetErrorHandler(warning_handler);
2848 (void) SetWarningHandler(warning_handler);
2850 Change to home directory.
2852 directory=getcwd(working_directory,MagickPathExtent);
2854 if (*resource_info->home_directory == '\0')
2855 (void) CopyMagickString(resource_info->home_directory,".",MagickPathExtent);
2856 status=chdir(resource_info->home_directory);
2858 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2859 "UnableToOpenFile","%s",resource_info->home_directory);
2864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2868 + X S a v e I m a g e %
2872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2874 % XSaveImage() saves an image to a file.
2876 % The format of the XSaveImage method is:
2878 % MagickBooleanType XSaveImage(Display *display,
2879 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2880 % ExceptionInfo *exception)
2882 % A description of each parameter follows:
2884 % o status: Method XSaveImage return True if the image is
2885 % written. False is returned is there is a memory shortage or if the
2886 % image fails to write.
2888 % o display: Specifies a connection to an X server; returned from
2891 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2893 % o windows: Specifies a pointer to a XWindows structure.
2895 % o image: the image.
2898 static MagickBooleanType XSaveImage(Display *display,
2899 XResourceInfo *resource_info,XWindows *windows,Image *image,
2900 ExceptionInfo *exception)
2903 filename[MagickPathExtent];
2912 Request file name from user.
2914 if (resource_info->write_filename != (char *) NULL)
2915 (void) CopyMagickString(filename,resource_info->write_filename,
2920 path[MagickPathExtent];
2925 GetPathComponent(image->filename,HeadPath,path);
2926 GetPathComponent(image->filename,TailPath,filename);
2928 (void) CopyMagickString(path,".",MagickPathExtent);
2931 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2932 "UnableToOpenFile","%s",path);
2934 XFileBrowserWidget(display,windows,"Save",filename);
2935 if (*filename == '\0')
2937 if (IsPathAccessible(filename) != MagickFalse)
2943 File exists-- seek user's permission before overwriting.
2945 status=XConfirmWidget(display,windows,"Overwrite",filename);
2949 image_info=CloneImageInfo(resource_info->image_info);
2950 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
2951 (void) SetImageInfo(image_info,1,exception);
2952 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2953 (LocaleCompare(image_info->magick,"JPG") == 0))
2956 quality[MagickPathExtent];
2962 Request JPEG quality from user.
2964 (void) FormatLocaleString(quality,MagickPathExtent,"%.20g",(double)
2965 image_info->quality);
2966 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2968 if (*quality == '\0')
2970 image->quality=StringToUnsignedLong(quality);
2971 image_info->interlace=status != MagickFalse ? NoInterlace :
2974 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2975 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2976 (LocaleCompare(image_info->magick,"PS") == 0) ||
2977 (LocaleCompare(image_info->magick,"PS2") == 0))
2980 geometry[MagickPathExtent];
2983 Request page geometry from user.
2985 (void) CopyMagickString(geometry,PSPageGeometry,MagickPathExtent);
2986 if (LocaleCompare(image_info->magick,"PDF") == 0)
2987 (void) CopyMagickString(geometry,PSPageGeometry,MagickPathExtent);
2988 if (image_info->page != (char *) NULL)
2989 (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
2990 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2991 "Select page geometry:",geometry);
2992 if (*geometry != '\0')
2993 image_info->page=GetPageGeometry(geometry);
2998 image=GetFirstImageInList(image);
2999 status=WriteImages(image_info,image,filename,exception);
3000 if (status != MagickFalse)
3001 image->taint=MagickFalse;
3002 image_info=DestroyImageInfo(image_info);
3003 XSetCursorState(display,windows,MagickFalse);
3004 return(status != 0 ? MagickTrue : MagickFalse);
3009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3013 + A n i m a t e I m a g e s %
3017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3019 % AnimateImages() repeatedly displays an image sequence to any X window
3020 % screen. It returns a value other than 0 if successful. Check the
3021 % exception member of image to determine the reason for any failure.
3023 % The format of the AnimateImages method is:
3025 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3028 % A description of each parameter follows:
3030 % o image_info: the image info.
3032 % o image: the image.
3034 % o exception: return any errors or warnings in this structure.
3037 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3038 Image *image,ExceptionInfo *exception)
3040 assert(image_info != (const ImageInfo *) NULL);
3041 assert(image_info->signature == MagickCoreSignature);
3043 assert(image != (Image *) NULL);
3044 assert(image->signature == MagickCoreSignature);
3045 if (image->debug != MagickFalse)
3046 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3047 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
3048 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
3049 return(MagickFalse);