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/colorspace-private.h"
50 #include "MagickCore/constitute.h"
51 #include "MagickCore/delegate.h"
52 #include "MagickCore/exception.h"
53 #include "MagickCore/exception-private.h"
54 #include "MagickCore/geometry.h"
55 #include "MagickCore/image-private.h"
56 #include "MagickCore/layer.h"
57 #include "MagickCore/list.h"
58 #include "MagickCore/log.h"
59 #include "MagickCore/image.h"
60 #include "MagickCore/memory_.h"
61 #include "MagickCore/monitor.h"
62 #include "MagickCore/monitor-private.h"
63 #include "MagickCore/option.h"
64 #include "MagickCore/pixel-accessor.h"
65 #include "MagickCore/property.h"
66 #include "MagickCore/resource_.h"
67 #include "MagickCore/string_.h"
68 #include "MagickCore/string-private.h"
69 #include "MagickCore/transform.h"
70 #include "MagickCore/utility.h"
71 #include "MagickCore/utility-private.h"
72 #include "MagickCore/version.h"
73 #include "MagickCore/widget.h"
74 #include "MagickCore/widget-private.h"
75 #include "MagickCore/xwindow.h"
76 #include "MagickCore/xwindow-private.h"
78 #if defined(MAGICKCORE_X11_DELEGATE)
80 Animate state declarations.
82 #define AutoReverseAnimationState 0x0004
83 #define ForwardAnimationState 0x0008
84 #define HighlightState 0x0010
85 #define PlayAnimationState 0x0020
86 #define RepeatAnimationState 0x0040
87 #define StepAnimationState 0x0080
97 " Press any button to map or unmap the Command widget.",
100 " The Command widget lists a number of sub-menus and commands.",
118 " Browse Documentation",
123 " Menu items with a indented triangle have a sub-menu. They",
124 " are represented above as the indented items. To access a",
125 " sub-menu item, move the pointer to the appropriate menu and",
126 " press a button and drag. When you find the desired sub-menu",
127 " item, release the button and the command is executed. Move",
128 " the pointer away from the sub-menu if you decide not to",
129 " execute a particular command.",
131 "KEYBOARD ACCELERATORS",
132 " Accelerators are one or two key presses that effect a",
133 " particular command. The keyboard accelerators that",
134 " animate(1) understands is:",
136 " Ctl+O Press to open an image from a file.",
138 " space Press to display the next image in the sequence.",
140 " < Press to speed-up the display of the images. Refer to",
141 " -delay for more information.",
143 " > Press to slow the display of the images. Refer to",
144 " -delay for more information.",
146 " F1 Press to display helpful information about animate(1).",
148 " Find Press to browse documentation about ImageMagick.",
150 " ? Press to display information about the image. Press",
151 " any key or button to erase the information.",
153 " This information is printed: image name; image size;",
154 " and the total number of unique colors in the image.",
156 " Ctl-q Press to discard all images and exit program.",
161 Constant declarations.
183 static const unsigned char
186 (unsigned char) 0xaa,
187 (unsigned char) 0x55,
188 (unsigned char) 0xaa,
189 (unsigned char) 0x55,
190 (unsigned char) 0xaa,
191 (unsigned char) 0x55,
192 (unsigned char) 0xaa,
197 (unsigned char) 0x00,
198 (unsigned char) 0x00,
199 (unsigned char) 0x00,
200 (unsigned char) 0x00,
201 (unsigned char) 0x00,
202 (unsigned char) 0x00,
203 (unsigned char) 0x00,
208 Enumeration declarations.
223 BrowseDocumentationCommand,
235 #define HighlightWidth 8
236 #define HighlightHeight 8
237 #define ShadowWidth 8
238 #define ShadowHeight 8
241 Forward declarations.
244 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
245 Image **,MagickStatusType *,ExceptionInfo *);
247 static MagickBooleanType
248 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255 % A n i m a t e I m a g e s %
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 % AnimateImages() repeatedly displays an image sequence to any X window
262 % screen. It returns a value other than 0 if successful. Check the
263 % exception member of image to determine the reason for any failure.
265 % The format of the AnimateImages method is:
267 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
268 % Image *images,ExceptionInfo *exception)
270 % A description of each parameter follows:
272 % o image_info: the image info.
274 % o image: the image.
276 % o exception: return any errors or warnings in this structure.
279 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
280 Image *images,ExceptionInfo *exception)
297 assert(image_info != (const ImageInfo *) NULL);
298 assert(image_info->signature == MagickSignature);
299 assert(images != (Image *) NULL);
300 assert(images->signature == MagickSignature);
301 if (images->debug != MagickFalse)
302 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
303 display=XOpenDisplay(image_info->server_name);
304 if (display == (Display *) NULL)
306 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
307 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
310 if (exception->severity != UndefinedException)
311 CatchException(exception);
312 (void) XSetErrorHandler(XError);
313 resource_database=XGetResourceDatabase(display,GetClientName());
314 (void) ResetMagickMemory(&resource_info,0,sizeof(XResourceInfo));
315 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
316 if (image_info->page != (char *) NULL)
317 resource_info.image_geometry=AcquireString(image_info->page);
318 resource_info.immutable=MagickTrue;
319 argv[0]=AcquireString(GetClientName());
320 (void) XAnimateImages(display,&resource_info,argv,1,images,exception);
321 (void) SetErrorHandler((ErrorHandler) NULL);
322 (void) SetWarningHandler((WarningHandler) NULL);
323 argv[0]=DestroyString(argv[0]);
324 (void) XCloseDisplay(display);
325 XDestroyResourceInfo(&resource_info);
326 status=exception->severity == UndefinedException ? MagickTrue : MagickFalse;
327 return(status != 0 ? MagickTrue : MagickFalse);
331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335 + X M a g i c k C o m m a n d %
339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 % XMagickCommand() makes a transform to the image or Image window as specified
342 % by a user menu button or keyboard command.
344 % The format of the XMagickCommand method is:
346 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
347 % XWindows *windows,const CommandType command_type,Image **image,
348 % MagickStatusType *state,ExceptionInfo *exception)
350 % A description of each parameter follows:
352 % o display: Specifies a connection to an X server; returned from
355 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
357 % o windows: Specifies a pointer to a XWindows structure.
359 % o image: the image; XMagickCommand
360 % may transform the image and return a new image pointer.
362 % o state: Specifies a MagickStatusType; XMagickCommand may return a
365 % o exception: return any errors or warnings in this structure.
369 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
370 XWindows *windows,const CommandType command_type,Image **image,
371 MagickStatusType *state,ExceptionInfo *exception)
386 Process user command.
388 nexus=NewImageList();
389 switch (command_type)
410 filenames[MaxTextExtent] = "*";
412 if (resource_info->immutable != MagickFalse)
415 Request file name from user.
417 XFileBrowserWidget(display,windows,"Animate",filenames);
418 if (*filenames == '\0')
419 return((Image *) NULL);
421 Expand the filenames.
423 filelist=(char **) AcquireMagickMemory(sizeof(char *));
424 if (filelist == (char **) NULL)
426 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
428 return((Image *) NULL);
431 filelist[0]=filenames;
432 status=ExpandFilenames(&number_files,&filelist);
433 if ((status == MagickFalse) || (number_files == 0))
435 if (number_files == 0)
437 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
438 return((Image *) NULL);
440 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
442 return((Image *) NULL);
444 read_info=CloneImageInfo(resource_info->image_info);
445 images=NewImageList();
446 XSetCursorState(display,windows,MagickTrue);
447 XCheckRefreshWindows(display,windows);
448 for (i=0; i < number_files; i++)
450 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
451 filelist[i]=DestroyString(filelist[i]);
452 *read_info->magick='\0';
453 next=ReadImage(read_info,exception);
454 CatchException(exception);
455 if (next != (Image *) NULL)
456 AppendImageToList(&images,next);
457 if (number_files <= 5)
459 proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
461 if (proceed == MagickFalse)
464 filelist=(char **) RelinquishMagickMemory(filelist);
465 read_info=DestroyImageInfo(read_info);
466 if (images == (Image *) NULL)
468 XSetCursorState(display,windows,MagickFalse);
469 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
470 return((Image *) NULL);
472 nexus=GetFirstImageInList(images);
479 basename[MaxTextExtent];
485 Window name is the base of the filename.
487 *state|=PlayAnimationState;
488 *state&=(~AutoReverseAnimationState);
489 GetPathComponent((*image)->magick_filename,BasePath,basename);
490 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
491 "%s: %s",MagickPackageName,basename);
492 if (resource_info->title != (char *) NULL)
497 title=InterpretImageProperties(resource_info->image_info,*image,
498 resource_info->title,exception);
499 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
500 title=DestroyString(title);
502 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
505 XSetWMName(display,windows->image.id,&window_name);
506 (void) XFree((void *) window_name.value);
510 case StepBackwardCommand:
511 case StepForwardCommand:
513 *state|=StepAnimationState;
514 *state&=(~PlayAnimationState);
515 if (command_type == StepBackwardCommand)
516 *state&=(~ForwardAnimationState);
517 if (command_type == StepForwardCommand)
518 *state|=ForwardAnimationState;
519 if (resource_info->title != (char *) NULL)
525 *state|=RepeatAnimationState;
526 *state&=(~AutoReverseAnimationState);
527 *state|=PlayAnimationState;
530 case AutoReverseCommand:
532 *state|=AutoReverseAnimationState;
533 *state&=(~RepeatAnimationState);
534 *state|=PlayAnimationState;
542 status=XSaveImage(display,resource_info,windows,*image,exception);
543 if (status == MagickFalse)
546 message[MaxTextExtent];
548 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
549 exception->reason != (char *) NULL ? exception->reason : "",
550 exception->description != (char *) NULL ? exception->description :
552 XNoticeWidget(display,windows,"Unable to save file:",message);
559 resource_info->delay++;
564 if (resource_info->delay == 0)
566 resource_info->delay--;
571 *state=ForwardAnimationState;
572 *state&=(~AutoReverseAnimationState);
577 *state&=(~ForwardAnimationState);
578 *state&=(~AutoReverseAnimationState);
583 XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image,
592 XTextViewWidget(display,resource_info,windows,MagickFalse,
593 "Help Viewer - Animate",AnimateHelp);
596 case BrowseDocumentationCommand:
606 Browse the ImageMagick documentation.
608 root_window=XRootWindow(display,XDefaultScreen(display));
609 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
610 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
611 if (mozilla_window != (Window) NULL)
614 command[MaxTextExtent],
618 Display documentation using Netscape remote control.
620 url=GetMagickHomeURL();
621 (void) FormatLocaleString(command,MaxTextExtent,
622 "openurl(%s,new-tab)",url);
623 url=DestroyString(url);
624 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
625 (void) XChangeProperty(display,mozilla_window,mozilla_atom,
626 XA_STRING,8,PropModeReplace,(unsigned char *) command,
627 (int) strlen(command));
628 XSetCursorState(display,windows,MagickFalse);
631 XSetCursorState(display,windows,MagickTrue);
632 XCheckRefreshWindows(display,windows);
633 status=InvokeDelegate(resource_info->image_info,*image,"browse",
634 (char *) NULL,exception);
635 if (status == MagickFalse)
636 XNoticeWidget(display,windows,"Unable to browse documentation",
638 XDelay(display,1500);
639 XSetCursorState(display,windows,MagickFalse);
644 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
645 GetMagickCopyright());
653 if (resource_info->confirm_exit == MagickFalse)
654 XClientMessage(display,windows->image.id,windows->im_protocols,
655 windows->im_exit,CurrentTime);
662 Confirm program exit.
664 status=XConfirmWidget(display,windows,"Do you really want to exit",
665 resource_info->client_name);
667 XClientMessage(display,windows->image.id,windows->im_protocols,
668 windows->im_exit,CurrentTime);
679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683 + X A n i m a t e B a c k g r o u n d I m a g e %
687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 % XAnimateBackgroundImage() animates an image sequence in the background of
692 % The format of the XAnimateBackgroundImage method is:
694 % void XAnimateBackgroundImage(Display *display,
695 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
697 % A description of each parameter follows:
699 % o display: Specifies a connection to an X server; returned from
702 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
704 % o images: the image list.
706 % o exception: return any errors or warnings in this structure.
710 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
717 #if defined(__cplusplus) || defined(c_plusplus)
721 static int SceneCompare(const void *x,const void *y)
727 image_1=(const Image **) x;
728 image_2=(const Image **) y;
729 return((int) ((*image_1)->scene-(*image_2)->scene));
732 #if defined(__cplusplus) || defined(c_plusplus)
736 MagickExport void XAnimateBackgroundImage(Display *display,
737 XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
740 geometry[MaxTextExtent],
741 visual_type[MaxTextExtent];
766 static XStandardColormap
770 *visual_info = (XVisualInfo *) NULL;
798 Determine target window.
800 assert(images != (Image *) NULL);
801 assert(images->signature == MagickSignature);
802 if (images->debug != MagickFalse)
803 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
804 resources=(*resource_info);
805 window_info.id=(Window) NULL;
806 root_window=XRootWindow(display,XDefaultScreen(display));
807 if (LocaleCompare(resources.window_id,"root") == 0)
808 window_info.id=root_window;
811 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
812 window_info.id=XWindowByID(display,root_window,
813 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
814 if (window_info.id == (Window) NULL)
816 XWindowByName(display,root_window,resources.window_id);
818 if (window_info.id == (Window) NULL)
820 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
821 resources.window_id);
825 Determine window visual id.
827 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
828 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
829 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
830 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
831 MagickTrue : MagickFalse;
832 if (status != MagickFalse)
833 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
834 XVisualIDFromVisual(window_attributes.visual));
835 if (visual_info == (XVisualInfo *) NULL)
838 Allocate standard colormap.
840 map_info=XAllocStandardColormap();
841 if (map_info == (XStandardColormap *) NULL)
842 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
844 map_info->colormap=(Colormap) NULL;
845 pixel.pixels=(unsigned long *) NULL;
847 Initialize visual info.
849 resources.map_type=(char *) NULL;
850 resources.visual_type=visual_type;
851 visual_info=XBestVisualInfo(display,map_info,&resources);
852 if (visual_info == (XVisualInfo *) NULL)
853 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
856 Initialize window info.
858 window_info.ximage=(XImage *) NULL;
859 window_info.matte_image=(XImage *) NULL;
860 window_info.pixmap=(Pixmap) NULL;
861 window_info.matte_pixmap=(Pixmap) NULL;
864 Free previous root colors.
866 if (window_info.id == root_window)
867 XDestroyWindowColors(display,root_window);
868 coalesce_image=CoalesceImages(images,exception);
869 if (coalesce_image == (Image *) NULL)
870 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
872 images=coalesce_image;
873 if (resources.map_type == (char *) NULL)
874 if ((visual_info->klass != TrueColor) &&
875 (visual_info->klass != DirectColor))
881 Determine if the sequence of images has the identical colormap.
883 for (next=images; next != (Image *) NULL; )
885 next->matte=MagickFalse;
886 if ((next->storage_class == DirectClass) ||
887 (next->colors != images->colors) ||
888 (next->colors > (size_t) visual_info->colormap_size))
890 for (i=0; i < (ssize_t) images->colors; i++)
891 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
893 if (i < (ssize_t) images->colors)
895 next=GetNextImageInList(next);
897 if (next != (Image *) NULL)
898 (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
902 Sort images by increasing scene number.
904 number_scenes=GetImageListLength(images);
905 image_list=ImageListToArray(images,exception);
906 if (image_list == (Image **) NULL)
907 ThrowXWindowFatalException(ResourceLimitFatalError,
908 "MemoryAllocationFailed",images->filename);
909 for (i=0; i < (ssize_t) number_scenes; i++)
910 if (image_list[i]->scene == 0)
912 if (i == (ssize_t) number_scenes)
913 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
915 Initialize Standard Colormap.
917 resources.colormap=SharedColormap;
918 display_image=image_list[0];
919 for (scene=0; scene < (int) number_scenes; scene++)
921 if ((resource_info->map_type != (char *) NULL) ||
922 (visual_info->klass == TrueColor) ||
923 (visual_info->klass == DirectColor))
924 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
925 MagickFalse ? TrueColorType : TrueColorMatteType,exception);
926 if ((display_image->columns < image_list[scene]->columns) &&
927 (display_image->rows < image_list[scene]->rows))
928 display_image=image_list[scene];
930 if ((resource_info->map_type != (char *) NULL) ||
931 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
932 (void) SetImageType(display_image,display_image->matte == MagickFalse ?
933 TrueColorType : TrueColorMatteType,exception);
934 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
937 Graphic context superclass.
939 context_values.background=pixel.background_color.pixel;
940 context_values.foreground=pixel.foreground_color.pixel;
941 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
942 (GCBackground | GCForeground),&context_values);
943 if (pixel.annotate_context == (GC) NULL)
944 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
947 Initialize Image window attributes.
949 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
950 &resources,&window_info);
954 window_info.width=(unsigned int) image_list[0]->columns;
955 window_info.height=(unsigned int) image_list[0]->rows;
956 if ((image_list[0]->columns != window_info.width) ||
957 (image_list[0]->rows != window_info.height))
958 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
959 image_list[0]->filename);
960 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
961 window_attributes.width,window_attributes.height);
962 geometry_info.width=window_info.width;
963 geometry_info.height=window_info.height;
964 geometry_info.x=(ssize_t) window_info.x;
965 geometry_info.y=(ssize_t) window_info.y;
966 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
967 &geometry_info.width,&geometry_info.height);
968 window_info.width=(unsigned int) geometry_info.width;
969 window_info.height=(unsigned int) geometry_info.height;
970 window_info.x=(int) geometry_info.x;
971 window_info.y=(int) geometry_info.y;
972 status=XMakeImage(display,&resources,&window_info,image_list[0],
973 window_info.width,window_info.height,exception);
974 if (status == MagickFalse)
975 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
979 if (display_image->debug != MagickFalse)
981 (void) LogMagickEvent(X11Event,GetMagickModule(),
982 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
983 image_list[0]->scene,(double) image_list[0]->columns,(double)
984 image_list[0]->rows);
985 if (image_list[0]->colors != 0)
986 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
987 image_list[0]->colors);
988 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
989 image_list[0]->magick);
992 Adjust image dimensions as specified by backdrop or geometry options.
994 width=window_info.width;
995 height=window_info.height;
996 if (resources.backdrop != MagickFalse)
999 Center image on window.
1001 window_info.x=(int) (window_attributes.width/2)-
1002 (window_info.ximage->width/2);
1003 window_info.y=(int) (window_attributes.height/2)-
1004 (window_info.ximage->height/2);
1005 width=(unsigned int) window_attributes.width;
1006 height=(unsigned int) window_attributes.height;
1008 if (resources.image_geometry != (char *) NULL)
1011 default_geometry[MaxTextExtent];
1021 User specified geometry.
1023 size_hints=XAllocSizeHints();
1024 if (size_hints == (XSizeHints *) NULL)
1025 ThrowXWindowFatalException(ResourceLimitFatalError,
1026 "MemoryAllocationFailed",images->filename);
1027 size_hints->flags=0L;
1028 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%ux%u",width,
1030 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1031 default_geometry,window_info.border_width,size_hints,&window_info.x,
1032 &window_info.y,(int *) &width,(int *) &height,&gravity);
1033 if (((flags & (XValue | YValue))) != 0)
1035 width=(unsigned int) window_attributes.width;
1036 height=(unsigned int) window_attributes.height;
1038 (void) XFree((void *) size_hints);
1041 Create the X pixmap.
1043 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1044 (unsigned int) height,window_info.depth);
1045 if (window_info.pixmap == (Pixmap) NULL)
1046 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1049 Display pixmap on the window.
1051 if (((unsigned int) width > window_info.width) ||
1052 ((unsigned int) height > window_info.height))
1053 (void) XFillRectangle(display,window_info.pixmap,
1054 window_info.annotate_context,0,0,(unsigned int) width,
1055 (unsigned int) height);
1056 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1057 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1058 window_info.height);
1059 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1060 (void) XClearWindow(display,window_info.id);
1062 Initialize image pixmaps structure.
1064 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1065 sizeof(*window_info.pixmaps));
1066 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1067 sizeof(*window_info.matte_pixmaps));
1068 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1069 (window_info.matte_pixmaps == (Pixmap *) NULL))
1070 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1072 window_info.pixmaps[0]=window_info.pixmap;
1073 window_info.matte_pixmaps[0]=window_info.pixmap;
1074 for (scene=1; scene < (int) number_scenes; scene++)
1083 window_info.pixmap=(Pixmap) NULL;
1084 window_info.matte_pixmap=(Pixmap) NULL;
1085 if ((resources.map_type != (char *) NULL) ||
1086 (visual_info->klass == TrueColor) ||
1087 (visual_info->klass == DirectColor))
1088 if (image_list[scene]->storage_class == PseudoClass)
1089 XGetPixelInfo(display,visual_info,map_info,&resources,
1090 image_list[scene],window_info.pixel_info);
1091 columns=(unsigned int) image_list[scene]->columns;
1092 rows=(unsigned int) image_list[scene]->rows;
1093 if ((image_list[scene]->columns != columns) ||
1094 (image_list[scene]->rows != rows))
1095 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1096 image_list[scene]->filename);
1097 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1098 columns,rows,exception);
1099 if (status == MagickFalse)
1100 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1102 if (display_image->debug != MagickFalse)
1104 (void) LogMagickEvent(X11Event,GetMagickModule(),
1105 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1106 image_list[scene]->filename,(double) columns,(double) rows);
1107 if (image_list[scene]->colors != 0)
1108 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1109 image_list[scene]->colors);
1110 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1111 image_list[scene]->magick);
1114 Create the X pixmap.
1116 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1118 if (window_info.pixmap == (Pixmap) NULL)
1119 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1122 Display pixmap on the window.
1124 if ((width > window_info.width) || (height > window_info.height))
1125 (void) XFillRectangle(display,window_info.pixmap,
1126 window_info.annotate_context,0,0,width,height);
1127 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1128 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1129 window_info.height);
1130 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1131 window_info.pixmap);
1132 (void) XClearWindow(display,window_info.id);
1133 window_info.pixmaps[scene]=window_info.pixmap;
1134 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1135 if (image_list[scene]->matte)
1136 (void) XClearWindow(display,window_info.id);
1137 delay=1000*image_list[scene]->delay/MagickMax(
1138 image_list[scene]->ticks_per_second,1L);
1139 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1141 window_info.pixel_info=(&pixel);
1143 Display pixmap on the window.
1145 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1149 for (scene=0; scene < (int) number_scenes; scene++)
1151 if (XEventsQueued(display,QueuedAfterFlush) > 0)
1153 (void) XNextEvent(display,&event);
1154 if (event.type == DestroyNotify)
1157 window_info.pixmap=window_info.pixmaps[scene];
1158 window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1159 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1160 window_info.pixmap);
1161 (void) XClearWindow(display,window_info.id);
1162 (void) XSync(display,MagickFalse);
1163 delay=1000*image_list[scene]->delay/MagickMax(
1164 image_list[scene]->ticks_per_second,1L);
1165 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1167 } while (event.type != DestroyNotify);
1168 (void) XSync(display,MagickFalse);
1169 image_list=(Image **) RelinquishMagickMemory(image_list);
1170 images=DestroyImageList(images);
1174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1178 + X A n i m a t e I m a g e s %
1182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1184 % XAnimateImages() displays an image via X11.
1186 % The format of the XAnimateImages method is:
1188 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1189 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1191 % A description of each parameter follows:
1193 % o display: Specifies a connection to an X server; returned from
1196 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1198 % o argv: Specifies the application's argument list.
1200 % o argc: Specifies the number of arguments.
1202 % o images: the image list.
1204 % o exception: return any errors or warnings in this structure.
1207 MagickExport Image *XAnimateImages(Display *display,
1208 XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1209 ExceptionInfo *exception)
1211 #define MagickMenus 4
1212 #define MaXWindows 8
1213 #define MagickTitle "Commands"
1251 "Browse Documentation",
1257 **Menus[MagickMenus]=
1265 static const CommandType
1289 DirectionCommands[]=
1297 BrowseDocumentationCommand,
1301 static const CommandType
1302 *Commands[MagickMenus]=
1311 command[MaxTextExtent],
1313 geometry[MaxTextExtent],
1314 resource_name[MaxTextExtent];
1351 working_directory[MaxTextExtent];
1357 *magick_windows[MaXWindows];
1411 assert(images != (Image *) NULL);
1412 assert(images->signature == MagickSignature);
1413 if (images->debug != MagickFalse)
1414 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1415 warning_handler=(WarningHandler) NULL;
1416 windows=XSetWindows((XWindows *) ~0);
1417 if (windows != (XWindows *) NULL)
1422 status=chdir(working_directory);
1424 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
1425 "UnableToOpenFile","%s",working_directory);
1426 warning_handler=resource_info->display_warnings ?
1427 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1428 warning_handler=resource_info->display_warnings ?
1429 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1437 Initialize window structure.
1439 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1441 if (p->storage_class == DirectClass)
1443 resource_info->colors=0;
1446 if (p->colors > resource_info->colors)
1447 resource_info->colors=p->colors;
1449 windows=XSetWindows(XInitializeWindows(display,resource_info));
1450 if (windows == (XWindows *) NULL)
1451 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1454 Initialize window id's.
1457 magick_windows[number_windows++]=(&windows->icon);
1458 magick_windows[number_windows++]=(&windows->backdrop);
1459 magick_windows[number_windows++]=(&windows->image);
1460 magick_windows[number_windows++]=(&windows->info);
1461 magick_windows[number_windows++]=(&windows->command);
1462 magick_windows[number_windows++]=(&windows->widget);
1463 magick_windows[number_windows++]=(&windows->popup);
1464 for (i=0; i < (ssize_t) number_windows; i++)
1465 magick_windows[i]->id=(Window) NULL;
1468 Initialize font info.
1470 if (windows->font_info != (XFontStruct *) NULL)
1471 (void) XFreeFont(display,windows->font_info);
1472 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1473 if (windows->font_info == (XFontStruct *) NULL)
1474 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1475 resource_info->font);
1477 Initialize Standard Colormap.
1479 map_info=windows->map_info;
1480 icon_map=windows->icon_map;
1481 visual_info=windows->visual_info;
1482 icon_visual=windows->icon_visual;
1483 pixel=windows->pixel_info;
1484 icon_pixel=windows->icon_pixel;
1485 font_info=windows->font_info;
1486 icon_resources=windows->icon_resources;
1487 class_hints=windows->class_hints;
1488 manager_hints=windows->manager_hints;
1489 root_window=XRootWindow(display,visual_info->screen);
1490 coalesce_image=CoalesceImages(images,exception);
1491 if (coalesce_image == (Image *) NULL)
1492 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1494 images=coalesce_image;
1495 if (resource_info->map_type == (char *) NULL)
1496 if ((visual_info->klass != TrueColor) &&
1497 (visual_info->klass != DirectColor))
1503 Determine if the sequence of images has the identical colormap.
1505 for (next=images; next != (Image *) NULL; )
1507 next->matte=MagickFalse;
1508 if ((next->storage_class == DirectClass) ||
1509 (next->colors != images->colors) ||
1510 (next->colors > (size_t) visual_info->colormap_size))
1512 for (i=0; i < (ssize_t) images->colors; i++)
1513 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1515 if (i < (ssize_t) images->colors)
1517 next=GetNextImageInList(next);
1519 if (next != (Image *) NULL)
1520 (void) RemapImages(resource_info->quantize_info,images,
1521 (Image *) NULL,exception);
1524 Sort images by increasing scene number.
1526 number_scenes=GetImageListLength(images);
1527 image_list=ImageListToArray(images,exception);
1528 if (image_list == (Image **) NULL)
1529 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1531 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1532 if (image_list[scene]->scene == 0)
1534 if (scene == (ssize_t) number_scenes)
1535 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1537 Initialize Standard Colormap.
1539 nexus=NewImageList();
1540 display_image=image_list[0];
1541 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1543 if ((resource_info->map_type != (char *) NULL) ||
1544 (visual_info->klass == TrueColor) ||
1545 (visual_info->klass == DirectColor))
1546 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
1547 MagickFalse ? TrueColorType : TrueColorMatteType,exception);
1548 if ((display_image->columns < image_list[scene]->columns) &&
1549 (display_image->rows < image_list[scene]->rows))
1550 display_image=image_list[scene];
1552 if (display_image->debug != MagickFalse)
1554 (void) LogMagickEvent(X11Event,GetMagickModule(),
1555 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1556 display_image->scene,(double) display_image->columns,(double)
1557 display_image->rows);
1558 if (display_image->colors != 0)
1559 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1560 display_image->colors);
1561 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1562 display_image->magick);
1564 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1565 map_info,pixel,exception);
1567 Initialize graphic context.
1569 windows->context.id=(Window) NULL;
1570 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1571 resource_info,&windows->context);
1572 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1573 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1574 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1575 manager_hints->flags=InputHint | StateHint;
1576 manager_hints->input=MagickFalse;
1577 manager_hints->initial_state=WithdrawnState;
1578 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1580 if (display_image->debug != MagickFalse)
1581 (void) LogMagickEvent(X11Event,GetMagickModule(),
1582 "Window id: 0x%lx (context)",windows->context.id);
1583 context_values.background=pixel->background_color.pixel;
1584 context_values.font=font_info->fid;
1585 context_values.foreground=pixel->foreground_color.pixel;
1586 context_values.graphics_exposures=MagickFalse;
1587 context_mask=(MagickStatusType)
1588 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1589 if (pixel->annotate_context != (GC) NULL)
1590 (void) XFreeGC(display,pixel->annotate_context);
1591 pixel->annotate_context=
1592 XCreateGC(display,windows->context.id,context_mask,&context_values);
1593 if (pixel->annotate_context == (GC) NULL)
1594 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1596 context_values.background=pixel->depth_color.pixel;
1597 if (pixel->widget_context != (GC) NULL)
1598 (void) XFreeGC(display,pixel->widget_context);
1599 pixel->widget_context=
1600 XCreateGC(display,windows->context.id,context_mask,&context_values);
1601 if (pixel->widget_context == (GC) NULL)
1602 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1604 context_values.background=pixel->foreground_color.pixel;
1605 context_values.foreground=pixel->background_color.pixel;
1606 context_values.plane_mask=
1607 context_values.background ^ context_values.foreground;
1608 if (pixel->highlight_context != (GC) NULL)
1609 (void) XFreeGC(display,pixel->highlight_context);
1610 pixel->highlight_context=XCreateGC(display,windows->context.id,
1611 (size_t) (context_mask | GCPlaneMask),&context_values);
1612 if (pixel->highlight_context == (GC) NULL)
1613 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1615 (void) XDestroyWindow(display,windows->context.id);
1617 Initialize icon window.
1619 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1620 icon_resources,&windows->icon);
1621 windows->icon.geometry=resource_info->icon_geometry;
1622 XBestIconSize(display,&windows->icon,display_image);
1623 windows->icon.attributes.colormap=
1624 XDefaultColormap(display,icon_visual->screen);
1625 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1626 manager_hints->flags=InputHint | StateHint;
1627 manager_hints->input=MagickFalse;
1628 manager_hints->initial_state=IconicState;
1629 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1631 if (display_image->debug != MagickFalse)
1632 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1635 Initialize graphic context for icon window.
1637 if (icon_pixel->annotate_context != (GC) NULL)
1638 (void) XFreeGC(display,icon_pixel->annotate_context);
1639 context_values.background=icon_pixel->background_color.pixel;
1640 context_values.foreground=icon_pixel->foreground_color.pixel;
1641 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1642 (size_t) (GCBackground | GCForeground),&context_values);
1643 if (icon_pixel->annotate_context == (GC) NULL)
1644 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1646 windows->icon.annotate_context=icon_pixel->annotate_context;
1648 Initialize Image window.
1650 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1651 resource_info,&windows->image);
1652 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1653 if (resource_info->use_shared_memory == MagickFalse)
1654 windows->image.shared_memory=MagickFalse;
1655 if (resource_info->title != (char *) NULL)
1660 title=InterpretImageProperties(resource_info->image_info,display_image,
1661 resource_info->title,exception);
1662 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1663 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
1664 title=DestroyString(title);
1669 filename[MaxTextExtent];
1672 Window name is the base of the filename.
1674 GetPathComponent(display_image->magick_filename,TailPath,filename);
1675 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1676 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1677 display_image->scene,(double) number_scenes);
1678 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
1680 if (resource_info->immutable != MagickFalse)
1681 windows->image.immutable=MagickTrue;
1682 windows->image.shape=MagickTrue;
1683 windows->image.geometry=resource_info->image_geometry;
1684 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
1685 XDisplayWidth(display,visual_info->screen),
1686 XDisplayHeight(display,visual_info->screen));
1687 geometry_info.width=display_image->columns;
1688 geometry_info.height=display_image->rows;
1691 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1692 &geometry_info.width,&geometry_info.height);
1693 windows->image.width=(unsigned int) geometry_info.width;
1694 windows->image.height=(unsigned int) geometry_info.height;
1695 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1696 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1697 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1698 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1699 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1700 resource_info,&windows->backdrop);
1701 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1704 Initialize backdrop window.
1706 windows->backdrop.x=0;
1707 windows->backdrop.y=0;
1708 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1709 windows->backdrop.flags=(size_t) (USSize | USPosition);
1710 windows->backdrop.width=(unsigned int)
1711 XDisplayWidth(display,visual_info->screen);
1712 windows->backdrop.height=(unsigned int)
1713 XDisplayHeight(display,visual_info->screen);
1714 windows->backdrop.border_width=0;
1715 windows->backdrop.immutable=MagickTrue;
1716 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1718 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1719 StructureNotifyMask;
1720 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1721 manager_hints->icon_window=windows->icon.id;
1722 manager_hints->input=MagickTrue;
1723 manager_hints->initial_state=
1724 resource_info->iconic ? IconicState : NormalState;
1725 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1726 &windows->backdrop);
1727 if (display_image->debug != MagickFalse)
1728 (void) LogMagickEvent(X11Event,GetMagickModule(),
1729 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1730 (void) XMapWindow(display,windows->backdrop.id);
1731 (void) XClearWindow(display,windows->backdrop.id);
1732 if (windows->image.id != (Window) NULL)
1734 (void) XDestroyWindow(display,windows->image.id);
1735 windows->image.id=(Window) NULL;
1738 Position image in the center the backdrop.
1740 windows->image.flags|=USPosition;
1741 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1742 (windows->image.width/2);
1743 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1744 (windows->image.height/2);
1746 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1747 manager_hints->icon_window=windows->icon.id;
1748 manager_hints->input=MagickTrue;
1749 manager_hints->initial_state=
1750 resource_info->iconic ? IconicState : NormalState;
1751 if (windows->group_leader.id != (Window) NULL)
1756 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1757 manager_hints->window_group=windows->group_leader.id;
1758 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1759 if (display_image->debug != MagickFalse)
1760 (void) LogMagickEvent(X11Event,GetMagickModule(),
1761 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1763 XMakeWindow(display,
1764 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1765 argv,argc,class_hints,manager_hints,&windows->image);
1766 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1767 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1768 if (windows->group_leader.id != (Window) NULL)
1769 (void) XSetTransientForHint(display,windows->image.id,
1770 windows->group_leader.id);
1771 if (display_image->debug != MagickFalse)
1772 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1775 Initialize Info widget.
1777 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1778 resource_info,&windows->info);
1779 (void) CloneString(&windows->info.name,"Info");
1780 (void) CloneString(&windows->info.icon_name,"Info");
1781 windows->info.border_width=1;
1784 windows->info.flags|=PPosition;
1785 windows->info.attributes.win_gravity=UnmapGravity;
1786 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1787 StructureNotifyMask;
1788 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1789 manager_hints->input=MagickFalse;
1790 manager_hints->initial_state=NormalState;
1791 manager_hints->window_group=windows->image.id;
1792 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1794 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1795 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1796 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1797 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1798 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1799 if (windows->image.mapped)
1800 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1801 if (display_image->debug != MagickFalse)
1802 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1805 Initialize Command widget.
1807 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1808 resource_info,&windows->command);
1809 windows->command.data=MagickMenus;
1810 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1811 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
1812 resource_info->client_name);
1813 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1814 resource_name,"geometry",(char *) NULL);
1815 (void) CloneString(&windows->command.name,MagickTitle);
1816 windows->command.border_width=0;
1817 windows->command.flags|=PPosition;
1818 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1819 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1820 OwnerGrabButtonMask | StructureNotifyMask;
1821 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1822 manager_hints->input=MagickTrue;
1823 manager_hints->initial_state=NormalState;
1824 manager_hints->window_group=windows->image.id;
1825 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1827 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1828 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1830 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1831 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1832 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1833 if (display_image->debug != MagickFalse)
1834 (void) LogMagickEvent(X11Event,GetMagickModule(),
1835 "Window id: 0x%lx (command)",windows->command.id);
1837 Initialize Widget window.
1839 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1840 resource_info,&windows->widget);
1841 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
1842 resource_info->client_name);
1843 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1844 resource_name,"geometry",(char *) NULL);
1845 windows->widget.border_width=0;
1846 windows->widget.flags|=PPosition;
1847 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1848 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1849 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1850 StructureNotifyMask;
1851 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1852 manager_hints->input=MagickTrue;
1853 manager_hints->initial_state=NormalState;
1854 manager_hints->window_group=windows->image.id;
1855 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1857 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1858 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1859 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1860 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1861 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1862 if (display_image->debug != MagickFalse)
1863 (void) LogMagickEvent(X11Event,GetMagickModule(),
1864 "Window id: 0x%lx (widget)",windows->widget.id);
1866 Initialize popup window.
1868 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1869 resource_info,&windows->popup);
1870 windows->popup.border_width=0;
1871 windows->popup.flags|=PPosition;
1872 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1873 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1874 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1875 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1876 manager_hints->input=MagickTrue;
1877 manager_hints->initial_state=NormalState;
1878 manager_hints->window_group=windows->image.id;
1879 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1881 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1882 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1883 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1884 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1885 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1886 if (display_image->debug != MagickFalse)
1887 (void) LogMagickEvent(X11Event,GetMagickModule(),
1888 "Window id: 0x%lx (pop up)",windows->popup.id);
1890 Set out progress and warning handlers.
1892 if (warning_handler == (WarningHandler) NULL)
1894 warning_handler=resource_info->display_warnings ?
1895 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1896 warning_handler=resource_info->display_warnings ?
1897 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1900 Initialize X image structure.
1905 Initialize image pixmaps structure.
1907 window_changes.width=(int) windows->image.width;
1908 window_changes.height=(int) windows->image.height;
1909 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1910 (unsigned int) (CWWidth | CWHeight),&window_changes);
1911 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1912 sizeof(*windows->image.pixmaps));
1913 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1914 sizeof(*windows->image.pixmaps));
1915 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1916 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1917 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1919 if ((windows->image.mapped == MagickFalse) ||
1920 (windows->backdrop.id != (Window) NULL))
1921 (void) XMapWindow(display,windows->image.id);
1922 XSetCursorState(display,windows,MagickTrue);
1923 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1932 if (IsRGBColorspace(image_list[scene]->colorspace) == MagickFalse)
1933 (void) TransformImageColorspace(image_list[scene],sRGBColorspace,
1935 windows->image.pixmap=(Pixmap) NULL;
1936 windows->image.matte_pixmap=(Pixmap) NULL;
1937 if ((resource_info->map_type != (char *) NULL) ||
1938 (visual_info->klass == TrueColor) ||
1939 (visual_info->klass == DirectColor))
1940 if (image_list[scene]->storage_class == PseudoClass)
1941 XGetPixelInfo(display,visual_info,map_info,resource_info,
1942 image_list[scene],windows->image.pixel_info);
1943 columns=(unsigned int) image_list[scene]->columns;
1944 rows=(unsigned int) image_list[scene]->rows;
1945 if ((image_list[scene]->columns != columns) ||
1946 (image_list[scene]->rows != rows))
1947 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1948 image_list[scene]->filename);
1949 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1950 columns,rows,exception);
1951 if (status == MagickFalse)
1952 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1954 if (image_list[scene]->debug != MagickFalse)
1956 (void) LogMagickEvent(X11Event,GetMagickModule(),
1957 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1958 image_list[scene]->filename,(double) columns,(double) rows);
1959 if (image_list[scene]->colors != 0)
1960 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1961 image_list[scene]->colors);
1962 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1963 image_list[scene]->magick);
1966 Window name is the base of the filename.
1968 if (resource_info->title != (char *) NULL)
1973 title=InterpretImageProperties(resource_info->image_info,
1974 image_list[scene],resource_info->title,exception);
1975 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1976 title=DestroyString(title);
1980 p=image_list[scene]->magick_filename+
1981 strlen(image_list[scene]->magick_filename)-1;
1982 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1984 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1985 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1986 (double) number_scenes);
1988 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1989 if (status != Success)
1991 XSetWMName(display,windows->image.id,&window_name);
1992 (void) XFree((void *) window_name.value);
1994 windows->image.pixmaps[scene]=windows->image.pixmap;
1995 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
2000 event.xexpose.width=(int) image_list[scene]->columns;
2001 event.xexpose.height=(int) image_list[scene]->rows;
2002 XRefreshWindow(display,&windows->image,&event);
2003 (void) XSync(display,MagickFalse);
2006 XSetCursorState(display,windows,MagickFalse);
2007 if (windows->command.mapped)
2008 (void) XMapRaised(display,windows->command.id);
2012 nexus=NewImageList();
2016 image=image_list[0];
2017 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2018 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2022 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2023 if ((state & PlayAnimationState) || (state & StepAnimationState))
2029 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2030 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2031 if (state & ForwardAnimationState)
2034 Forward animation: increment scene number.
2036 if (scene < ((ssize_t) number_scenes-1))
2041 if (iterations == (ssize_t) image_list[0]->iterations)
2046 if ((state & AutoReverseAnimationState) != 0)
2048 state&=(~ForwardAnimationState);
2053 if ((state & RepeatAnimationState) == 0)
2054 state&=(~PlayAnimationState);
2063 Reverse animation: decrement scene number.
2065 if (scene > first_scene)
2070 if (iterations == (ssize_t) image_list[0]->iterations)
2073 state&=(~RepeatAnimationState);
2075 if (state & AutoReverseAnimationState)
2077 state|=ForwardAnimationState;
2083 if ((state & RepeatAnimationState) == MagickFalse)
2084 state&=(~PlayAnimationState);
2085 scene=(ssize_t) number_scenes-1;
2089 scene=MagickMax(scene,0);
2090 image=image_list[scene];
2091 if ((image != (Image *) NULL) && (image->start_loop != 0))
2093 if ((state & StepAnimationState) ||
2094 (resource_info->title != (char *) NULL))
2097 Update window title.
2099 p=image_list[scene]->filename+
2100 strlen(image_list[scene]->filename)-1;
2101 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2103 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
2104 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2105 scene+1,(double) number_scenes);
2106 if (resource_info->title != (char *) NULL)
2111 title=InterpretImageProperties(resource_info->image_info,
2112 image,resource_info->title,exception);
2113 (void) CopyMagickString(windows->image.name,title,
2115 title=DestroyString(title);
2117 status=XStringListToTextProperty(&windows->image.name,1,
2119 if (status != Success)
2121 XSetWMName(display,windows->image.id,&window_name);
2122 (void) XFree((void *) window_name.value);
2126 Copy X pixmap to Image window.
2128 XGetPixelInfo(display,visual_info,map_info,resource_info,
2129 image_list[scene],windows->image.pixel_info);
2130 windows->image.ximage->width=(int) image->columns;
2131 windows->image.ximage->height=(int) image->rows;
2132 windows->image.pixmap=windows->image.pixmaps[scene];
2133 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2136 event.xexpose.width=(int) image->columns;
2137 event.xexpose.height=(int) image->rows;
2138 if ((state & ExitState) == 0)
2140 XRefreshWindow(display,&windows->image,&event);
2141 (void) XSync(display,MagickFalse);
2143 state&=(~StepAnimationState);
2144 if (pause != MagickFalse)
2145 for (i=0; i < (ssize_t) resource_info->pause; i++)
2150 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2157 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2158 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2159 *(command+length)='\0';
2160 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2162 XClientMessage(display,windows->image.id,
2163 windows->im_protocols,windows->im_exit,CurrentTime);
2172 Handle a window event.
2174 timestamp=time((time_t *) NULL);
2175 (void) XNextEvent(display,&event);
2176 if (windows->image.stasis == MagickFalse)
2177 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2178 MagickTrue : MagickFalse;
2179 if (event.xany.window == windows->command.id)
2185 Select a command from the Command widget.
2187 id=XCommandWidget(display,windows,CommandMenu,&event);
2190 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
2191 command_type=CommandMenus[id];
2192 if (id < MagickMenus)
2198 Select a command from a pop-up menu.
2200 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2204 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
2205 command_type=Commands[id][entry];
2207 if (command_type != NullCommand)
2208 nexus=XMagickCommand(display,resource_info,windows,
2209 command_type,&image,&state,exception);
2216 if (display_image->debug != MagickFalse)
2217 (void) LogMagickEvent(X11Event,GetMagickModule(),
2218 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2219 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2220 if ((event.xbutton.button == Button3) &&
2221 (event.xbutton.state & Mod1Mask))
2224 Convert Alt-Button3 to Button2.
2226 event.xbutton.button=Button2;
2227 event.xbutton.state&=(~Mod1Mask);
2229 if (event.xbutton.window == windows->backdrop.id)
2231 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2232 event.xbutton.time);
2235 if (event.xbutton.window == windows->image.id)
2237 if (resource_info->immutable != MagickFalse)
2243 Map/unmap Command widget.
2245 if (windows->command.mapped)
2246 (void) XWithdrawWindow(display,windows->command.id,
2247 windows->command.screen);
2250 (void) XCommandWidget(display,windows,CommandMenu,
2252 (void) XMapRaised(display,windows->command.id);
2259 if (display_image->debug != MagickFalse)
2260 (void) LogMagickEvent(X11Event,GetMagickModule(),
2261 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2262 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2267 if (display_image->debug != MagickFalse)
2268 (void) LogMagickEvent(X11Event,GetMagickModule(),
2269 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2270 event.xclient.window,(unsigned long) event.xclient.message_type,
2271 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2272 if (event.xclient.message_type == windows->im_protocols)
2274 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2277 Update graphic context and window colormap.
2279 for (i=0; i < (ssize_t) number_windows; i++)
2281 if (magick_windows[i]->id == windows->icon.id)
2283 context_values.background=pixel->background_color.pixel;
2284 context_values.foreground=pixel->foreground_color.pixel;
2285 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2286 context_mask,&context_values);
2287 (void) XChangeGC(display,magick_windows[i]->widget_context,
2288 context_mask,&context_values);
2289 context_values.background=pixel->foreground_color.pixel;
2290 context_values.foreground=pixel->background_color.pixel;
2291 context_values.plane_mask=
2292 context_values.background ^ context_values.foreground;
2293 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2294 (size_t) (context_mask | GCPlaneMask),
2296 magick_windows[i]->attributes.background_pixel=
2297 pixel->background_color.pixel;
2298 magick_windows[i]->attributes.border_pixel=
2299 pixel->border_color.pixel;
2300 magick_windows[i]->attributes.colormap=map_info->colormap;
2301 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2302 (unsigned long) magick_windows[i]->mask,
2303 &magick_windows[i]->attributes);
2305 if (windows->backdrop.id != (Window) NULL)
2306 (void) XInstallColormap(display,map_info->colormap);
2309 if (*event.xclient.data.l == (long) windows->im_exit)
2316 if (event.xclient.message_type == windows->dnd_protocols)
2334 Display image named by the Drag-and-Drop selection.
2336 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2338 selection=XInternAtom(display,"DndSelection",MagickFalse);
2339 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2340 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2342 if ((status != Success) || (length == 0))
2344 if (*event.xclient.data.l == 2)
2349 (void) CopyMagickString(resource_info->image_info->filename,
2350 (char *) data,MaxTextExtent);
2357 if (LocaleNCompare((char *) data,"file:",5) != 0)
2359 (void) XFree((void *) data);
2362 (void) CopyMagickString(resource_info->image_info->filename,
2363 ((char *) data)+5,MaxTextExtent);
2365 nexus=ReadImage(resource_info->image_info,exception);
2366 CatchException(exception);
2367 if (nexus != (Image *) NULL)
2369 (void) XFree((void *) data);
2373 If client window delete message, exit.
2375 if (event.xclient.message_type != windows->wm_protocols)
2377 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2379 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2380 (Time) event.xclient.data.l[1]);
2383 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2385 (void) XWithdrawWindow(display,event.xclient.window,
2386 visual_info->screen);
2387 if (event.xclient.window == windows->image.id)
2394 case ConfigureNotify:
2396 if (display_image->debug != MagickFalse)
2397 (void) LogMagickEvent(X11Event,GetMagickModule(),
2398 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2399 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2400 event.xconfigure.y,event.xconfigure.send_event);
2401 if (event.xconfigure.window == windows->image.id)
2403 if (event.xconfigure.send_event != 0)
2409 Position the transient windows relative of the Image window.
2411 if (windows->command.geometry == (char *) NULL)
2412 if (windows->command.mapped == MagickFalse)
2415 event.xconfigure.x-windows->command.width-25;
2416 windows->command.y=event.xconfigure.y;
2417 XConstrainWindowPosition(display,&windows->command);
2418 window_changes.x=windows->command.x;
2419 window_changes.y=windows->command.y;
2420 (void) XReconfigureWMWindow(display,windows->command.id,
2421 windows->command.screen,(unsigned int) (CWX | CWY),
2424 if (windows->widget.geometry == (char *) NULL)
2425 if (windows->widget.mapped == MagickFalse)
2428 event.xconfigure.x+event.xconfigure.width/10;
2430 event.xconfigure.y+event.xconfigure.height/10;
2431 XConstrainWindowPosition(display,&windows->widget);
2432 window_changes.x=windows->widget.x;
2433 window_changes.y=windows->widget.y;
2434 (void) XReconfigureWMWindow(display,windows->widget.id,
2435 windows->widget.screen,(unsigned int) (CWX | CWY),
2440 Image window has a new configuration.
2442 windows->image.width=(unsigned int) event.xconfigure.width;
2443 windows->image.height=(unsigned int) event.xconfigure.height;
2446 if (event.xconfigure.window == windows->icon.id)
2449 Icon window has a new configuration.
2451 windows->icon.width=(unsigned int) event.xconfigure.width;
2452 windows->icon.height=(unsigned int) event.xconfigure.height;
2460 Group leader has exited.
2462 if (display_image->debug != MagickFalse)
2463 (void) LogMagickEvent(X11Event,GetMagickModule(),
2464 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2465 if (event.xdestroywindow.window == windows->group_leader.id)
2475 Selectively install colormap.
2477 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2478 if (event.xcrossing.mode != NotifyUngrab)
2479 XInstallColormap(display,map_info->colormap);
2484 if (display_image->debug != MagickFalse)
2485 (void) LogMagickEvent(X11Event,GetMagickModule(),
2486 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2487 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2490 Repaint windows that are now exposed.
2492 if (event.xexpose.window == windows->image.id)
2494 windows->image.pixmap=windows->image.pixmaps[scene];
2495 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2496 XRefreshWindow(display,&windows->image,&event);
2499 if (event.xexpose.window == windows->icon.id)
2500 if (event.xexpose.count == 0)
2502 XRefreshWindow(display,&windows->icon,&event);
2513 Respond to a user key press.
2515 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2516 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2517 *(command+length)='\0';
2518 if (display_image->debug != MagickFalse)
2519 (void) LogMagickEvent(X11Event,GetMagickModule(),
2520 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2521 command_type=NullCommand;
2526 if ((event.xkey.state & ControlMask) == MagickFalse)
2528 command_type=OpenCommand;
2533 command_type=StepBackwardCommand;
2538 command_type=StepForwardCommand;
2543 command_type=FasterCommand;
2548 command_type=SlowerCommand;
2553 command_type=HelpCommand;
2558 command_type=BrowseDocumentationCommand;
2563 command_type=InfoCommand;
2569 command_type=QuitCommand;
2575 if (command_type != NullCommand)
2576 nexus=XMagickCommand(display,resource_info,windows,
2577 command_type,&image,&state,exception);
2583 Respond to a user key release.
2585 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2586 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2587 if (display_image->debug != MagickFalse)
2588 (void) LogMagickEvent(X11Event,GetMagickModule(),
2589 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2595 Selectively uninstall colormap.
2597 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2598 if (event.xcrossing.mode != NotifyUngrab)
2599 XUninstallColormap(display,map_info->colormap);
2604 if (display_image->debug != MagickFalse)
2605 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2607 if (event.xmap.window == windows->backdrop.id)
2609 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2611 windows->backdrop.mapped=MagickTrue;
2614 if (event.xmap.window == windows->image.id)
2616 if (windows->backdrop.id != (Window) NULL)
2617 (void) XInstallColormap(display,map_info->colormap);
2618 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2620 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2621 nexus=XMagickCommand(display,resource_info,windows,
2622 OpenCommand,&image,&state,exception);
2626 windows->image.mapped=MagickTrue;
2629 if (event.xmap.window == windows->info.id)
2631 windows->info.mapped=MagickTrue;
2634 if (event.xmap.window == windows->icon.id)
2637 Create an icon image.
2639 XMakeStandardColormap(display,icon_visual,icon_resources,
2640 display_image,icon_map,icon_pixel,exception);
2641 (void) XMakeImage(display,icon_resources,&windows->icon,
2642 display_image,windows->icon.width,windows->icon.height,
2644 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2645 windows->icon.pixmap);
2646 (void) XClearWindow(display,windows->icon.id);
2647 (void) XWithdrawWindow(display,windows->info.id,
2648 windows->info.screen);
2649 windows->icon.mapped=MagickTrue;
2652 if (event.xmap.window == windows->command.id)
2654 windows->command.mapped=MagickTrue;
2657 if (event.xmap.window == windows->popup.id)
2659 windows->popup.mapped=MagickTrue;
2662 if (event.xmap.window == windows->widget.id)
2664 windows->widget.mapped=MagickTrue;
2671 (void) XRefreshKeyboardMapping(&event.xmapping);
2676 case PropertyNotify:
2692 if (display_image->debug != MagickFalse)
2693 (void) LogMagickEvent(X11Event,GetMagickModule(),
2694 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2695 event.xproperty.window,(unsigned long) event.xproperty.atom,
2696 event.xproperty.state);
2697 if (event.xproperty.atom != windows->im_remote_command)
2700 Display image named by the remote command protocol.
2702 status=XGetWindowProperty(display,event.xproperty.window,
2703 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
2704 AnyPropertyType,&type,&format,&length,&after,&data);
2705 if ((status != Success) || (length == 0))
2707 (void) CopyMagickString(resource_info->image_info->filename,
2708 (char *) data,MaxTextExtent);
2709 nexus=ReadImage(resource_info->image_info,exception);
2710 CatchException(exception);
2711 if (nexus != (Image *) NULL)
2713 (void) XFree((void *) data);
2716 case ReparentNotify:
2718 if (display_image->debug != MagickFalse)
2719 (void) LogMagickEvent(X11Event,GetMagickModule(),
2720 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2721 event.xreparent.window);
2726 if (display_image->debug != MagickFalse)
2727 (void) LogMagickEvent(X11Event,GetMagickModule(),
2728 "Unmap Notify: 0x%lx",event.xunmap.window);
2729 if (event.xunmap.window == windows->backdrop.id)
2731 windows->backdrop.mapped=MagickFalse;
2734 if (event.xunmap.window == windows->image.id)
2736 windows->image.mapped=MagickFalse;
2739 if (event.xunmap.window == windows->info.id)
2741 windows->info.mapped=MagickFalse;
2744 if (event.xunmap.window == windows->icon.id)
2746 if (map_info->colormap == icon_map->colormap)
2747 XConfigureImageColormap(display,resource_info,windows,
2748 display_image,exception);
2749 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2751 windows->icon.mapped=MagickFalse;
2754 if (event.xunmap.window == windows->command.id)
2756 windows->command.mapped=MagickFalse;
2759 if (event.xunmap.window == windows->popup.id)
2761 if (windows->backdrop.id != (Window) NULL)
2762 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2764 windows->popup.mapped=MagickFalse;
2767 if (event.xunmap.window == windows->widget.id)
2769 if (windows->backdrop.id != (Window) NULL)
2770 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2772 windows->widget.mapped=MagickFalse;
2779 if (display_image->debug != MagickFalse)
2780 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2786 while (!(state & ExitState));
2787 image_list=(Image **) RelinquishMagickMemory(image_list);
2788 images=DestroyImageList(images);
2789 if ((windows->visual_info->klass == GrayScale) ||
2790 (windows->visual_info->klass == PseudoColor) ||
2791 (windows->visual_info->klass == DirectColor))
2796 if (windows->info.mapped)
2797 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2798 if (windows->command.mapped)
2799 (void) XWithdrawWindow(display,windows->command.id,
2800 windows->command.screen);
2802 if (resource_info->backdrop == MagickFalse)
2803 if (windows->backdrop.mapped)
2805 (void) XWithdrawWindow(display,windows->backdrop.id,\
2806 windows->backdrop.screen);
2807 (void) XDestroyWindow(display,windows->backdrop.id);
2808 windows->backdrop.id=(Window) NULL;
2809 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2810 (void) XDestroyWindow(display,windows->image.id);
2811 windows->image.id=(Window) NULL;
2813 XSetCursorState(display,windows,MagickTrue);
2814 XCheckRefreshWindows(display,windows);
2815 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2817 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2818 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2819 windows->image.pixmaps[scene]=(Pixmap) NULL;
2820 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2821 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2822 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2824 XSetCursorState(display,windows,MagickFalse);
2825 windows->image.pixmaps=(Pixmap *)
2826 RelinquishMagickMemory(windows->image.pixmaps);
2827 windows->image.matte_pixmaps=(Pixmap *)
2828 RelinquishMagickMemory(windows->image.matte_pixmaps);
2829 if (nexus == (Image *) NULL)
2834 if (windows->image.mapped != MagickFalse)
2835 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime);
2836 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2837 if (resource_info->map_type == (char *) NULL)
2838 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2839 DestroyXResources();
2841 (void) XSync(display,MagickFalse);
2843 Restore our progress monitor and warning handlers.
2845 (void) SetErrorHandler(warning_handler);
2846 (void) SetWarningHandler(warning_handler);
2848 Change to home directory.
2850 directory=getcwd(working_directory,MaxTextExtent);
2852 status=chdir(resource_info->home_directory);
2854 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2855 "UnableToOpenFile","%s",resource_info->home_directory);
2860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2864 + X S a v e I m a g e %
2868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2870 % XSaveImage() saves an image to a file.
2872 % The format of the XSaveImage method is:
2874 % MagickBooleanType XSaveImage(Display *display,
2875 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2876 % ExceptionInfo *exception)
2878 % A description of each parameter follows:
2880 % o status: Method XSaveImage return True if the image is
2881 % written. False is returned is there is a memory shortage or if the
2882 % image fails to write.
2884 % o display: Specifies a connection to an X server; returned from
2887 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2889 % o windows: Specifies a pointer to a XWindows structure.
2891 % o image: the image.
2894 static MagickBooleanType XSaveImage(Display *display,
2895 XResourceInfo *resource_info,XWindows *windows,Image *image,
2896 ExceptionInfo *exception)
2899 filename[MaxTextExtent];
2908 Request file name from user.
2910 if (resource_info->write_filename != (char *) NULL)
2911 (void) CopyMagickString(filename,resource_info->write_filename,
2916 path[MaxTextExtent];
2921 GetPathComponent(image->filename,HeadPath,path);
2922 GetPathComponent(image->filename,TailPath,filename);
2925 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2926 "UnableToOpenFile","%s",path);
2928 XFileBrowserWidget(display,windows,"Save",filename);
2929 if (*filename == '\0')
2931 if (IsPathAccessible(filename) != MagickFalse)
2937 File exists-- seek user's permission before overwriting.
2939 status=XConfirmWidget(display,windows,"Overwrite",filename);
2943 image_info=CloneImageInfo(resource_info->image_info);
2944 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2945 (void) SetImageInfo(image_info,1,exception);
2946 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2947 (LocaleCompare(image_info->magick,"JPG") == 0))
2950 quality[MaxTextExtent];
2956 Request JPEG quality from user.
2958 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
2959 image_info->quality);
2960 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2962 if (*quality == '\0')
2964 image->quality=StringToUnsignedLong(quality);
2965 image_info->interlace=status != MagickFalse ? NoInterlace :
2968 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2969 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2970 (LocaleCompare(image_info->magick,"PS") == 0) ||
2971 (LocaleCompare(image_info->magick,"PS2") == 0))
2974 geometry[MaxTextExtent];
2977 Request page geometry from user.
2979 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2980 if (LocaleCompare(image_info->magick,"PDF") == 0)
2981 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2982 if (image_info->page != (char *) NULL)
2983 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
2984 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2985 "Select page geometry:",geometry);
2986 if (*geometry != '\0')
2987 image_info->page=GetPageGeometry(geometry);
2992 image=GetFirstImageInList(image);
2993 status=WriteImages(image_info,image,filename,exception);
2994 if (status != MagickFalse)
2995 image->taint=MagickFalse;
2996 image_info=DestroyImageInfo(image_info);
2997 XSetCursorState(display,windows,MagickFalse);
2998 return(status != 0 ? MagickTrue : MagickFalse);
3003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3007 + A n i m a t e I m a g e s %
3011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3013 % AnimateImages() repeatedly displays an image sequence to any X window
3014 % screen. It returns a value other than 0 if successful. Check the
3015 % exception member of image to determine the reason for any failure.
3017 % The format of the AnimateImages method is:
3019 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3022 % A description of each parameter follows:
3024 % o image_info: the image info.
3026 % o image: the image.
3028 % o exception: return any errors or warnings in this structure.
3031 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3032 Image *image,ExceptionInfo *exception)
3034 assert(image_info != (const ImageInfo *) NULL);
3035 assert(image_info->signature == MagickSignature);
3036 assert(image != (Image *) NULL);
3037 assert(image->signature == MagickSignature);
3038 if (image->debug != MagickFalse)
3039 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3040 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
3041 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
3042 return(MagickFalse);