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-2012 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 % http://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/client.h"
46 #include "MagickCore/color.h"
47 #include "MagickCore/color-private.h"
48 #include "MagickCore/colorspace.h"
49 #include "MagickCore/constitute.h"
50 #include "MagickCore/delegate.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/geometry.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/layer.h"
56 #include "MagickCore/list.h"
57 #include "MagickCore/log.h"
58 #include "MagickCore/image.h"
59 #include "MagickCore/memory_.h"
60 #include "MagickCore/monitor.h"
61 #include "MagickCore/monitor-private.h"
62 #include "MagickCore/option.h"
63 #include "MagickCore/pixel-accessor.h"
64 #include "MagickCore/property.h"
65 #include "MagickCore/resource_.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/string-private.h"
68 #include "MagickCore/transform.h"
69 #include "MagickCore/utility.h"
70 #include "MagickCore/utility-private.h"
71 #include "MagickCore/version.h"
72 #include "MagickCore/widget.h"
73 #include "MagickCore/widget-private.h"
74 #include "MagickCore/xwindow.h"
75 #include "MagickCore/xwindow-private.h"
77 #if defined(MAGICKCORE_X11_DELEGATE)
79 Animate state declarations.
81 #define AutoReverseAnimationState 0x0004
82 #define ForwardAnimationState 0x0008
83 #define HighlightState 0x0010
84 #define PlayAnimationState 0x0020
85 #define RepeatAnimationState 0x0040
86 #define StepAnimationState 0x0080
96 " Press any button to map or unmap the Command widget.",
99 " The Command widget lists a number of sub-menus and commands.",
117 " Browse Documentation",
122 " Menu items with a indented triangle have a sub-menu. They",
123 " are represented above as the indented items. To access a",
124 " sub-menu item, move the pointer to the appropriate menu and",
125 " press a button and drag. When you find the desired sub-menu",
126 " item, release the button and the command is executed. Move",
127 " the pointer away from the sub-menu if you decide not to",
128 " execute a particular command.",
130 "KEYBOARD ACCELERATORS",
131 " Accelerators are one or two key presses that effect a",
132 " particular command. The keyboard accelerators that",
133 " animate(1) understands is:",
135 " Ctl+O Press to open an image from a file.",
137 " space Press to display the next image in the sequence.",
139 " < Press to speed-up the display of the images. Refer to",
140 " -delay for more information.",
142 " > Press to slow the display of the images. Refer to",
143 " -delay for more information.",
145 " F1 Press to display helpful information about animate(1).",
147 " Find Press to browse documentation about ImageMagick.",
149 " ? Press to display information about the image. Press",
150 " any key or button to erase the information.",
152 " This information is printed: image name; image size;",
153 " and the total number of unique colors in the image.",
155 " Ctl-q Press to discard all images and exit program.",
160 Constant declarations.
182 static const unsigned char
185 (unsigned char) 0xaa,
186 (unsigned char) 0x55,
187 (unsigned char) 0xaa,
188 (unsigned char) 0x55,
189 (unsigned char) 0xaa,
190 (unsigned char) 0x55,
191 (unsigned char) 0xaa,
196 (unsigned char) 0x00,
197 (unsigned char) 0x00,
198 (unsigned char) 0x00,
199 (unsigned char) 0x00,
200 (unsigned char) 0x00,
201 (unsigned char) 0x00,
202 (unsigned char) 0x00,
207 Enumeration declarations.
222 BrowseDocumentationCommand,
234 #define HighlightWidth 8
235 #define HighlightHeight 8
236 #define ShadowWidth 8
237 #define ShadowHeight 8
240 Forward declarations.
243 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
244 Image **,MagickStatusType *,ExceptionInfo *);
246 static MagickBooleanType
247 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 % A n i m a t e I m a g e s %
258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 % AnimateImages() repeatedly displays an image sequence to any X window
261 % screen. It returns a value other than 0 if successful. Check the
262 % exception member of image to determine the reason for any failure.
264 % The format of the AnimateImages method is:
266 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
267 % Image *images,ExceptionInfo *exception)
269 % A description of each parameter follows:
271 % o image_info: the image info.
273 % o image: the image.
275 % o exception: return any errors or warnings in this structure.
278 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
279 Image *images,ExceptionInfo *exception)
296 assert(image_info != (const ImageInfo *) NULL);
297 assert(image_info->signature == MagickSignature);
298 assert(images != (Image *) NULL);
299 assert(images->signature == MagickSignature);
300 if (images->debug != MagickFalse)
301 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
302 display=XOpenDisplay(image_info->server_name);
303 if (display == (Display *) NULL)
305 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
306 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
309 if (exception->severity != UndefinedException)
310 CatchException(exception);
311 (void) XSetErrorHandler(XError);
312 resource_database=XGetResourceDatabase(display,GetClientName());
313 (void) ResetMagickMemory(&resource_info,0,sizeof(XResourceInfo));
314 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
315 if (image_info->page != (char *) NULL)
316 resource_info.image_geometry=AcquireString(image_info->page);
317 resource_info.immutable=MagickTrue;
318 argv[0]=AcquireString(GetClientName());
319 (void) XAnimateImages(display,&resource_info,argv,1,images,exception);
320 (void) SetErrorHandler((ErrorHandler) NULL);
321 (void) SetWarningHandler((WarningHandler) NULL);
322 argv[0]=DestroyString(argv[0]);
323 (void) XCloseDisplay(display);
324 XDestroyResourceInfo(&resource_info);
325 status=exception->severity == UndefinedException ? MagickTrue : MagickFalse;
326 return(status != 0 ? MagickTrue : MagickFalse);
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 + X M a g i c k C o m m a n d %
338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 % XMagickCommand() makes a transform to the image or Image window as specified
341 % by a user menu button or keyboard command.
343 % The format of the XMagickCommand method is:
345 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
346 % XWindows *windows,const CommandType command_type,Image **image,
347 % MagickStatusType *state,ExceptionInfo *exception)
349 % A description of each parameter follows:
351 % o display: Specifies a connection to an X server; returned from
354 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
356 % o windows: Specifies a pointer to a XWindows structure.
358 % o image: the image; XMagickCommand
359 % may transform the image and return a new image pointer.
361 % o state: Specifies a MagickStatusType; XMagickCommand may return a
364 % o exception: return any errors or warnings in this structure.
368 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
369 XWindows *windows,const CommandType command_type,Image **image,
370 MagickStatusType *state,ExceptionInfo *exception)
385 Process user command.
387 nexus=NewImageList();
388 switch (command_type)
409 filenames[MaxTextExtent] = "*";
411 if (resource_info->immutable != MagickFalse)
414 Request file name from user.
416 XFileBrowserWidget(display,windows,"Animate",filenames);
417 if (*filenames == '\0')
418 return((Image *) NULL);
420 Expand the filenames.
422 filelist=(char **) AcquireMagickMemory(sizeof(char *));
423 if (filelist == (char **) NULL)
425 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
427 return((Image *) NULL);
430 filelist[0]=filenames;
431 status=ExpandFilenames(&number_files,&filelist);
432 if ((status == MagickFalse) || (number_files == 0))
434 if (number_files == 0)
436 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
437 return((Image *) NULL);
439 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
441 return((Image *) NULL);
443 read_info=CloneImageInfo(resource_info->image_info);
444 images=NewImageList();
445 XSetCursorState(display,windows,MagickTrue);
446 XCheckRefreshWindows(display,windows);
447 for (i=0; i < number_files; i++)
449 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
450 filelist[i]=DestroyString(filelist[i]);
451 *read_info->magick='\0';
452 next=ReadImage(read_info,exception);
453 CatchException(exception);
454 if (next != (Image *) NULL)
455 AppendImageToList(&images,next);
456 if (number_files <= 5)
458 proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
460 if (proceed == MagickFalse)
463 filelist=(char **) RelinquishMagickMemory(filelist);
464 read_info=DestroyImageInfo(read_info);
465 if (images == (Image *) NULL)
467 XSetCursorState(display,windows,MagickFalse);
468 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
469 return((Image *) NULL);
471 nexus=GetFirstImageInList(images);
478 basename[MaxTextExtent];
484 Window name is the base of the filename.
486 *state|=PlayAnimationState;
487 *state&=(~AutoReverseAnimationState);
488 GetPathComponent((*image)->magick_filename,BasePath,basename);
489 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
490 "%s: %s",MagickPackageName,basename);
491 if (resource_info->title != (char *) NULL)
496 title=InterpretImageProperties(resource_info->image_info,*image,
497 resource_info->title,exception);
498 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
499 title=DestroyString(title);
501 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
504 XSetWMName(display,windows->image.id,&window_name);
505 (void) XFree((void *) window_name.value);
509 case StepBackwardCommand:
510 case StepForwardCommand:
512 *state|=StepAnimationState;
513 *state&=(~PlayAnimationState);
514 if (command_type == StepBackwardCommand)
515 *state&=(~ForwardAnimationState);
516 if (command_type == StepForwardCommand)
517 *state|=ForwardAnimationState;
518 if (resource_info->title != (char *) NULL)
524 *state|=RepeatAnimationState;
525 *state&=(~AutoReverseAnimationState);
526 *state|=PlayAnimationState;
529 case AutoReverseCommand:
531 *state|=AutoReverseAnimationState;
532 *state&=(~RepeatAnimationState);
533 *state|=PlayAnimationState;
541 status=XSaveImage(display,resource_info,windows,*image,exception);
542 if (status == MagickFalse)
545 message[MaxTextExtent];
547 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
548 exception->reason != (char *) NULL ? exception->reason : "",
549 exception->description != (char *) NULL ? exception->description :
551 XNoticeWidget(display,windows,"Unable to save file:",message);
558 resource_info->delay++;
563 if (resource_info->delay == 0)
565 resource_info->delay--;
570 *state=ForwardAnimationState;
571 *state&=(~AutoReverseAnimationState);
576 *state&=(~ForwardAnimationState);
577 *state&=(~AutoReverseAnimationState);
582 XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image,
591 XTextViewWidget(display,resource_info,windows,MagickFalse,
592 "Help Viewer - Animate",AnimateHelp);
595 case BrowseDocumentationCommand:
605 Browse the ImageMagick documentation.
607 root_window=XRootWindow(display,XDefaultScreen(display));
608 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
609 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
610 if (mozilla_window != (Window) NULL)
613 command[MaxTextExtent],
617 Display documentation using Netscape remote control.
619 url=GetMagickHomeURL();
620 (void) FormatLocaleString(command,MaxTextExtent,
621 "openurl(%s,new-tab)",url);
622 url=DestroyString(url);
623 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
624 (void) XChangeProperty(display,mozilla_window,mozilla_atom,
625 XA_STRING,8,PropModeReplace,(unsigned char *) command,
626 (int) strlen(command));
627 XSetCursorState(display,windows,MagickFalse);
630 XSetCursorState(display,windows,MagickTrue);
631 XCheckRefreshWindows(display,windows);
632 status=InvokeDelegate(resource_info->image_info,*image,"browse",
633 (char *) NULL,exception);
634 if (status == MagickFalse)
635 XNoticeWidget(display,windows,"Unable to browse documentation",
637 XDelay(display,1500);
638 XSetCursorState(display,windows,MagickFalse);
643 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
644 GetMagickCopyright());
652 if (resource_info->confirm_exit == MagickFalse)
653 XClientMessage(display,windows->image.id,windows->im_protocols,
654 windows->im_exit,CurrentTime);
661 Confirm program exit.
663 status=XConfirmWidget(display,windows,"Do you really want to exit",
664 resource_info->client_name);
666 XClientMessage(display,windows->image.id,windows->im_protocols,
667 windows->im_exit,CurrentTime);
678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
682 + X A n i m a t e B a c k g r o u n d I m a g e %
686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688 % XAnimateBackgroundImage() animates an image sequence in the background of
691 % The format of the XAnimateBackgroundImage method is:
693 % void XAnimateBackgroundImage(Display *display,
694 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
696 % A description of each parameter follows:
698 % o display: Specifies a connection to an X server; returned from
701 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
703 % o images: the image list.
705 % o exception: return any errors or warnings in this structure.
709 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
716 #if defined(__cplusplus) || defined(c_plusplus)
720 static int SceneCompare(const void *x,const void *y)
726 image_1=(const Image **) x;
727 image_2=(const Image **) y;
728 return((int) ((*image_1)->scene-(*image_2)->scene));
731 #if defined(__cplusplus) || defined(c_plusplus)
735 MagickExport void XAnimateBackgroundImage(Display *display,
736 XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
739 geometry[MaxTextExtent],
740 visual_type[MaxTextExtent];
765 static XStandardColormap
769 *visual_info = (XVisualInfo *) NULL;
797 Determine target window.
799 assert(images != (Image *) NULL);
800 assert(images->signature == MagickSignature);
801 if (images->debug != MagickFalse)
802 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
803 resources=(*resource_info);
804 window_info.id=(Window) NULL;
805 root_window=XRootWindow(display,XDefaultScreen(display));
806 if (LocaleCompare(resources.window_id,"root") == 0)
807 window_info.id=root_window;
810 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
811 window_info.id=XWindowByID(display,root_window,
812 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
813 if (window_info.id == (Window) NULL)
815 XWindowByName(display,root_window,resources.window_id);
817 if (window_info.id == (Window) NULL)
819 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
820 resources.window_id);
824 Determine window visual id.
826 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
827 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
828 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
829 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
830 MagickTrue : MagickFalse;
831 if (status != MagickFalse)
832 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
833 XVisualIDFromVisual(window_attributes.visual));
834 if (visual_info == (XVisualInfo *) NULL)
837 Allocate standard colormap.
839 map_info=XAllocStandardColormap();
840 if (map_info == (XStandardColormap *) NULL)
841 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
843 map_info->colormap=(Colormap) NULL;
844 pixel.pixels=(unsigned long *) NULL;
846 Initialize visual info.
848 resources.map_type=(char *) NULL;
849 resources.visual_type=visual_type;
850 visual_info=XBestVisualInfo(display,map_info,&resources);
851 if (visual_info == (XVisualInfo *) NULL)
852 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
855 Initialize window info.
857 window_info.ximage=(XImage *) NULL;
858 window_info.matte_image=(XImage *) NULL;
859 window_info.pixmap=(Pixmap) NULL;
860 window_info.matte_pixmap=(Pixmap) NULL;
863 Free previous root colors.
865 if (window_info.id == root_window)
866 XDestroyWindowColors(display,root_window);
867 coalesce_image=CoalesceImages(images,exception);
868 if (coalesce_image == (Image *) NULL)
869 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
871 images=coalesce_image;
872 if (resources.map_type == (char *) NULL)
873 if ((visual_info->klass != TrueColor) &&
874 (visual_info->klass != DirectColor))
880 Determine if the sequence of images has the identical colormap.
882 for (next=images; next != (Image *) NULL; )
884 next->matte=MagickFalse;
885 if ((next->storage_class == DirectClass) ||
886 (next->colors != images->colors) ||
887 (next->colors > (size_t) visual_info->colormap_size))
889 for (i=0; i < (ssize_t) images->colors; i++)
890 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
892 if (i < (ssize_t) images->colors)
894 next=GetNextImageInList(next);
896 if (next != (Image *) NULL)
897 (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
901 Sort images by increasing scene number.
903 number_scenes=GetImageListLength(images);
904 image_list=ImageListToArray(images,exception);
905 if (image_list == (Image **) NULL)
906 ThrowXWindowFatalException(ResourceLimitFatalError,
907 "MemoryAllocationFailed",images->filename);
908 for (i=0; i < (ssize_t) number_scenes; i++)
909 if (image_list[i]->scene == 0)
911 if (i == (ssize_t) number_scenes)
912 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
914 Initialize Standard Colormap.
916 resources.colormap=SharedColormap;
917 display_image=image_list[0];
918 for (scene=0; scene < (int) number_scenes; scene++)
920 if ((resource_info->map_type != (char *) NULL) ||
921 (visual_info->klass == TrueColor) ||
922 (visual_info->klass == DirectColor))
923 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
924 MagickFalse ? TrueColorType : TrueColorMatteType,exception);
925 if ((display_image->columns < image_list[scene]->columns) &&
926 (display_image->rows < image_list[scene]->rows))
927 display_image=image_list[scene];
929 if ((resource_info->map_type != (char *) NULL) ||
930 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
931 (void) SetImageType(display_image,display_image->matte == MagickFalse ?
932 TrueColorType : TrueColorMatteType,exception);
933 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
936 Graphic context superclass.
938 context_values.background=pixel.background_color.pixel;
939 context_values.foreground=pixel.foreground_color.pixel;
940 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
941 (GCBackground | GCForeground),&context_values);
942 if (pixel.annotate_context == (GC) NULL)
943 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
946 Initialize Image window attributes.
948 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
949 &resources,&window_info);
953 window_info.width=(unsigned int) image_list[0]->columns;
954 window_info.height=(unsigned int) image_list[0]->rows;
955 if ((image_list[0]->columns != window_info.width) ||
956 (image_list[0]->rows != window_info.height))
957 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
958 image_list[0]->filename);
959 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
960 window_attributes.width,window_attributes.height);
961 geometry_info.width=window_info.width;
962 geometry_info.height=window_info.height;
963 geometry_info.x=(ssize_t) window_info.x;
964 geometry_info.y=(ssize_t) window_info.y;
965 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
966 &geometry_info.width,&geometry_info.height);
967 window_info.width=(unsigned int) geometry_info.width;
968 window_info.height=(unsigned int) geometry_info.height;
969 window_info.x=(int) geometry_info.x;
970 window_info.y=(int) geometry_info.y;
971 status=XMakeImage(display,&resources,&window_info,image_list[0],
972 window_info.width,window_info.height,exception);
973 if (status == MagickFalse)
974 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
978 if (display_image->debug != MagickFalse)
980 (void) LogMagickEvent(X11Event,GetMagickModule(),
981 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
982 image_list[0]->scene,(double) image_list[0]->columns,(double)
983 image_list[0]->rows);
984 if (image_list[0]->colors != 0)
985 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
986 image_list[0]->colors);
987 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
988 image_list[0]->magick);
991 Adjust image dimensions as specified by backdrop or geometry options.
993 width=window_info.width;
994 height=window_info.height;
995 if (resources.backdrop != MagickFalse)
998 Center image on window.
1000 window_info.x=(int) (window_attributes.width/2)-
1001 (window_info.ximage->width/2);
1002 window_info.y=(int) (window_attributes.height/2)-
1003 (window_info.ximage->height/2);
1004 width=(unsigned int) window_attributes.width;
1005 height=(unsigned int) window_attributes.height;
1007 if (resources.image_geometry != (char *) NULL)
1010 default_geometry[MaxTextExtent];
1020 User specified geometry.
1022 size_hints=XAllocSizeHints();
1023 if (size_hints == (XSizeHints *) NULL)
1024 ThrowXWindowFatalException(ResourceLimitFatalError,
1025 "MemoryAllocationFailed",images->filename);
1026 size_hints->flags=0L;
1027 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%ux%u",width,
1029 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1030 default_geometry,window_info.border_width,size_hints,&window_info.x,
1031 &window_info.y,(int *) &width,(int *) &height,&gravity);
1032 if (((flags & (XValue | YValue))) != 0)
1034 width=(unsigned int) window_attributes.width;
1035 height=(unsigned int) window_attributes.height;
1037 (void) XFree((void *) size_hints);
1040 Create the X pixmap.
1042 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1043 (unsigned int) height,window_info.depth);
1044 if (window_info.pixmap == (Pixmap) NULL)
1045 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1048 Display pixmap on the window.
1050 if (((unsigned int) width > window_info.width) ||
1051 ((unsigned int) height > window_info.height))
1052 (void) XFillRectangle(display,window_info.pixmap,
1053 window_info.annotate_context,0,0,(unsigned int) width,
1054 (unsigned int) height);
1055 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1056 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1057 window_info.height);
1058 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1059 (void) XClearWindow(display,window_info.id);
1061 Initialize image pixmaps structure.
1063 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1064 sizeof(*window_info.pixmaps));
1065 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1066 sizeof(*window_info.matte_pixmaps));
1067 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1068 (window_info.matte_pixmaps == (Pixmap *) NULL))
1069 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1071 window_info.pixmaps[0]=window_info.pixmap;
1072 window_info.matte_pixmaps[0]=window_info.pixmap;
1073 for (scene=1; scene < (int) number_scenes; scene++)
1082 window_info.pixmap=(Pixmap) NULL;
1083 window_info.matte_pixmap=(Pixmap) NULL;
1084 if ((resources.map_type != (char *) NULL) ||
1085 (visual_info->klass == TrueColor) ||
1086 (visual_info->klass == DirectColor))
1087 if (image_list[scene]->storage_class == PseudoClass)
1088 XGetPixelInfo(display,visual_info,map_info,&resources,
1089 image_list[scene],window_info.pixel_info);
1090 columns=(unsigned int) image_list[scene]->columns;
1091 rows=(unsigned int) image_list[scene]->rows;
1092 if ((image_list[scene]->columns != columns) ||
1093 (image_list[scene]->rows != rows))
1094 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1095 image_list[scene]->filename);
1096 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1097 columns,rows,exception);
1098 if (status == MagickFalse)
1099 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1101 if (display_image->debug != MagickFalse)
1103 (void) LogMagickEvent(X11Event,GetMagickModule(),
1104 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1105 image_list[scene]->filename,(double) columns,(double) rows);
1106 if (image_list[scene]->colors != 0)
1107 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1108 image_list[scene]->colors);
1109 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1110 image_list[scene]->magick);
1113 Create the X pixmap.
1115 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1117 if (window_info.pixmap == (Pixmap) NULL)
1118 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1121 Display pixmap on the window.
1123 if ((width > window_info.width) || (height > window_info.height))
1124 (void) XFillRectangle(display,window_info.pixmap,
1125 window_info.annotate_context,0,0,width,height);
1126 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1127 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1128 window_info.height);
1129 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1130 window_info.pixmap);
1131 (void) XClearWindow(display,window_info.id);
1132 window_info.pixmaps[scene]=window_info.pixmap;
1133 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1134 if (image_list[scene]->matte)
1135 (void) XClearWindow(display,window_info.id);
1136 delay=1000*image_list[scene]->delay/MagickMax(
1137 image_list[scene]->ticks_per_second,1L);
1138 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1140 window_info.pixel_info=(&pixel);
1142 Display pixmap on the window.
1144 (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));
1166 } while (event.type != DestroyNotify);
1167 (void) XSync(display,MagickFalse);
1168 image_list=(Image **) RelinquishMagickMemory(image_list);
1169 images=DestroyImageList(images);
1173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1177 + X A n i m a t e I m a g e s %
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183 % XAnimateImages() displays an image via X11.
1185 % The format of the XAnimateImages method is:
1187 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1188 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1190 % A description of each parameter follows:
1192 % o display: Specifies a connection to an X server; returned from
1195 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1197 % o argv: Specifies the application's argument list.
1199 % o argc: Specifies the number of arguments.
1201 % o images: the image list.
1203 % o exception: return any errors or warnings in this structure.
1206 MagickExport Image *XAnimateImages(Display *display,
1207 XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1208 ExceptionInfo *exception)
1210 #define MagickMenus 4
1211 #define MaXWindows 8
1212 #define MagickTitle "Commands"
1250 "Browse Documentation",
1256 **Menus[MagickMenus]=
1264 static const CommandType
1288 DirectionCommands[]=
1296 BrowseDocumentationCommand,
1300 static const CommandType
1301 *Commands[MagickMenus]=
1310 command[MaxTextExtent],
1312 geometry[MaxTextExtent],
1313 resource_name[MaxTextExtent];
1350 working_directory[MaxTextExtent];
1356 *magick_windows[MaXWindows];
1410 assert(images != (Image *) NULL);
1411 assert(images->signature == MagickSignature);
1412 if (images->debug != MagickFalse)
1413 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1414 warning_handler=(WarningHandler) NULL;
1415 windows=XSetWindows((XWindows *) ~0);
1416 if (windows != (XWindows *) NULL)
1421 status=chdir(working_directory);
1423 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
1424 "UnableToOpenFile","%s",working_directory);
1425 warning_handler=resource_info->display_warnings ?
1426 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1427 warning_handler=resource_info->display_warnings ?
1428 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1436 Initialize window structure.
1438 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1440 if (p->storage_class == DirectClass)
1442 resource_info->colors=0;
1445 if (p->colors > resource_info->colors)
1446 resource_info->colors=p->colors;
1448 windows=XSetWindows(XInitializeWindows(display,resource_info));
1449 if (windows == (XWindows *) NULL)
1450 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1453 Initialize window id's.
1456 magick_windows[number_windows++]=(&windows->icon);
1457 magick_windows[number_windows++]=(&windows->backdrop);
1458 magick_windows[number_windows++]=(&windows->image);
1459 magick_windows[number_windows++]=(&windows->info);
1460 magick_windows[number_windows++]=(&windows->command);
1461 magick_windows[number_windows++]=(&windows->widget);
1462 magick_windows[number_windows++]=(&windows->popup);
1463 for (i=0; i < (ssize_t) number_windows; i++)
1464 magick_windows[i]->id=(Window) NULL;
1467 Initialize font info.
1469 if (windows->font_info != (XFontStruct *) NULL)
1470 (void) XFreeFont(display,windows->font_info);
1471 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1472 if (windows->font_info == (XFontStruct *) NULL)
1473 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1474 resource_info->font);
1476 Initialize Standard Colormap.
1478 map_info=windows->map_info;
1479 icon_map=windows->icon_map;
1480 visual_info=windows->visual_info;
1481 icon_visual=windows->icon_visual;
1482 pixel=windows->pixel_info;
1483 icon_pixel=windows->icon_pixel;
1484 font_info=windows->font_info;
1485 icon_resources=windows->icon_resources;
1486 class_hints=windows->class_hints;
1487 manager_hints=windows->manager_hints;
1488 root_window=XRootWindow(display,visual_info->screen);
1489 coalesce_image=CoalesceImages(images,exception);
1490 if (coalesce_image == (Image *) NULL)
1491 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1493 images=coalesce_image;
1494 if (resource_info->map_type == (char *) NULL)
1495 if ((visual_info->klass != TrueColor) &&
1496 (visual_info->klass != DirectColor))
1502 Determine if the sequence of images has the identical colormap.
1504 for (next=images; next != (Image *) NULL; )
1506 next->matte=MagickFalse;
1507 if ((next->storage_class == DirectClass) ||
1508 (next->colors != images->colors) ||
1509 (next->colors > (size_t) visual_info->colormap_size))
1511 for (i=0; i < (ssize_t) images->colors; i++)
1512 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1514 if (i < (ssize_t) images->colors)
1516 next=GetNextImageInList(next);
1518 if (next != (Image *) NULL)
1519 (void) RemapImages(resource_info->quantize_info,images,
1520 (Image *) NULL,exception);
1523 Sort images by increasing scene number.
1525 number_scenes=GetImageListLength(images);
1526 image_list=ImageListToArray(images,exception);
1527 if (image_list == (Image **) NULL)
1528 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1530 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1531 if (image_list[scene]->scene == 0)
1533 if (scene == (ssize_t) number_scenes)
1534 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1536 Initialize Standard Colormap.
1538 nexus=NewImageList();
1539 display_image=image_list[0];
1540 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1542 if ((resource_info->map_type != (char *) NULL) ||
1543 (visual_info->klass == TrueColor) ||
1544 (visual_info->klass == DirectColor))
1545 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
1546 MagickFalse ? TrueColorType : TrueColorMatteType,exception);
1547 if ((display_image->columns < image_list[scene]->columns) &&
1548 (display_image->rows < image_list[scene]->rows))
1549 display_image=image_list[scene];
1551 if (display_image->debug != MagickFalse)
1553 (void) LogMagickEvent(X11Event,GetMagickModule(),
1554 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1555 display_image->scene,(double) display_image->columns,(double)
1556 display_image->rows);
1557 if (display_image->colors != 0)
1558 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1559 display_image->colors);
1560 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1561 display_image->magick);
1563 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1564 map_info,pixel,exception);
1566 Initialize graphic context.
1568 windows->context.id=(Window) NULL;
1569 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1570 resource_info,&windows->context);
1571 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1572 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1573 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1574 manager_hints->flags=InputHint | StateHint;
1575 manager_hints->input=MagickFalse;
1576 manager_hints->initial_state=WithdrawnState;
1577 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1579 if (display_image->debug != MagickFalse)
1580 (void) LogMagickEvent(X11Event,GetMagickModule(),
1581 "Window id: 0x%lx (context)",windows->context.id);
1582 context_values.background=pixel->background_color.pixel;
1583 context_values.font=font_info->fid;
1584 context_values.foreground=pixel->foreground_color.pixel;
1585 context_values.graphics_exposures=MagickFalse;
1586 context_mask=(MagickStatusType)
1587 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1588 if (pixel->annotate_context != (GC) NULL)
1589 (void) XFreeGC(display,pixel->annotate_context);
1590 pixel->annotate_context=
1591 XCreateGC(display,windows->context.id,context_mask,&context_values);
1592 if (pixel->annotate_context == (GC) NULL)
1593 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1595 context_values.background=pixel->depth_color.pixel;
1596 if (pixel->widget_context != (GC) NULL)
1597 (void) XFreeGC(display,pixel->widget_context);
1598 pixel->widget_context=
1599 XCreateGC(display,windows->context.id,context_mask,&context_values);
1600 if (pixel->widget_context == (GC) NULL)
1601 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1603 context_values.background=pixel->foreground_color.pixel;
1604 context_values.foreground=pixel->background_color.pixel;
1605 context_values.plane_mask=
1606 context_values.background ^ context_values.foreground;
1607 if (pixel->highlight_context != (GC) NULL)
1608 (void) XFreeGC(display,pixel->highlight_context);
1609 pixel->highlight_context=XCreateGC(display,windows->context.id,
1610 (size_t) (context_mask | GCPlaneMask),&context_values);
1611 if (pixel->highlight_context == (GC) NULL)
1612 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1614 (void) XDestroyWindow(display,windows->context.id);
1616 Initialize icon window.
1618 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1619 icon_resources,&windows->icon);
1620 windows->icon.geometry=resource_info->icon_geometry;
1621 XBestIconSize(display,&windows->icon,display_image);
1622 windows->icon.attributes.colormap=
1623 XDefaultColormap(display,icon_visual->screen);
1624 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1625 manager_hints->flags=InputHint | StateHint;
1626 manager_hints->input=MagickFalse;
1627 manager_hints->initial_state=IconicState;
1628 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1630 if (display_image->debug != MagickFalse)
1631 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1634 Initialize graphic context for icon window.
1636 if (icon_pixel->annotate_context != (GC) NULL)
1637 (void) XFreeGC(display,icon_pixel->annotate_context);
1638 context_values.background=icon_pixel->background_color.pixel;
1639 context_values.foreground=icon_pixel->foreground_color.pixel;
1640 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1641 (size_t) (GCBackground | GCForeground),&context_values);
1642 if (icon_pixel->annotate_context == (GC) NULL)
1643 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1645 windows->icon.annotate_context=icon_pixel->annotate_context;
1647 Initialize Image window.
1649 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1650 resource_info,&windows->image);
1651 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1652 if (resource_info->use_shared_memory == MagickFalse)
1653 windows->image.shared_memory=MagickFalse;
1654 if (resource_info->title != (char *) NULL)
1659 title=InterpretImageProperties(resource_info->image_info,display_image,
1660 resource_info->title,exception);
1661 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1662 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
1663 title=DestroyString(title);
1668 filename[MaxTextExtent];
1671 Window name is the base of the filename.
1673 GetPathComponent(display_image->magick_filename,TailPath,filename);
1674 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1675 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1676 display_image->scene,(double) number_scenes);
1677 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
1679 if (resource_info->immutable != MagickFalse)
1680 windows->image.immutable=MagickTrue;
1681 windows->image.shape=MagickTrue;
1682 windows->image.geometry=resource_info->image_geometry;
1683 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
1684 XDisplayWidth(display,visual_info->screen),
1685 XDisplayHeight(display,visual_info->screen));
1686 geometry_info.width=display_image->columns;
1687 geometry_info.height=display_image->rows;
1690 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1691 &geometry_info.width,&geometry_info.height);
1692 windows->image.width=(unsigned int) geometry_info.width;
1693 windows->image.height=(unsigned int) geometry_info.height;
1694 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1695 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1696 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1697 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1698 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1699 resource_info,&windows->backdrop);
1700 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1703 Initialize backdrop window.
1705 windows->backdrop.x=0;
1706 windows->backdrop.y=0;
1707 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1708 windows->backdrop.flags=(size_t) (USSize | USPosition);
1709 windows->backdrop.width=(unsigned int)
1710 XDisplayWidth(display,visual_info->screen);
1711 windows->backdrop.height=(unsigned int)
1712 XDisplayHeight(display,visual_info->screen);
1713 windows->backdrop.border_width=0;
1714 windows->backdrop.immutable=MagickTrue;
1715 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1717 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1718 StructureNotifyMask;
1719 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1720 manager_hints->icon_window=windows->icon.id;
1721 manager_hints->input=MagickTrue;
1722 manager_hints->initial_state=
1723 resource_info->iconic ? IconicState : NormalState;
1724 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1725 &windows->backdrop);
1726 if (display_image->debug != MagickFalse)
1727 (void) LogMagickEvent(X11Event,GetMagickModule(),
1728 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1729 (void) XMapWindow(display,windows->backdrop.id);
1730 (void) XClearWindow(display,windows->backdrop.id);
1731 if (windows->image.id != (Window) NULL)
1733 (void) XDestroyWindow(display,windows->image.id);
1734 windows->image.id=(Window) NULL;
1737 Position image in the center the backdrop.
1739 windows->image.flags|=USPosition;
1740 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1741 (windows->image.width/2);
1742 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1743 (windows->image.height/2);
1745 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1746 manager_hints->icon_window=windows->icon.id;
1747 manager_hints->input=MagickTrue;
1748 manager_hints->initial_state=
1749 resource_info->iconic ? IconicState : NormalState;
1750 if (windows->group_leader.id != (Window) NULL)
1755 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1756 manager_hints->window_group=windows->group_leader.id;
1757 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1758 if (display_image->debug != MagickFalse)
1759 (void) LogMagickEvent(X11Event,GetMagickModule(),
1760 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1762 XMakeWindow(display,
1763 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1764 argv,argc,class_hints,manager_hints,&windows->image);
1765 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1766 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1767 if (windows->group_leader.id != (Window) NULL)
1768 (void) XSetTransientForHint(display,windows->image.id,
1769 windows->group_leader.id);
1770 if (display_image->debug != MagickFalse)
1771 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1774 Initialize Info widget.
1776 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1777 resource_info,&windows->info);
1778 (void) CloneString(&windows->info.name,"Info");
1779 (void) CloneString(&windows->info.icon_name,"Info");
1780 windows->info.border_width=1;
1783 windows->info.flags|=PPosition;
1784 windows->info.attributes.win_gravity=UnmapGravity;
1785 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1786 StructureNotifyMask;
1787 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1788 manager_hints->input=MagickFalse;
1789 manager_hints->initial_state=NormalState;
1790 manager_hints->window_group=windows->image.id;
1791 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1793 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1794 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1795 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1796 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1797 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1798 if (windows->image.mapped)
1799 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1800 if (display_image->debug != MagickFalse)
1801 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1804 Initialize Command widget.
1806 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1807 resource_info,&windows->command);
1808 windows->command.data=MagickMenus;
1809 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1810 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
1811 resource_info->client_name);
1812 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1813 resource_name,"geometry",(char *) NULL);
1814 (void) CloneString(&windows->command.name,MagickTitle);
1815 windows->command.border_width=0;
1816 windows->command.flags|=PPosition;
1817 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1818 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1819 OwnerGrabButtonMask | StructureNotifyMask;
1820 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1821 manager_hints->input=MagickTrue;
1822 manager_hints->initial_state=NormalState;
1823 manager_hints->window_group=windows->image.id;
1824 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1826 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1827 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1829 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1830 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1831 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1832 if (display_image->debug != MagickFalse)
1833 (void) LogMagickEvent(X11Event,GetMagickModule(),
1834 "Window id: 0x%lx (command)",windows->command.id);
1836 Initialize Widget window.
1838 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1839 resource_info,&windows->widget);
1840 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
1841 resource_info->client_name);
1842 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1843 resource_name,"geometry",(char *) NULL);
1844 windows->widget.border_width=0;
1845 windows->widget.flags|=PPosition;
1846 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1847 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1848 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1849 StructureNotifyMask;
1850 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1851 manager_hints->input=MagickTrue;
1852 manager_hints->initial_state=NormalState;
1853 manager_hints->window_group=windows->image.id;
1854 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1856 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1857 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1858 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1859 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1860 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1861 if (display_image->debug != MagickFalse)
1862 (void) LogMagickEvent(X11Event,GetMagickModule(),
1863 "Window id: 0x%lx (widget)",windows->widget.id);
1865 Initialize popup window.
1867 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1868 resource_info,&windows->popup);
1869 windows->popup.border_width=0;
1870 windows->popup.flags|=PPosition;
1871 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1872 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1873 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1874 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1875 manager_hints->input=MagickTrue;
1876 manager_hints->initial_state=NormalState;
1877 manager_hints->window_group=windows->image.id;
1878 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1880 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1881 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1882 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1883 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1884 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1885 if (display_image->debug != MagickFalse)
1886 (void) LogMagickEvent(X11Event,GetMagickModule(),
1887 "Window id: 0x%lx (pop up)",windows->popup.id);
1889 Set out progress and warning handlers.
1891 if (warning_handler == (WarningHandler) NULL)
1893 warning_handler=resource_info->display_warnings ?
1894 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1895 warning_handler=resource_info->display_warnings ?
1896 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1899 Initialize X image structure.
1904 Initialize image pixmaps structure.
1906 window_changes.width=(int) windows->image.width;
1907 window_changes.height=(int) windows->image.height;
1908 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1909 (unsigned int) (CWWidth | CWHeight),&window_changes);
1910 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1911 sizeof(*windows->image.pixmaps));
1912 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1913 sizeof(*windows->image.pixmaps));
1914 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1915 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1916 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1918 if ((windows->image.mapped == MagickFalse) ||
1919 (windows->backdrop.id != (Window) NULL))
1920 (void) XMapWindow(display,windows->image.id);
1921 XSetCursorState(display,windows,MagickTrue);
1922 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1931 (void) TransformImageColorspace(image_list[scene],RGBColorspace,exception);
1932 windows->image.pixmap=(Pixmap) NULL;
1933 windows->image.matte_pixmap=(Pixmap) NULL;
1934 if ((resource_info->map_type != (char *) NULL) ||
1935 (visual_info->klass == TrueColor) ||
1936 (visual_info->klass == DirectColor))
1937 if (image_list[scene]->storage_class == PseudoClass)
1938 XGetPixelInfo(display,visual_info,map_info,resource_info,
1939 image_list[scene],windows->image.pixel_info);
1940 columns=(unsigned int) image_list[scene]->columns;
1941 rows=(unsigned int) image_list[scene]->rows;
1942 if ((image_list[scene]->columns != columns) ||
1943 (image_list[scene]->rows != rows))
1944 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1945 image_list[scene]->filename);
1946 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1947 columns,rows,exception);
1948 if (status == MagickFalse)
1949 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1951 if (image_list[scene]->debug != MagickFalse)
1953 (void) LogMagickEvent(X11Event,GetMagickModule(),
1954 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1955 image_list[scene]->filename,(double) columns,(double) rows);
1956 if (image_list[scene]->colors != 0)
1957 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1958 image_list[scene]->colors);
1959 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1960 image_list[scene]->magick);
1963 Window name is the base of the filename.
1965 if (resource_info->title != (char *) NULL)
1970 title=InterpretImageProperties(resource_info->image_info,
1971 image_list[scene],resource_info->title,exception);
1972 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1973 title=DestroyString(title);
1977 p=image_list[scene]->magick_filename+
1978 strlen(image_list[scene]->magick_filename)-1;
1979 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1981 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1982 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1983 (double) number_scenes);
1985 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1986 if (status != Success)
1988 XSetWMName(display,windows->image.id,&window_name);
1989 (void) XFree((void *) window_name.value);
1991 windows->image.pixmaps[scene]=windows->image.pixmap;
1992 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1997 event.xexpose.width=(int) image_list[scene]->columns;
1998 event.xexpose.height=(int) image_list[scene]->rows;
1999 XRefreshWindow(display,&windows->image,&event);
2000 (void) XSync(display,MagickFalse);
2003 XSetCursorState(display,windows,MagickFalse);
2004 if (windows->command.mapped)
2005 (void) XMapRaised(display,windows->command.id);
2009 nexus=NewImageList();
2013 image=image_list[0];
2014 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2015 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2019 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2020 if ((state & PlayAnimationState) || (state & StepAnimationState))
2026 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2027 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2028 if (state & ForwardAnimationState)
2031 Forward animation: increment scene number.
2033 if (scene < ((ssize_t) number_scenes-1))
2038 if (iterations == (ssize_t) image_list[0]->iterations)
2043 if ((state & AutoReverseAnimationState) != 0)
2045 state&=(~ForwardAnimationState);
2050 if ((state & RepeatAnimationState) == 0)
2051 state&=(~PlayAnimationState);
2060 Reverse animation: decrement scene number.
2062 if (scene > first_scene)
2067 if (iterations == (ssize_t) image_list[0]->iterations)
2070 state&=(~RepeatAnimationState);
2072 if (state & AutoReverseAnimationState)
2074 state|=ForwardAnimationState;
2080 if ((state & RepeatAnimationState) == MagickFalse)
2081 state&=(~PlayAnimationState);
2082 scene=(ssize_t) number_scenes-1;
2086 scene=MagickMax(scene,0);
2087 image=image_list[scene];
2088 if ((image != (Image *) NULL) && (image->start_loop != 0))
2090 if ((state & StepAnimationState) ||
2091 (resource_info->title != (char *) NULL))
2094 Update window title.
2096 p=image_list[scene]->filename+
2097 strlen(image_list[scene]->filename)-1;
2098 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2100 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
2101 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2102 scene+1,(double) number_scenes);
2103 if (resource_info->title != (char *) NULL)
2108 title=InterpretImageProperties(resource_info->image_info,
2109 image,resource_info->title,exception);
2110 (void) CopyMagickString(windows->image.name,title,
2112 title=DestroyString(title);
2114 status=XStringListToTextProperty(&windows->image.name,1,
2116 if (status != Success)
2118 XSetWMName(display,windows->image.id,&window_name);
2119 (void) XFree((void *) window_name.value);
2123 Copy X pixmap to Image window.
2125 XGetPixelInfo(display,visual_info,map_info,resource_info,
2126 image_list[scene],windows->image.pixel_info);
2127 windows->image.ximage->width=(int) image->columns;
2128 windows->image.ximage->height=(int) image->rows;
2129 windows->image.pixmap=windows->image.pixmaps[scene];
2130 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2133 event.xexpose.width=(int) image->columns;
2134 event.xexpose.height=(int) image->rows;
2135 if ((state & ExitState) == 0)
2137 XRefreshWindow(display,&windows->image,&event);
2138 (void) XSync(display,MagickFalse);
2140 state&=(~StepAnimationState);
2141 if (pause != MagickFalse)
2142 for (i=0; i < (ssize_t) resource_info->pause; i++)
2147 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2154 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2155 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2156 *(command+length)='\0';
2157 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2159 XClientMessage(display,windows->image.id,
2160 windows->im_protocols,windows->im_exit,CurrentTime);
2169 Handle a window event.
2171 timestamp=time((time_t *) NULL);
2172 (void) XNextEvent(display,&event);
2173 if (windows->image.stasis == MagickFalse)
2174 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2175 MagickTrue : MagickFalse;
2176 if (event.xany.window == windows->command.id)
2182 Select a command from the Command widget.
2184 id=XCommandWidget(display,windows,CommandMenu,&event);
2187 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
2188 command_type=CommandMenus[id];
2189 if (id < MagickMenus)
2195 Select a command from a pop-up menu.
2197 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2201 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
2202 command_type=Commands[id][entry];
2204 if (command_type != NullCommand)
2205 nexus=XMagickCommand(display,resource_info,windows,
2206 command_type,&image,&state,exception);
2213 if (display_image->debug != MagickFalse)
2214 (void) LogMagickEvent(X11Event,GetMagickModule(),
2215 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2216 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2217 if ((event.xbutton.button == Button3) &&
2218 (event.xbutton.state & Mod1Mask))
2221 Convert Alt-Button3 to Button2.
2223 event.xbutton.button=Button2;
2224 event.xbutton.state&=(~Mod1Mask);
2226 if (event.xbutton.window == windows->backdrop.id)
2228 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2229 event.xbutton.time);
2232 if (event.xbutton.window == windows->image.id)
2234 if (resource_info->immutable != MagickFalse)
2240 Map/unmap Command widget.
2242 if (windows->command.mapped)
2243 (void) XWithdrawWindow(display,windows->command.id,
2244 windows->command.screen);
2247 (void) XCommandWidget(display,windows,CommandMenu,
2249 (void) XMapRaised(display,windows->command.id);
2256 if (display_image->debug != MagickFalse)
2257 (void) LogMagickEvent(X11Event,GetMagickModule(),
2258 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2259 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2264 if (display_image->debug != MagickFalse)
2265 (void) LogMagickEvent(X11Event,GetMagickModule(),
2266 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2267 event.xclient.window,(unsigned long) event.xclient.message_type,
2268 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2269 if (event.xclient.message_type == windows->im_protocols)
2271 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2274 Update graphic context and window colormap.
2276 for (i=0; i < (ssize_t) number_windows; i++)
2278 if (magick_windows[i]->id == windows->icon.id)
2280 context_values.background=pixel->background_color.pixel;
2281 context_values.foreground=pixel->foreground_color.pixel;
2282 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2283 context_mask,&context_values);
2284 (void) XChangeGC(display,magick_windows[i]->widget_context,
2285 context_mask,&context_values);
2286 context_values.background=pixel->foreground_color.pixel;
2287 context_values.foreground=pixel->background_color.pixel;
2288 context_values.plane_mask=
2289 context_values.background ^ context_values.foreground;
2290 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2291 (size_t) (context_mask | GCPlaneMask),
2293 magick_windows[i]->attributes.background_pixel=
2294 pixel->background_color.pixel;
2295 magick_windows[i]->attributes.border_pixel=
2296 pixel->border_color.pixel;
2297 magick_windows[i]->attributes.colormap=map_info->colormap;
2298 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2299 (unsigned long) magick_windows[i]->mask,
2300 &magick_windows[i]->attributes);
2302 if (windows->backdrop.id != (Window) NULL)
2303 (void) XInstallColormap(display,map_info->colormap);
2306 if (*event.xclient.data.l == (long) windows->im_exit)
2313 if (event.xclient.message_type == windows->dnd_protocols)
2331 Display image named by the Drag-and-Drop selection.
2333 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2335 selection=XInternAtom(display,"DndSelection",MagickFalse);
2336 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2337 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2339 if ((status != Success) || (length == 0))
2341 if (*event.xclient.data.l == 2)
2346 (void) CopyMagickString(resource_info->image_info->filename,
2347 (char *) data,MaxTextExtent);
2354 if (LocaleNCompare((char *) data,"file:",5) != 0)
2356 (void) XFree((void *) data);
2359 (void) CopyMagickString(resource_info->image_info->filename,
2360 ((char *) data)+5,MaxTextExtent);
2362 nexus=ReadImage(resource_info->image_info,exception);
2363 CatchException(exception);
2364 if (nexus != (Image *) NULL)
2366 (void) XFree((void *) data);
2370 If client window delete message, exit.
2372 if (event.xclient.message_type != windows->wm_protocols)
2374 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2376 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2377 (Time) event.xclient.data.l[1]);
2380 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2382 (void) XWithdrawWindow(display,event.xclient.window,
2383 visual_info->screen);
2384 if (event.xclient.window == windows->image.id)
2391 case ConfigureNotify:
2393 if (display_image->debug != MagickFalse)
2394 (void) LogMagickEvent(X11Event,GetMagickModule(),
2395 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2396 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2397 event.xconfigure.y,event.xconfigure.send_event);
2398 if (event.xconfigure.window == windows->image.id)
2400 if (event.xconfigure.send_event != 0)
2406 Position the transient windows relative of the Image window.
2408 if (windows->command.geometry == (char *) NULL)
2409 if (windows->command.mapped == MagickFalse)
2412 event.xconfigure.x-windows->command.width-25;
2413 windows->command.y=event.xconfigure.y;
2414 XConstrainWindowPosition(display,&windows->command);
2415 window_changes.x=windows->command.x;
2416 window_changes.y=windows->command.y;
2417 (void) XReconfigureWMWindow(display,windows->command.id,
2418 windows->command.screen,(unsigned int) (CWX | CWY),
2421 if (windows->widget.geometry == (char *) NULL)
2422 if (windows->widget.mapped == MagickFalse)
2425 event.xconfigure.x+event.xconfigure.width/10;
2427 event.xconfigure.y+event.xconfigure.height/10;
2428 XConstrainWindowPosition(display,&windows->widget);
2429 window_changes.x=windows->widget.x;
2430 window_changes.y=windows->widget.y;
2431 (void) XReconfigureWMWindow(display,windows->widget.id,
2432 windows->widget.screen,(unsigned int) (CWX | CWY),
2437 Image window has a new configuration.
2439 windows->image.width=(unsigned int) event.xconfigure.width;
2440 windows->image.height=(unsigned int) event.xconfigure.height;
2443 if (event.xconfigure.window == windows->icon.id)
2446 Icon window has a new configuration.
2448 windows->icon.width=(unsigned int) event.xconfigure.width;
2449 windows->icon.height=(unsigned int) event.xconfigure.height;
2457 Group leader has exited.
2459 if (display_image->debug != MagickFalse)
2460 (void) LogMagickEvent(X11Event,GetMagickModule(),
2461 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2462 if (event.xdestroywindow.window == windows->group_leader.id)
2472 Selectively install colormap.
2474 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2475 if (event.xcrossing.mode != NotifyUngrab)
2476 XInstallColormap(display,map_info->colormap);
2481 if (display_image->debug != MagickFalse)
2482 (void) LogMagickEvent(X11Event,GetMagickModule(),
2483 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2484 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2487 Repaint windows that are now exposed.
2489 if (event.xexpose.window == windows->image.id)
2491 windows->image.pixmap=windows->image.pixmaps[scene];
2492 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2493 XRefreshWindow(display,&windows->image,&event);
2496 if (event.xexpose.window == windows->icon.id)
2497 if (event.xexpose.count == 0)
2499 XRefreshWindow(display,&windows->icon,&event);
2510 Respond to a user key press.
2512 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2513 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2514 *(command+length)='\0';
2515 if (display_image->debug != MagickFalse)
2516 (void) LogMagickEvent(X11Event,GetMagickModule(),
2517 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2518 command_type=NullCommand;
2523 if ((event.xkey.state & ControlMask) == MagickFalse)
2525 command_type=OpenCommand;
2530 command_type=StepBackwardCommand;
2535 command_type=StepForwardCommand;
2540 command_type=FasterCommand;
2545 command_type=SlowerCommand;
2550 command_type=HelpCommand;
2555 command_type=BrowseDocumentationCommand;
2560 command_type=InfoCommand;
2566 command_type=QuitCommand;
2572 if (command_type != NullCommand)
2573 nexus=XMagickCommand(display,resource_info,windows,
2574 command_type,&image,&state,exception);
2580 Respond to a user key release.
2582 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2583 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2584 if (display_image->debug != MagickFalse)
2585 (void) LogMagickEvent(X11Event,GetMagickModule(),
2586 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2592 Selectively uninstall colormap.
2594 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2595 if (event.xcrossing.mode != NotifyUngrab)
2596 XUninstallColormap(display,map_info->colormap);
2601 if (display_image->debug != MagickFalse)
2602 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2604 if (event.xmap.window == windows->backdrop.id)
2606 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2608 windows->backdrop.mapped=MagickTrue;
2611 if (event.xmap.window == windows->image.id)
2613 if (windows->backdrop.id != (Window) NULL)
2614 (void) XInstallColormap(display,map_info->colormap);
2615 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2617 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2618 nexus=XMagickCommand(display,resource_info,windows,
2619 OpenCommand,&image,&state,exception);
2623 windows->image.mapped=MagickTrue;
2626 if (event.xmap.window == windows->info.id)
2628 windows->info.mapped=MagickTrue;
2631 if (event.xmap.window == windows->icon.id)
2634 Create an icon image.
2636 XMakeStandardColormap(display,icon_visual,icon_resources,
2637 display_image,icon_map,icon_pixel,exception);
2638 (void) XMakeImage(display,icon_resources,&windows->icon,
2639 display_image,windows->icon.width,windows->icon.height,
2641 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2642 windows->icon.pixmap);
2643 (void) XClearWindow(display,windows->icon.id);
2644 (void) XWithdrawWindow(display,windows->info.id,
2645 windows->info.screen);
2646 windows->icon.mapped=MagickTrue;
2649 if (event.xmap.window == windows->command.id)
2651 windows->command.mapped=MagickTrue;
2654 if (event.xmap.window == windows->popup.id)
2656 windows->popup.mapped=MagickTrue;
2659 if (event.xmap.window == windows->widget.id)
2661 windows->widget.mapped=MagickTrue;
2668 (void) XRefreshKeyboardMapping(&event.xmapping);
2673 case PropertyNotify:
2689 if (display_image->debug != MagickFalse)
2690 (void) LogMagickEvent(X11Event,GetMagickModule(),
2691 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2692 event.xproperty.window,(unsigned long) event.xproperty.atom,
2693 event.xproperty.state);
2694 if (event.xproperty.atom != windows->im_remote_command)
2697 Display image named by the remote command protocol.
2699 status=XGetWindowProperty(display,event.xproperty.window,
2700 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
2701 AnyPropertyType,&type,&format,&length,&after,&data);
2702 if ((status != Success) || (length == 0))
2704 (void) CopyMagickString(resource_info->image_info->filename,
2705 (char *) data,MaxTextExtent);
2706 nexus=ReadImage(resource_info->image_info,exception);
2707 CatchException(exception);
2708 if (nexus != (Image *) NULL)
2710 (void) XFree((void *) data);
2713 case ReparentNotify:
2715 if (display_image->debug != MagickFalse)
2716 (void) LogMagickEvent(X11Event,GetMagickModule(),
2717 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2718 event.xreparent.window);
2723 if (display_image->debug != MagickFalse)
2724 (void) LogMagickEvent(X11Event,GetMagickModule(),
2725 "Unmap Notify: 0x%lx",event.xunmap.window);
2726 if (event.xunmap.window == windows->backdrop.id)
2728 windows->backdrop.mapped=MagickFalse;
2731 if (event.xunmap.window == windows->image.id)
2733 windows->image.mapped=MagickFalse;
2736 if (event.xunmap.window == windows->info.id)
2738 windows->info.mapped=MagickFalse;
2741 if (event.xunmap.window == windows->icon.id)
2743 if (map_info->colormap == icon_map->colormap)
2744 XConfigureImageColormap(display,resource_info,windows,
2745 display_image,exception);
2746 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2748 windows->icon.mapped=MagickFalse;
2751 if (event.xunmap.window == windows->command.id)
2753 windows->command.mapped=MagickFalse;
2756 if (event.xunmap.window == windows->popup.id)
2758 if (windows->backdrop.id != (Window) NULL)
2759 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2761 windows->popup.mapped=MagickFalse;
2764 if (event.xunmap.window == windows->widget.id)
2766 if (windows->backdrop.id != (Window) NULL)
2767 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2769 windows->widget.mapped=MagickFalse;
2776 if (display_image->debug != MagickFalse)
2777 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2783 while (!(state & ExitState));
2784 image_list=(Image **) RelinquishMagickMemory(image_list);
2785 images=DestroyImageList(images);
2786 if ((windows->visual_info->klass == GrayScale) ||
2787 (windows->visual_info->klass == PseudoColor) ||
2788 (windows->visual_info->klass == DirectColor))
2793 if (windows->info.mapped)
2794 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2795 if (windows->command.mapped)
2796 (void) XWithdrawWindow(display,windows->command.id,
2797 windows->command.screen);
2799 if (resource_info->backdrop == MagickFalse)
2800 if (windows->backdrop.mapped)
2802 (void) XWithdrawWindow(display,windows->backdrop.id,\
2803 windows->backdrop.screen);
2804 (void) XDestroyWindow(display,windows->backdrop.id);
2805 windows->backdrop.id=(Window) NULL;
2806 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2807 (void) XDestroyWindow(display,windows->image.id);
2808 windows->image.id=(Window) NULL;
2810 XSetCursorState(display,windows,MagickTrue);
2811 XCheckRefreshWindows(display,windows);
2812 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2814 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2815 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2816 windows->image.pixmaps[scene]=(Pixmap) NULL;
2817 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2818 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2819 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2821 XSetCursorState(display,windows,MagickFalse);
2822 windows->image.pixmaps=(Pixmap *)
2823 RelinquishMagickMemory(windows->image.pixmaps);
2824 windows->image.matte_pixmaps=(Pixmap *)
2825 RelinquishMagickMemory(windows->image.matte_pixmaps);
2826 if (nexus == (Image *) NULL)
2831 if (windows->image.mapped != MagickFalse)
2832 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime);
2833 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2834 if (resource_info->map_type == (char *) NULL)
2835 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2836 DestroyXResources();
2838 (void) XSync(display,MagickFalse);
2840 Restore our progress monitor and warning handlers.
2842 (void) SetErrorHandler(warning_handler);
2843 (void) SetWarningHandler(warning_handler);
2845 Change to home directory.
2847 directory=getcwd(working_directory,MaxTextExtent);
2849 status=chdir(resource_info->home_directory);
2851 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2852 "UnableToOpenFile","%s",resource_info->home_directory);
2857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2861 + X S a v e I m a g e %
2865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2867 % XSaveImage() saves an image to a file.
2869 % The format of the XSaveImage method is:
2871 % MagickBooleanType XSaveImage(Display *display,
2872 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2873 % ExceptionInfo *exception)
2875 % A description of each parameter follows:
2877 % o status: Method XSaveImage return True if the image is
2878 % written. False is returned is there is a memory shortage or if the
2879 % image fails to write.
2881 % o display: Specifies a connection to an X server; returned from
2884 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2886 % o windows: Specifies a pointer to a XWindows structure.
2888 % o image: the image.
2891 static MagickBooleanType XSaveImage(Display *display,
2892 XResourceInfo *resource_info,XWindows *windows,Image *image,
2893 ExceptionInfo *exception)
2896 filename[MaxTextExtent];
2905 Request file name from user.
2907 if (resource_info->write_filename != (char *) NULL)
2908 (void) CopyMagickString(filename,resource_info->write_filename,
2913 path[MaxTextExtent];
2918 GetPathComponent(image->filename,HeadPath,path);
2919 GetPathComponent(image->filename,TailPath,filename);
2922 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2923 "UnableToOpenFile","%s",path);
2925 XFileBrowserWidget(display,windows,"Save",filename);
2926 if (*filename == '\0')
2928 if (IsPathAccessible(filename) != MagickFalse)
2934 File exists-- seek user's permission before overwriting.
2936 status=XConfirmWidget(display,windows,"Overwrite",filename);
2940 image_info=CloneImageInfo(resource_info->image_info);
2941 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2942 (void) SetImageInfo(image_info,1,exception);
2943 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2944 (LocaleCompare(image_info->magick,"JPG") == 0))
2947 quality[MaxTextExtent];
2953 Request JPEG quality from user.
2955 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
2956 image_info->quality);
2957 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2959 if (*quality == '\0')
2961 image->quality=StringToUnsignedLong(quality);
2962 image_info->interlace=status != MagickFalse ? NoInterlace :
2965 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2966 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2967 (LocaleCompare(image_info->magick,"PS") == 0) ||
2968 (LocaleCompare(image_info->magick,"PS2") == 0))
2971 geometry[MaxTextExtent];
2974 Request page geometry from user.
2976 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2977 if (LocaleCompare(image_info->magick,"PDF") == 0)
2978 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2979 if (image_info->page != (char *) NULL)
2980 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
2981 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2982 "Select page geometry:",geometry);
2983 if (*geometry != '\0')
2984 image_info->page=GetPageGeometry(geometry);
2989 image=GetFirstImageInList(image);
2990 status=WriteImages(image_info,image,filename,exception);
2991 if (status != MagickFalse)
2992 image->taint=MagickFalse;
2993 image_info=DestroyImageInfo(image_info);
2994 XSetCursorState(display,windows,MagickFalse);
2995 return(status != 0 ? MagickTrue : MagickFalse);
3000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3004 + A n i m a t e I m a g e s %
3008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3010 % AnimateImages() repeatedly displays an image sequence to any X window
3011 % screen. It returns a value other than 0 if successful. Check the
3012 % exception member of image to determine the reason for any failure.
3014 % The format of the AnimateImages method is:
3016 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3019 % A description of each parameter follows:
3021 % o image_info: the image info.
3023 % o image: the image.
3025 % o exception: return any errors or warnings in this structure.
3028 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3029 Image *image,ExceptionInfo *exception)
3031 assert(image_info != (const ImageInfo *) NULL);
3032 assert(image_info->signature == MagickSignature);
3033 assert(image != (Image *) NULL);
3034 assert(image->signature == MagickSignature);
3035 if (image->debug != MagickFalse)
3036 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3037 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
3038 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
3039 return(MagickFalse);