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-2011 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 SetErrorHandler((ErrorHandler) NULL);
321 SetWarningHandler((WarningHandler) NULL);
322 SetErrorHandler((ErrorHandler) NULL);
323 SetWarningHandler((WarningHandler) NULL);
324 argv[0]=DestroyString(argv[0]);
325 (void) XCloseDisplay(display);
326 XDestroyResourceInfo(&resource_info);
327 status=exception->severity == UndefinedException ? MagickTrue : MagickFalse;
328 return(status != 0 ? MagickTrue : MagickFalse);
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336 + X M a g i c k C o m m a n d %
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 % XMagickCommand() makes a transform to the image or Image window as specified
343 % by a user menu button or keyboard command.
345 % The format of the XMagickCommand method is:
347 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
348 % XWindows *windows,const CommandType command_type,Image **image,
349 % MagickStatusType *state,ExceptionInfo *exception)
351 % A description of each parameter follows:
353 % o display: Specifies a connection to an X server; returned from
356 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
358 % o windows: Specifies a pointer to a XWindows structure.
360 % o image: the image; XMagickCommand
361 % may transform the image and return a new image pointer.
363 % o state: Specifies a MagickStatusType; XMagickCommand may return a
366 % o exception: return any errors or warnings in this structure.
370 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
371 XWindows *windows,const CommandType command_type,Image **image,
372 MagickStatusType *state,ExceptionInfo *exception)
387 Process user command.
389 nexus=NewImageList();
390 switch (command_type)
411 filenames[MaxTextExtent] = "*";
413 if (resource_info->immutable != MagickFalse)
416 Request file name from user.
418 XFileBrowserWidget(display,windows,"Animate",filenames);
419 if (*filenames == '\0')
420 return((Image *) NULL);
422 Expand the filenames.
424 filelist=(char **) AcquireMagickMemory(sizeof(char *));
425 if (filelist == (char **) NULL)
427 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
429 return((Image *) NULL);
432 filelist[0]=filenames;
433 status=ExpandFilenames(&number_files,&filelist);
434 if ((status == MagickFalse) || (number_files == 0))
436 if (number_files == 0)
438 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
439 return((Image *) NULL);
441 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
443 return((Image *) NULL);
445 read_info=CloneImageInfo(resource_info->image_info);
446 images=NewImageList();
447 XSetCursorState(display,windows,MagickTrue);
448 XCheckRefreshWindows(display,windows);
449 for (i=0; i < number_files; i++)
451 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
452 filelist[i]=DestroyString(filelist[i]);
453 *read_info->magick='\0';
454 next=ReadImage(read_info,exception);
455 CatchException(exception);
456 if (next != (Image *) NULL)
457 AppendImageToList(&images,next);
458 if (number_files <= 5)
460 proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
462 if (proceed == MagickFalse)
465 filelist=(char **) RelinquishMagickMemory(filelist);
466 read_info=DestroyImageInfo(read_info);
467 if (images == (Image *) NULL)
469 XSetCursorState(display,windows,MagickFalse);
470 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
471 return((Image *) NULL);
473 nexus=GetFirstImageInList(images);
480 basename[MaxTextExtent];
486 Window name is the base of the filename.
488 *state|=PlayAnimationState;
489 *state&=(~AutoReverseAnimationState);
490 GetPathComponent((*image)->magick_filename,BasePath,basename);
491 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
492 "%s: %s",MagickPackageName,basename);
493 if (resource_info->title != (char *) NULL)
498 title=InterpretImageProperties(resource_info->image_info,*image,
499 resource_info->title,exception);
500 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
501 title=DestroyString(title);
503 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
506 XSetWMName(display,windows->image.id,&window_name);
507 (void) XFree((void *) window_name.value);
511 case StepBackwardCommand:
512 case StepForwardCommand:
514 *state|=StepAnimationState;
515 *state&=(~PlayAnimationState);
516 if (command_type == StepBackwardCommand)
517 *state&=(~ForwardAnimationState);
518 if (command_type == StepForwardCommand)
519 *state|=ForwardAnimationState;
520 if (resource_info->title != (char *) NULL)
526 *state|=RepeatAnimationState;
527 *state&=(~AutoReverseAnimationState);
528 *state|=PlayAnimationState;
531 case AutoReverseCommand:
533 *state|=AutoReverseAnimationState;
534 *state&=(~RepeatAnimationState);
535 *state|=PlayAnimationState;
543 status=XSaveImage(display,resource_info,windows,*image,exception);
544 if (status == MagickFalse)
546 XNoticeWidget(display,windows,"Unable to write X image:",
554 resource_info->delay++;
559 if (resource_info->delay == 0)
561 resource_info->delay--;
566 *state=ForwardAnimationState;
567 *state&=(~AutoReverseAnimationState);
572 *state&=(~ForwardAnimationState);
573 *state&=(~AutoReverseAnimationState);
578 XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image);
586 XTextViewWidget(display,resource_info,windows,MagickFalse,
587 "Help Viewer - Animate",AnimateHelp);
590 case BrowseDocumentationCommand:
600 Browse the ImageMagick documentation.
602 root_window=XRootWindow(display,XDefaultScreen(display));
603 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
604 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
605 if (mozilla_window != (Window) NULL)
608 command[MaxTextExtent],
612 Display documentation using Netscape remote control.
614 url=GetMagickHomeURL();
615 (void) FormatLocaleString(command,MaxTextExtent,
616 "openurl(%s,new-tab)",url);
617 url=DestroyString(url);
618 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
619 (void) XChangeProperty(display,mozilla_window,mozilla_atom,
620 XA_STRING,8,PropModeReplace,(unsigned char *) command,
621 (int) strlen(command));
622 XSetCursorState(display,windows,MagickFalse);
625 XSetCursorState(display,windows,MagickTrue);
626 XCheckRefreshWindows(display,windows);
627 status=InvokeDelegate(resource_info->image_info,*image,"browse",
628 (char *) NULL,exception);
629 if (status == MagickFalse)
630 XNoticeWidget(display,windows,"Unable to browse documentation",
632 XDelay(display,1500);
633 XSetCursorState(display,windows,MagickFalse);
638 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
639 GetMagickCopyright());
647 if (resource_info->confirm_exit == MagickFalse)
648 XClientMessage(display,windows->image.id,windows->im_protocols,
649 windows->im_exit,CurrentTime);
656 Confirm program exit.
658 status=XConfirmWidget(display,windows,"Do you really want to exit",
659 resource_info->client_name);
661 XClientMessage(display,windows->image.id,windows->im_protocols,
662 windows->im_exit,CurrentTime);
673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
677 + X A n i m a t e B a c k g r o u n d I m a g e %
681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683 % XAnimateBackgroundImage() animates an image sequence in the background of
686 % The format of the XAnimateBackgroundImage method is:
688 % void XAnimateBackgroundImage(Display *display,
689 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
691 % A description of each parameter follows:
693 % o display: Specifies a connection to an X server; returned from
696 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
698 % o images: the image list.
700 % o exception: return any errors or warnings in this structure.
704 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
711 #if defined(__cplusplus) || defined(c_plusplus)
715 static int SceneCompare(const void *x,const void *y)
721 image_1=(const Image **) x;
722 image_2=(const Image **) y;
723 return((int) ((*image_1)->scene-(*image_2)->scene));
726 #if defined(__cplusplus) || defined(c_plusplus)
730 MagickExport void XAnimateBackgroundImage(Display *display,
731 XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
734 geometry[MaxTextExtent],
735 visual_type[MaxTextExtent];
760 static XStandardColormap
764 *visual_info = (XVisualInfo *) NULL;
792 Determine target window.
794 assert(images != (Image *) NULL);
795 assert(images->signature == MagickSignature);
796 if (images->debug != MagickFalse)
797 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
798 resources=(*resource_info);
799 window_info.id=(Window) NULL;
800 root_window=XRootWindow(display,XDefaultScreen(display));
801 if (LocaleCompare(resources.window_id,"root") == 0)
802 window_info.id=root_window;
805 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
806 window_info.id=XWindowByID(display,root_window,
807 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
808 if (window_info.id == (Window) NULL)
810 XWindowByName(display,root_window,resources.window_id);
812 if (window_info.id == (Window) NULL)
814 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
815 resources.window_id);
819 Determine window visual id.
821 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
822 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
823 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
824 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
825 MagickTrue : MagickFalse;
826 if (status != MagickFalse)
827 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
828 XVisualIDFromVisual(window_attributes.visual));
829 if (visual_info == (XVisualInfo *) NULL)
832 Allocate standard colormap.
834 map_info=XAllocStandardColormap();
835 if (map_info == (XStandardColormap *) NULL)
836 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
838 map_info->colormap=(Colormap) NULL;
839 pixel.pixels=(unsigned long *) NULL;
841 Initialize visual info.
843 resources.map_type=(char *) NULL;
844 resources.visual_type=visual_type;
845 visual_info=XBestVisualInfo(display,map_info,&resources);
846 if (visual_info == (XVisualInfo *) NULL)
847 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
850 Initialize window info.
852 window_info.ximage=(XImage *) NULL;
853 window_info.matte_image=(XImage *) NULL;
854 window_info.pixmap=(Pixmap) NULL;
855 window_info.matte_pixmap=(Pixmap) NULL;
858 Free previous root colors.
860 if (window_info.id == root_window)
861 XDestroyWindowColors(display,root_window);
862 coalesce_image=CoalesceImages(images,exception);
863 if (coalesce_image == (Image *) NULL)
864 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
866 images=coalesce_image;
867 if (resources.map_type == (char *) NULL)
868 if ((visual_info->klass != TrueColor) &&
869 (visual_info->klass != DirectColor))
875 Determine if the sequence of images has the identical colormap.
877 for (next=images; next != (Image *) NULL; )
879 next->matte=MagickFalse;
880 if ((next->storage_class == DirectClass) ||
881 (next->colors != images->colors) ||
882 (next->colors > (size_t) visual_info->colormap_size))
884 for (i=0; i < (ssize_t) images->colors; i++)
885 if (IsPixelPacketEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
887 if (i < (ssize_t) images->colors)
889 next=GetNextImageInList(next);
891 if (next != (Image *) NULL)
892 (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
896 Sort images by increasing scene number.
898 number_scenes=GetImageListLength(images);
899 image_list=ImageListToArray(images,exception);
900 if (image_list == (Image **) NULL)
901 ThrowXWindowFatalException(ResourceLimitFatalError,
902 "MemoryAllocationFailed",images->filename);
903 for (i=0; i < (ssize_t) number_scenes; i++)
904 if (image_list[i]->scene == 0)
906 if (i == (ssize_t) number_scenes)
907 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
909 Initialize Standard Colormap.
911 resources.colormap=SharedColormap;
912 display_image=image_list[0];
913 for (scene=0; scene < (int) number_scenes; scene++)
915 if ((resource_info->map_type != (char *) NULL) ||
916 (visual_info->klass == TrueColor) ||
917 (visual_info->klass == DirectColor))
918 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
919 MagickFalse ? TrueColorType : TrueColorMatteType,exception);
920 if ((display_image->columns < image_list[scene]->columns) &&
921 (display_image->rows < image_list[scene]->rows))
922 display_image=image_list[scene];
924 if ((resource_info->map_type != (char *) NULL) ||
925 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
926 (void) SetImageType(display_image,display_image->matte == MagickFalse ?
927 TrueColorType : TrueColorMatteType,exception);
928 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
931 Graphic context superclass.
933 context_values.background=pixel.background_color.pixel;
934 context_values.foreground=pixel.foreground_color.pixel;
935 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
936 (GCBackground | GCForeground),&context_values);
937 if (pixel.annotate_context == (GC) NULL)
938 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
941 Initialize Image window attributes.
943 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
944 &resources,&window_info);
948 window_info.width=(unsigned int) image_list[0]->columns;
949 window_info.height=(unsigned int) image_list[0]->rows;
950 if ((image_list[0]->columns != window_info.width) ||
951 (image_list[0]->rows != window_info.height))
952 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
953 image_list[0]->filename);
954 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
955 window_attributes.width,window_attributes.height);
956 geometry_info.width=window_info.width;
957 geometry_info.height=window_info.height;
958 geometry_info.x=(ssize_t) window_info.x;
959 geometry_info.y=(ssize_t) window_info.y;
960 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
961 &geometry_info.width,&geometry_info.height);
962 window_info.width=(unsigned int) geometry_info.width;
963 window_info.height=(unsigned int) geometry_info.height;
964 window_info.x=(int) geometry_info.x;
965 window_info.y=(int) geometry_info.y;
966 status=XMakeImage(display,&resources,&window_info,image_list[0],
967 window_info.width,window_info.height,exception);
968 if (status == MagickFalse)
969 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
973 if (display_image->debug != MagickFalse)
975 (void) LogMagickEvent(X11Event,GetMagickModule(),
976 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
977 image_list[0]->scene,(double) image_list[0]->columns,(double)
978 image_list[0]->rows);
979 if (image_list[0]->colors != 0)
980 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
981 image_list[0]->colors);
982 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
983 image_list[0]->magick);
986 Adjust image dimensions as specified by backdrop or geometry options.
988 width=window_info.width;
989 height=window_info.height;
990 if (resources.backdrop != MagickFalse)
993 Center image on window.
995 window_info.x=(int) (window_attributes.width/2)-
996 (window_info.ximage->width/2);
997 window_info.y=(int) (window_attributes.height/2)-
998 (window_info.ximage->height/2);
999 width=(unsigned int) window_attributes.width;
1000 height=(unsigned int) window_attributes.height;
1002 if (resources.image_geometry != (char *) NULL)
1005 default_geometry[MaxTextExtent];
1015 User specified geometry.
1017 size_hints=XAllocSizeHints();
1018 if (size_hints == (XSizeHints *) NULL)
1019 ThrowXWindowFatalException(ResourceLimitFatalError,
1020 "MemoryAllocationFailed",images->filename);
1021 size_hints->flags=0L;
1022 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%ux%u",width,
1024 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1025 default_geometry,window_info.border_width,size_hints,&window_info.x,
1026 &window_info.y,(int *) &width,(int *) &height,&gravity);
1027 if (((flags & (XValue | YValue))) != 0)
1029 width=(unsigned int) window_attributes.width;
1030 height=(unsigned int) window_attributes.height;
1032 (void) XFree((void *) size_hints);
1035 Create the X pixmap.
1037 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1038 (unsigned int) height,window_info.depth);
1039 if (window_info.pixmap == (Pixmap) NULL)
1040 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1043 Display pixmap on the window.
1045 if (((unsigned int) width > window_info.width) ||
1046 ((unsigned int) height > window_info.height))
1047 (void) XFillRectangle(display,window_info.pixmap,
1048 window_info.annotate_context,0,0,(unsigned int) width,
1049 (unsigned int) height);
1050 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1051 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1052 window_info.height);
1053 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1054 (void) XClearWindow(display,window_info.id);
1056 Initialize image pixmaps structure.
1058 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1059 sizeof(*window_info.pixmaps));
1060 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1061 sizeof(*window_info.matte_pixmaps));
1062 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1063 (window_info.matte_pixmaps == (Pixmap *) NULL))
1064 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1066 window_info.pixmaps[0]=window_info.pixmap;
1067 window_info.matte_pixmaps[0]=window_info.pixmap;
1068 for (scene=1; scene < (int) number_scenes; scene++)
1077 window_info.pixmap=(Pixmap) NULL;
1078 window_info.matte_pixmap=(Pixmap) NULL;
1079 if ((resources.map_type != (char *) NULL) ||
1080 (visual_info->klass == TrueColor) ||
1081 (visual_info->klass == DirectColor))
1082 if (image_list[scene]->storage_class == PseudoClass)
1083 XGetPixelInfo(display,visual_info,map_info,&resources,
1084 image_list[scene],window_info.pixel_info);
1085 columns=(unsigned int) image_list[scene]->columns;
1086 rows=(unsigned int) image_list[scene]->rows;
1087 if ((image_list[scene]->columns != columns) ||
1088 (image_list[scene]->rows != rows))
1089 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1090 image_list[scene]->filename);
1091 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1092 columns,rows,exception);
1093 if (status == MagickFalse)
1094 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1096 if (display_image->debug != MagickFalse)
1098 (void) LogMagickEvent(X11Event,GetMagickModule(),
1099 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1100 image_list[scene]->filename,(double) columns,(double) rows);
1101 if (image_list[scene]->colors != 0)
1102 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1103 image_list[scene]->colors);
1104 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1105 image_list[scene]->magick);
1108 Create the X pixmap.
1110 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1112 if (window_info.pixmap == (Pixmap) NULL)
1113 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1116 Display pixmap on the window.
1118 if ((width > window_info.width) || (height > window_info.height))
1119 (void) XFillRectangle(display,window_info.pixmap,
1120 window_info.annotate_context,0,0,width,height);
1121 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1122 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1123 window_info.height);
1124 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1125 window_info.pixmap);
1126 (void) XClearWindow(display,window_info.id);
1127 window_info.pixmaps[scene]=window_info.pixmap;
1128 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1129 if (image_list[scene]->matte)
1130 (void) XClearWindow(display,window_info.id);
1131 delay=1000*image_list[scene]->delay/MagickMax(
1132 image_list[scene]->ticks_per_second,1L);
1133 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1135 window_info.pixel_info=(&pixel);
1137 Display pixmap on the window.
1139 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1143 for (scene=0; scene < (int) number_scenes; scene++)
1145 if (XEventsQueued(display,QueuedAfterFlush) > 0)
1147 (void) XNextEvent(display,&event);
1148 if (event.type == DestroyNotify)
1151 window_info.pixmap=window_info.pixmaps[scene];
1152 window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1153 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1154 window_info.pixmap);
1155 (void) XClearWindow(display,window_info.id);
1156 (void) XSync(display,MagickFalse);
1157 delay=1000*image_list[scene]->delay/MagickMax(
1158 image_list[scene]->ticks_per_second,1L);
1159 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1161 } while (event.type != DestroyNotify);
1162 (void) XSync(display,MagickFalse);
1163 image_list=(Image **) RelinquishMagickMemory(image_list);
1164 images=DestroyImageList(images);
1168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172 + X A n i m a t e I m a g e s %
1176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1178 % XAnimateImages() displays an image via X11.
1180 % The format of the XAnimateImages method is:
1182 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1183 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1185 % A description of each parameter follows:
1187 % o display: Specifies a connection to an X server; returned from
1190 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1192 % o argv: Specifies the application's argument list.
1194 % o argc: Specifies the number of arguments.
1196 % o images: the image list.
1198 % o exception: return any errors or warnings in this structure.
1201 MagickExport Image *XAnimateImages(Display *display,
1202 XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1203 ExceptionInfo *exception)
1205 #define MagickMenus 4
1206 #define MaXWindows 8
1207 #define MagickTitle "Commands"
1245 "Browse Documentation",
1251 **Menus[MagickMenus]=
1259 static const CommandType
1283 DirectionCommands[]=
1291 BrowseDocumentationCommand,
1295 static const CommandType
1296 *Commands[MagickMenus]=
1305 command[MaxTextExtent],
1307 geometry[MaxTextExtent],
1308 resource_name[MaxTextExtent];
1345 working_directory[MaxTextExtent];
1351 *magick_windows[MaXWindows];
1405 assert(images != (Image *) NULL);
1406 assert(images->signature == MagickSignature);
1407 if (images->debug != MagickFalse)
1408 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1409 warning_handler=(WarningHandler) NULL;
1410 windows=XSetWindows((XWindows *) ~0);
1411 if (windows != (XWindows *) NULL)
1416 status=chdir(working_directory);
1418 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
1419 "UnableToOpenFile","%s",working_directory);
1420 warning_handler=resource_info->display_warnings ?
1421 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1422 warning_handler=resource_info->display_warnings ?
1423 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1431 Initialize window structure.
1433 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1435 if (p->storage_class == DirectClass)
1437 resource_info->colors=0;
1440 if (p->colors > resource_info->colors)
1441 resource_info->colors=p->colors;
1443 windows=XSetWindows(XInitializeWindows(display,resource_info));
1444 if (windows == (XWindows *) NULL)
1445 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1448 Initialize window id's.
1451 magick_windows[number_windows++]=(&windows->icon);
1452 magick_windows[number_windows++]=(&windows->backdrop);
1453 magick_windows[number_windows++]=(&windows->image);
1454 magick_windows[number_windows++]=(&windows->info);
1455 magick_windows[number_windows++]=(&windows->command);
1456 magick_windows[number_windows++]=(&windows->widget);
1457 magick_windows[number_windows++]=(&windows->popup);
1458 for (i=0; i < (ssize_t) number_windows; i++)
1459 magick_windows[i]->id=(Window) NULL;
1462 Initialize font info.
1464 if (windows->font_info != (XFontStruct *) NULL)
1465 (void) XFreeFont(display,windows->font_info);
1466 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1467 if (windows->font_info == (XFontStruct *) NULL)
1468 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1469 resource_info->font);
1471 Initialize Standard Colormap.
1473 map_info=windows->map_info;
1474 icon_map=windows->icon_map;
1475 visual_info=windows->visual_info;
1476 icon_visual=windows->icon_visual;
1477 pixel=windows->pixel_info;
1478 icon_pixel=windows->icon_pixel;
1479 font_info=windows->font_info;
1480 icon_resources=windows->icon_resources;
1481 class_hints=windows->class_hints;
1482 manager_hints=windows->manager_hints;
1483 root_window=XRootWindow(display,visual_info->screen);
1484 coalesce_image=CoalesceImages(images,exception);
1485 if (coalesce_image == (Image *) NULL)
1486 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1488 images=coalesce_image;
1489 if (resource_info->map_type == (char *) NULL)
1490 if ((visual_info->klass != TrueColor) &&
1491 (visual_info->klass != DirectColor))
1497 Determine if the sequence of images has the identical colormap.
1499 for (next=images; next != (Image *) NULL; )
1501 next->matte=MagickFalse;
1502 if ((next->storage_class == DirectClass) ||
1503 (next->colors != images->colors) ||
1504 (next->colors > (size_t) visual_info->colormap_size))
1506 for (i=0; i < (ssize_t) images->colors; i++)
1507 if (IsPixelPacketEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1509 if (i < (ssize_t) images->colors)
1511 next=GetNextImageInList(next);
1513 if (next != (Image *) NULL)
1514 (void) RemapImages(resource_info->quantize_info,images,
1515 (Image *) NULL,exception);
1518 Sort images by increasing scene number.
1520 number_scenes=GetImageListLength(images);
1521 image_list=ImageListToArray(images,exception);
1522 if (image_list == (Image **) NULL)
1523 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1525 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1526 if (image_list[scene]->scene == 0)
1528 if (scene == (ssize_t) number_scenes)
1529 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1531 Initialize Standard Colormap.
1533 nexus=NewImageList();
1534 display_image=image_list[0];
1535 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1537 if ((resource_info->map_type != (char *) NULL) ||
1538 (visual_info->klass == TrueColor) ||
1539 (visual_info->klass == DirectColor))
1540 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
1541 MagickFalse ? TrueColorType : TrueColorMatteType,exception);
1542 if ((display_image->columns < image_list[scene]->columns) &&
1543 (display_image->rows < image_list[scene]->rows))
1544 display_image=image_list[scene];
1546 if (display_image->debug != MagickFalse)
1548 (void) LogMagickEvent(X11Event,GetMagickModule(),
1549 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1550 display_image->scene,(double) display_image->columns,(double)
1551 display_image->rows);
1552 if (display_image->colors != 0)
1553 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1554 display_image->colors);
1555 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1556 display_image->magick);
1558 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1561 Initialize graphic context.
1563 windows->context.id=(Window) NULL;
1564 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1565 resource_info,&windows->context);
1566 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1567 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1568 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1569 manager_hints->flags=InputHint | StateHint;
1570 manager_hints->input=MagickFalse;
1571 manager_hints->initial_state=WithdrawnState;
1572 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1574 if (display_image->debug != MagickFalse)
1575 (void) LogMagickEvent(X11Event,GetMagickModule(),
1576 "Window id: 0x%lx (context)",windows->context.id);
1577 context_values.background=pixel->background_color.pixel;
1578 context_values.font=font_info->fid;
1579 context_values.foreground=pixel->foreground_color.pixel;
1580 context_values.graphics_exposures=MagickFalse;
1581 context_mask=(MagickStatusType)
1582 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1583 if (pixel->annotate_context != (GC) NULL)
1584 (void) XFreeGC(display,pixel->annotate_context);
1585 pixel->annotate_context=
1586 XCreateGC(display,windows->context.id,context_mask,&context_values);
1587 if (pixel->annotate_context == (GC) NULL)
1588 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1590 context_values.background=pixel->depth_color.pixel;
1591 if (pixel->widget_context != (GC) NULL)
1592 (void) XFreeGC(display,pixel->widget_context);
1593 pixel->widget_context=
1594 XCreateGC(display,windows->context.id,context_mask,&context_values);
1595 if (pixel->widget_context == (GC) NULL)
1596 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1598 context_values.background=pixel->foreground_color.pixel;
1599 context_values.foreground=pixel->background_color.pixel;
1600 context_values.plane_mask=
1601 context_values.background ^ context_values.foreground;
1602 if (pixel->highlight_context != (GC) NULL)
1603 (void) XFreeGC(display,pixel->highlight_context);
1604 pixel->highlight_context=XCreateGC(display,windows->context.id,
1605 (size_t) (context_mask | GCPlaneMask),&context_values);
1606 if (pixel->highlight_context == (GC) NULL)
1607 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1609 (void) XDestroyWindow(display,windows->context.id);
1611 Initialize icon window.
1613 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1614 icon_resources,&windows->icon);
1615 windows->icon.geometry=resource_info->icon_geometry;
1616 XBestIconSize(display,&windows->icon,display_image);
1617 windows->icon.attributes.colormap=
1618 XDefaultColormap(display,icon_visual->screen);
1619 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1620 manager_hints->flags=InputHint | StateHint;
1621 manager_hints->input=MagickFalse;
1622 manager_hints->initial_state=IconicState;
1623 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1625 if (display_image->debug != MagickFalse)
1626 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1629 Initialize graphic context for icon window.
1631 if (icon_pixel->annotate_context != (GC) NULL)
1632 (void) XFreeGC(display,icon_pixel->annotate_context);
1633 context_values.background=icon_pixel->background_color.pixel;
1634 context_values.foreground=icon_pixel->foreground_color.pixel;
1635 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1636 (size_t) (GCBackground | GCForeground),&context_values);
1637 if (icon_pixel->annotate_context == (GC) NULL)
1638 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1640 windows->icon.annotate_context=icon_pixel->annotate_context;
1642 Initialize Image window.
1644 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1645 resource_info,&windows->image);
1646 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1647 if (resource_info->use_shared_memory == MagickFalse)
1648 windows->image.shared_memory=MagickFalse;
1649 if (resource_info->title != (char *) NULL)
1654 title=InterpretImageProperties(resource_info->image_info,display_image,
1655 resource_info->title,exception);
1656 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1657 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
1658 title=DestroyString(title);
1663 filename[MaxTextExtent];
1666 Window name is the base of the filename.
1668 GetPathComponent(display_image->magick_filename,TailPath,filename);
1669 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1670 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1671 display_image->scene,(double) number_scenes);
1672 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
1674 if (resource_info->immutable != MagickFalse)
1675 windows->image.immutable=MagickTrue;
1676 windows->image.shape=MagickTrue;
1677 windows->image.geometry=resource_info->image_geometry;
1678 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
1679 XDisplayWidth(display,visual_info->screen),
1680 XDisplayHeight(display,visual_info->screen));
1681 geometry_info.width=display_image->columns;
1682 geometry_info.height=display_image->rows;
1685 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1686 &geometry_info.width,&geometry_info.height);
1687 windows->image.width=(unsigned int) geometry_info.width;
1688 windows->image.height=(unsigned int) geometry_info.height;
1689 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1690 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1691 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1692 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1693 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1694 resource_info,&windows->backdrop);
1695 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1698 Initialize backdrop window.
1700 windows->backdrop.x=0;
1701 windows->backdrop.y=0;
1702 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1703 windows->backdrop.flags=(size_t) (USSize | USPosition);
1704 windows->backdrop.width=(unsigned int)
1705 XDisplayWidth(display,visual_info->screen);
1706 windows->backdrop.height=(unsigned int)
1707 XDisplayHeight(display,visual_info->screen);
1708 windows->backdrop.border_width=0;
1709 windows->backdrop.immutable=MagickTrue;
1710 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1712 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1713 StructureNotifyMask;
1714 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1715 manager_hints->icon_window=windows->icon.id;
1716 manager_hints->input=MagickTrue;
1717 manager_hints->initial_state=
1718 resource_info->iconic ? IconicState : NormalState;
1719 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1720 &windows->backdrop);
1721 if (display_image->debug != MagickFalse)
1722 (void) LogMagickEvent(X11Event,GetMagickModule(),
1723 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1724 (void) XMapWindow(display,windows->backdrop.id);
1725 (void) XClearWindow(display,windows->backdrop.id);
1726 if (windows->image.id != (Window) NULL)
1728 (void) XDestroyWindow(display,windows->image.id);
1729 windows->image.id=(Window) NULL;
1732 Position image in the center the backdrop.
1734 windows->image.flags|=USPosition;
1735 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1736 (windows->image.width/2);
1737 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1738 (windows->image.height/2);
1740 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1741 manager_hints->icon_window=windows->icon.id;
1742 manager_hints->input=MagickTrue;
1743 manager_hints->initial_state=
1744 resource_info->iconic ? IconicState : NormalState;
1745 if (windows->group_leader.id != (Window) NULL)
1750 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1751 manager_hints->window_group=windows->group_leader.id;
1752 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1753 if (display_image->debug != MagickFalse)
1754 (void) LogMagickEvent(X11Event,GetMagickModule(),
1755 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1757 XMakeWindow(display,
1758 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1759 argv,argc,class_hints,manager_hints,&windows->image);
1760 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1761 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1762 if (windows->group_leader.id != (Window) NULL)
1763 (void) XSetTransientForHint(display,windows->image.id,
1764 windows->group_leader.id);
1765 if (display_image->debug != MagickFalse)
1766 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1769 Initialize Info widget.
1771 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1772 resource_info,&windows->info);
1773 (void) CloneString(&windows->info.name,"Info");
1774 (void) CloneString(&windows->info.icon_name,"Info");
1775 windows->info.border_width=1;
1778 windows->info.flags|=PPosition;
1779 windows->info.attributes.win_gravity=UnmapGravity;
1780 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1781 StructureNotifyMask;
1782 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1783 manager_hints->input=MagickFalse;
1784 manager_hints->initial_state=NormalState;
1785 manager_hints->window_group=windows->image.id;
1786 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1788 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1789 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1790 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1791 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1792 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1793 if (windows->image.mapped)
1794 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1795 if (display_image->debug != MagickFalse)
1796 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1799 Initialize Command widget.
1801 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1802 resource_info,&windows->command);
1803 windows->command.data=MagickMenus;
1804 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1805 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
1806 resource_info->client_name);
1807 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1808 resource_name,"geometry",(char *) NULL);
1809 (void) CloneString(&windows->command.name,MagickTitle);
1810 windows->command.border_width=0;
1811 windows->command.flags|=PPosition;
1812 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1813 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1814 OwnerGrabButtonMask | StructureNotifyMask;
1815 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1816 manager_hints->input=MagickTrue;
1817 manager_hints->initial_state=NormalState;
1818 manager_hints->window_group=windows->image.id;
1819 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1821 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1822 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1824 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1825 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1826 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1827 if (display_image->debug != MagickFalse)
1828 (void) LogMagickEvent(X11Event,GetMagickModule(),
1829 "Window id: 0x%lx (command)",windows->command.id);
1831 Initialize Widget window.
1833 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1834 resource_info,&windows->widget);
1835 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
1836 resource_info->client_name);
1837 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1838 resource_name,"geometry",(char *) NULL);
1839 windows->widget.border_width=0;
1840 windows->widget.flags|=PPosition;
1841 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1842 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1843 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1844 StructureNotifyMask;
1845 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1846 manager_hints->input=MagickTrue;
1847 manager_hints->initial_state=NormalState;
1848 manager_hints->window_group=windows->image.id;
1849 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1851 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1852 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1853 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1854 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1855 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1856 if (display_image->debug != MagickFalse)
1857 (void) LogMagickEvent(X11Event,GetMagickModule(),
1858 "Window id: 0x%lx (widget)",windows->widget.id);
1860 Initialize popup window.
1862 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1863 resource_info,&windows->popup);
1864 windows->popup.border_width=0;
1865 windows->popup.flags|=PPosition;
1866 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1867 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1868 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1869 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1870 manager_hints->input=MagickTrue;
1871 manager_hints->initial_state=NormalState;
1872 manager_hints->window_group=windows->image.id;
1873 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1875 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1876 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1877 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1878 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1879 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1880 if (display_image->debug != MagickFalse)
1881 (void) LogMagickEvent(X11Event,GetMagickModule(),
1882 "Window id: 0x%lx (pop up)",windows->popup.id);
1884 Set out progress and warning handlers.
1886 if (warning_handler == (WarningHandler) NULL)
1888 warning_handler=resource_info->display_warnings ?
1889 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1890 warning_handler=resource_info->display_warnings ?
1891 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1894 Initialize X image structure.
1899 Initialize image pixmaps structure.
1901 window_changes.width=(int) windows->image.width;
1902 window_changes.height=(int) windows->image.height;
1903 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1904 (unsigned int) (CWWidth | CWHeight),&window_changes);
1905 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1906 sizeof(*windows->image.pixmaps));
1907 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1908 sizeof(*windows->image.pixmaps));
1909 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1910 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1911 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1913 if ((windows->image.mapped == MagickFalse) ||
1914 (windows->backdrop.id != (Window) NULL))
1915 (void) XMapWindow(display,windows->image.id);
1916 XSetCursorState(display,windows,MagickTrue);
1917 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1926 (void) TransformImageColorspace(image_list[scene],RGBColorspace);
1927 windows->image.pixmap=(Pixmap) NULL;
1928 windows->image.matte_pixmap=(Pixmap) NULL;
1929 if ((resource_info->map_type != (char *) NULL) ||
1930 (visual_info->klass == TrueColor) ||
1931 (visual_info->klass == DirectColor))
1932 if (image_list[scene]->storage_class == PseudoClass)
1933 XGetPixelInfo(display,visual_info,map_info,resource_info,
1934 image_list[scene],windows->image.pixel_info);
1935 columns=(unsigned int) image_list[scene]->columns;
1936 rows=(unsigned int) image_list[scene]->rows;
1937 if ((image_list[scene]->columns != columns) ||
1938 (image_list[scene]->rows != rows))
1939 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1940 image_list[scene]->filename);
1941 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1942 columns,rows,exception);
1943 if (status == MagickFalse)
1944 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1946 if (image_list[scene]->debug != MagickFalse)
1948 (void) LogMagickEvent(X11Event,GetMagickModule(),
1949 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1950 image_list[scene]->filename,(double) columns,(double) rows);
1951 if (image_list[scene]->colors != 0)
1952 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1953 image_list[scene]->colors);
1954 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1955 image_list[scene]->magick);
1958 Window name is the base of the filename.
1960 if (resource_info->title != (char *) NULL)
1965 title=InterpretImageProperties(resource_info->image_info,
1966 image_list[scene],resource_info->title,exception);
1967 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1968 title=DestroyString(title);
1972 p=image_list[scene]->magick_filename+
1973 strlen(image_list[scene]->magick_filename)-1;
1974 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1976 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1977 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1978 (double) number_scenes);
1980 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1981 if (status != Success)
1983 XSetWMName(display,windows->image.id,&window_name);
1984 (void) XFree((void *) window_name.value);
1986 windows->image.pixmaps[scene]=windows->image.pixmap;
1987 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1992 event.xexpose.width=(int) image_list[scene]->columns;
1993 event.xexpose.height=(int) image_list[scene]->rows;
1994 XRefreshWindow(display,&windows->image,&event);
1995 (void) XSync(display,MagickFalse);
1998 XSetCursorState(display,windows,MagickFalse);
1999 if (windows->command.mapped)
2000 (void) XMapRaised(display,windows->command.id);
2004 nexus=NewImageList();
2008 image=image_list[0];
2009 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2010 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2014 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2015 if ((state & PlayAnimationState) || (state & StepAnimationState))
2021 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2022 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2023 if (state & ForwardAnimationState)
2026 Forward animation: increment scene number.
2028 if (scene < ((ssize_t) number_scenes-1))
2033 if (iterations == (ssize_t) image_list[0]->iterations)
2038 if ((state & AutoReverseAnimationState) != 0)
2040 state&=(~ForwardAnimationState);
2045 if ((state & RepeatAnimationState) == 0)
2046 state&=(~PlayAnimationState);
2055 Reverse animation: decrement scene number.
2057 if (scene > first_scene)
2062 if (iterations == (ssize_t) image_list[0]->iterations)
2065 state&=(~RepeatAnimationState);
2067 if (state & AutoReverseAnimationState)
2069 state|=ForwardAnimationState;
2075 if ((state & RepeatAnimationState) == MagickFalse)
2076 state&=(~PlayAnimationState);
2077 scene=(ssize_t) number_scenes-1;
2081 scene=MagickMax(scene,0);
2082 image=image_list[scene];
2083 if ((image != (Image *) NULL) && (image->start_loop != 0))
2085 if ((state & StepAnimationState) ||
2086 (resource_info->title != (char *) NULL))
2089 Update window title.
2091 p=image_list[scene]->filename+
2092 strlen(image_list[scene]->filename)-1;
2093 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2095 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
2096 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2097 scene+1,(double) number_scenes);
2098 if (resource_info->title != (char *) NULL)
2103 title=InterpretImageProperties(resource_info->image_info,
2104 image,resource_info->title,exception);
2105 (void) CopyMagickString(windows->image.name,title,
2107 title=DestroyString(title);
2109 status=XStringListToTextProperty(&windows->image.name,1,
2111 if (status != Success)
2113 XSetWMName(display,windows->image.id,&window_name);
2114 (void) XFree((void *) window_name.value);
2118 Copy X pixmap to Image window.
2120 XGetPixelInfo(display,visual_info,map_info,resource_info,
2121 image_list[scene],windows->image.pixel_info);
2122 windows->image.ximage->width=(int) image->columns;
2123 windows->image.ximage->height=(int) image->rows;
2124 windows->image.pixmap=windows->image.pixmaps[scene];
2125 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2128 event.xexpose.width=(int) image->columns;
2129 event.xexpose.height=(int) image->rows;
2130 if ((state & ExitState) == 0)
2132 XRefreshWindow(display,&windows->image,&event);
2133 (void) XSync(display,MagickFalse);
2135 state&=(~StepAnimationState);
2136 if (pause != MagickFalse)
2137 for (i=0; i < (ssize_t) resource_info->pause; i++)
2142 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2149 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2150 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2151 *(command+length)='\0';
2152 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2154 XClientMessage(display,windows->image.id,
2155 windows->im_protocols,windows->im_exit,CurrentTime);
2164 Handle a window event.
2166 timestamp=time((time_t *) NULL);
2167 (void) XNextEvent(display,&event);
2168 if (windows->image.stasis == MagickFalse)
2169 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2170 MagickTrue : MagickFalse;
2171 if (event.xany.window == windows->command.id)
2177 Select a command from the Command widget.
2179 id=XCommandWidget(display,windows,CommandMenu,&event);
2182 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
2183 command_type=CommandMenus[id];
2184 if (id < MagickMenus)
2190 Select a command from a pop-up menu.
2192 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2196 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
2197 command_type=Commands[id][entry];
2199 if (command_type != NullCommand)
2200 nexus=XMagickCommand(display,resource_info,windows,
2201 command_type,&image,&state,exception);
2208 if (display_image->debug != MagickFalse)
2209 (void) LogMagickEvent(X11Event,GetMagickModule(),
2210 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2211 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2212 if ((event.xbutton.button == Button3) &&
2213 (event.xbutton.state & Mod1Mask))
2216 Convert Alt-Button3 to Button2.
2218 event.xbutton.button=Button2;
2219 event.xbutton.state&=(~Mod1Mask);
2221 if (event.xbutton.window == windows->backdrop.id)
2223 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2224 event.xbutton.time);
2227 if (event.xbutton.window == windows->image.id)
2229 if (resource_info->immutable != MagickFalse)
2235 Map/unmap Command widget.
2237 if (windows->command.mapped)
2238 (void) XWithdrawWindow(display,windows->command.id,
2239 windows->command.screen);
2242 (void) XCommandWidget(display,windows,CommandMenu,
2244 (void) XMapRaised(display,windows->command.id);
2251 if (display_image->debug != MagickFalse)
2252 (void) LogMagickEvent(X11Event,GetMagickModule(),
2253 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2254 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2259 if (display_image->debug != MagickFalse)
2260 (void) LogMagickEvent(X11Event,GetMagickModule(),
2261 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2262 event.xclient.window,(unsigned long) event.xclient.message_type,
2263 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2264 if (event.xclient.message_type == windows->im_protocols)
2266 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2269 Update graphic context and window colormap.
2271 for (i=0; i < (ssize_t) number_windows; i++)
2273 if (magick_windows[i]->id == windows->icon.id)
2275 context_values.background=pixel->background_color.pixel;
2276 context_values.foreground=pixel->foreground_color.pixel;
2277 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2278 context_mask,&context_values);
2279 (void) XChangeGC(display,magick_windows[i]->widget_context,
2280 context_mask,&context_values);
2281 context_values.background=pixel->foreground_color.pixel;
2282 context_values.foreground=pixel->background_color.pixel;
2283 context_values.plane_mask=
2284 context_values.background ^ context_values.foreground;
2285 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2286 (size_t) (context_mask | GCPlaneMask),
2288 magick_windows[i]->attributes.background_pixel=
2289 pixel->background_color.pixel;
2290 magick_windows[i]->attributes.border_pixel=
2291 pixel->border_color.pixel;
2292 magick_windows[i]->attributes.colormap=map_info->colormap;
2293 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2294 (unsigned long) magick_windows[i]->mask,
2295 &magick_windows[i]->attributes);
2297 if (windows->backdrop.id != (Window) NULL)
2298 (void) XInstallColormap(display,map_info->colormap);
2301 if (*event.xclient.data.l == (long) windows->im_exit)
2308 if (event.xclient.message_type == windows->dnd_protocols)
2326 Display image named by the Drag-and-Drop selection.
2328 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2330 selection=XInternAtom(display,"DndSelection",MagickFalse);
2331 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2332 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2334 if ((status != Success) || (length == 0))
2336 if (*event.xclient.data.l == 2)
2341 (void) CopyMagickString(resource_info->image_info->filename,
2342 (char *) data,MaxTextExtent);
2349 if (LocaleNCompare((char *) data,"file:",5) != 0)
2351 (void) XFree((void *) data);
2354 (void) CopyMagickString(resource_info->image_info->filename,
2355 ((char *) data)+5,MaxTextExtent);
2357 nexus=ReadImage(resource_info->image_info,exception);
2358 CatchException(exception);
2359 if (nexus != (Image *) NULL)
2361 (void) XFree((void *) data);
2365 If client window delete message, exit.
2367 if (event.xclient.message_type != windows->wm_protocols)
2369 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2371 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2372 (Time) event.xclient.data.l[1]);
2375 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2377 (void) XWithdrawWindow(display,event.xclient.window,
2378 visual_info->screen);
2379 if (event.xclient.window == windows->image.id)
2386 case ConfigureNotify:
2388 if (display_image->debug != MagickFalse)
2389 (void) LogMagickEvent(X11Event,GetMagickModule(),
2390 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2391 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2392 event.xconfigure.y,event.xconfigure.send_event);
2393 if (event.xconfigure.window == windows->image.id)
2395 if (event.xconfigure.send_event != 0)
2401 Position the transient windows relative of the Image window.
2403 if (windows->command.geometry == (char *) NULL)
2404 if (windows->command.mapped == MagickFalse)
2407 event.xconfigure.x-windows->command.width-25;
2408 windows->command.y=event.xconfigure.y;
2409 XConstrainWindowPosition(display,&windows->command);
2410 window_changes.x=windows->command.x;
2411 window_changes.y=windows->command.y;
2412 (void) XReconfigureWMWindow(display,windows->command.id,
2413 windows->command.screen,(unsigned int) (CWX | CWY),
2416 if (windows->widget.geometry == (char *) NULL)
2417 if (windows->widget.mapped == MagickFalse)
2420 event.xconfigure.x+event.xconfigure.width/10;
2422 event.xconfigure.y+event.xconfigure.height/10;
2423 XConstrainWindowPosition(display,&windows->widget);
2424 window_changes.x=windows->widget.x;
2425 window_changes.y=windows->widget.y;
2426 (void) XReconfigureWMWindow(display,windows->widget.id,
2427 windows->widget.screen,(unsigned int) (CWX | CWY),
2432 Image window has a new configuration.
2434 windows->image.width=(unsigned int) event.xconfigure.width;
2435 windows->image.height=(unsigned int) event.xconfigure.height;
2438 if (event.xconfigure.window == windows->icon.id)
2441 Icon window has a new configuration.
2443 windows->icon.width=(unsigned int) event.xconfigure.width;
2444 windows->icon.height=(unsigned int) event.xconfigure.height;
2452 Group leader has exited.
2454 if (display_image->debug != MagickFalse)
2455 (void) LogMagickEvent(X11Event,GetMagickModule(),
2456 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2457 if (event.xdestroywindow.window == windows->group_leader.id)
2467 Selectively install colormap.
2469 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2470 if (event.xcrossing.mode != NotifyUngrab)
2471 XInstallColormap(display,map_info->colormap);
2476 if (display_image->debug != MagickFalse)
2477 (void) LogMagickEvent(X11Event,GetMagickModule(),
2478 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2479 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2482 Repaint windows that are now exposed.
2484 if (event.xexpose.window == windows->image.id)
2486 windows->image.pixmap=windows->image.pixmaps[scene];
2487 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2488 XRefreshWindow(display,&windows->image,&event);
2491 if (event.xexpose.window == windows->icon.id)
2492 if (event.xexpose.count == 0)
2494 XRefreshWindow(display,&windows->icon,&event);
2505 Respond to a user key press.
2507 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2508 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2509 *(command+length)='\0';
2510 if (display_image->debug != MagickFalse)
2511 (void) LogMagickEvent(X11Event,GetMagickModule(),
2512 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2513 command_type=NullCommand;
2518 if ((event.xkey.state & ControlMask) == MagickFalse)
2520 command_type=OpenCommand;
2525 command_type=StepBackwardCommand;
2530 command_type=StepForwardCommand;
2535 command_type=FasterCommand;
2540 command_type=SlowerCommand;
2545 command_type=HelpCommand;
2550 command_type=BrowseDocumentationCommand;
2555 command_type=InfoCommand;
2561 command_type=QuitCommand;
2567 if (command_type != NullCommand)
2568 nexus=XMagickCommand(display,resource_info,windows,
2569 command_type,&image,&state,exception);
2575 Respond to a user key release.
2577 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2578 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2579 if (display_image->debug != MagickFalse)
2580 (void) LogMagickEvent(X11Event,GetMagickModule(),
2581 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2587 Selectively uninstall colormap.
2589 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2590 if (event.xcrossing.mode != NotifyUngrab)
2591 XUninstallColormap(display,map_info->colormap);
2596 if (display_image->debug != MagickFalse)
2597 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2599 if (event.xmap.window == windows->backdrop.id)
2601 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2603 windows->backdrop.mapped=MagickTrue;
2606 if (event.xmap.window == windows->image.id)
2608 if (windows->backdrop.id != (Window) NULL)
2609 (void) XInstallColormap(display,map_info->colormap);
2610 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2612 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2613 nexus=XMagickCommand(display,resource_info,windows,
2614 OpenCommand,&image,&state,exception);
2618 windows->image.mapped=MagickTrue;
2621 if (event.xmap.window == windows->info.id)
2623 windows->info.mapped=MagickTrue;
2626 if (event.xmap.window == windows->icon.id)
2629 Create an icon image.
2631 XMakeStandardColormap(display,icon_visual,icon_resources,
2632 display_image,icon_map,icon_pixel);
2633 (void) XMakeImage(display,icon_resources,&windows->icon,
2634 display_image,windows->icon.width,windows->icon.height,
2636 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2637 windows->icon.pixmap);
2638 (void) XClearWindow(display,windows->icon.id);
2639 (void) XWithdrawWindow(display,windows->info.id,
2640 windows->info.screen);
2641 windows->icon.mapped=MagickTrue;
2644 if (event.xmap.window == windows->command.id)
2646 windows->command.mapped=MagickTrue;
2649 if (event.xmap.window == windows->popup.id)
2651 windows->popup.mapped=MagickTrue;
2654 if (event.xmap.window == windows->widget.id)
2656 windows->widget.mapped=MagickTrue;
2663 (void) XRefreshKeyboardMapping(&event.xmapping);
2668 case PropertyNotify:
2684 if (display_image->debug != MagickFalse)
2685 (void) LogMagickEvent(X11Event,GetMagickModule(),
2686 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2687 event.xproperty.window,(unsigned long) event.xproperty.atom,
2688 event.xproperty.state);
2689 if (event.xproperty.atom != windows->im_remote_command)
2692 Display image named by the remote command protocol.
2694 status=XGetWindowProperty(display,event.xproperty.window,
2695 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
2696 AnyPropertyType,&type,&format,&length,&after,&data);
2697 if ((status != Success) || (length == 0))
2699 (void) CopyMagickString(resource_info->image_info->filename,
2700 (char *) data,MaxTextExtent);
2701 nexus=ReadImage(resource_info->image_info,exception);
2702 CatchException(exception);
2703 if (nexus != (Image *) NULL)
2705 (void) XFree((void *) data);
2708 case ReparentNotify:
2710 if (display_image->debug != MagickFalse)
2711 (void) LogMagickEvent(X11Event,GetMagickModule(),
2712 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2713 event.xreparent.window);
2718 if (display_image->debug != MagickFalse)
2719 (void) LogMagickEvent(X11Event,GetMagickModule(),
2720 "Unmap Notify: 0x%lx",event.xunmap.window);
2721 if (event.xunmap.window == windows->backdrop.id)
2723 windows->backdrop.mapped=MagickFalse;
2726 if (event.xunmap.window == windows->image.id)
2728 windows->image.mapped=MagickFalse;
2731 if (event.xunmap.window == windows->info.id)
2733 windows->info.mapped=MagickFalse;
2736 if (event.xunmap.window == windows->icon.id)
2738 if (map_info->colormap == icon_map->colormap)
2739 XConfigureImageColormap(display,resource_info,windows,
2741 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2743 windows->icon.mapped=MagickFalse;
2746 if (event.xunmap.window == windows->command.id)
2748 windows->command.mapped=MagickFalse;
2751 if (event.xunmap.window == windows->popup.id)
2753 if (windows->backdrop.id != (Window) NULL)
2754 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2756 windows->popup.mapped=MagickFalse;
2759 if (event.xunmap.window == windows->widget.id)
2761 if (windows->backdrop.id != (Window) NULL)
2762 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2764 windows->widget.mapped=MagickFalse;
2771 if (display_image->debug != MagickFalse)
2772 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2778 while (!(state & ExitState));
2779 image_list=(Image **) RelinquishMagickMemory(image_list);
2780 images=DestroyImageList(images);
2781 if ((windows->visual_info->klass == GrayScale) ||
2782 (windows->visual_info->klass == PseudoColor) ||
2783 (windows->visual_info->klass == DirectColor))
2788 if (windows->info.mapped)
2789 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2790 if (windows->command.mapped)
2791 (void) XWithdrawWindow(display,windows->command.id,
2792 windows->command.screen);
2794 if (resource_info->backdrop == MagickFalse)
2795 if (windows->backdrop.mapped)
2797 (void) XWithdrawWindow(display,windows->backdrop.id,\
2798 windows->backdrop.screen);
2799 (void) XDestroyWindow(display,windows->backdrop.id);
2800 windows->backdrop.id=(Window) NULL;
2801 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2802 (void) XDestroyWindow(display,windows->image.id);
2803 windows->image.id=(Window) NULL;
2805 XSetCursorState(display,windows,MagickTrue);
2806 XCheckRefreshWindows(display,windows);
2807 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2809 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2810 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2811 windows->image.pixmaps[scene]=(Pixmap) NULL;
2812 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2813 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2814 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2816 XSetCursorState(display,windows,MagickFalse);
2817 windows->image.pixmaps=(Pixmap *)
2818 RelinquishMagickMemory(windows->image.pixmaps);
2819 windows->image.matte_pixmaps=(Pixmap *)
2820 RelinquishMagickMemory(windows->image.matte_pixmaps);
2821 if (nexus == (Image *) NULL)
2826 if (windows->image.mapped != MagickFalse)
2827 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime);
2828 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2829 if (resource_info->map_type == (char *) NULL)
2830 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2831 DestroyXResources();
2833 (void) XSync(display,MagickFalse);
2835 Restore our progress monitor and warning handlers.
2837 (void) SetErrorHandler(warning_handler);
2838 (void) SetWarningHandler(warning_handler);
2840 Change to home directory.
2842 directory=getcwd(working_directory,MaxTextExtent);
2844 status=chdir(resource_info->home_directory);
2846 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2847 "UnableToOpenFile","%s",resource_info->home_directory);
2852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2856 + X S a v e I m a g e %
2860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2862 % XSaveImage() saves an image to a file.
2864 % The format of the XSaveImage method is:
2866 % MagickBooleanType XSaveImage(Display *display,
2867 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2868 % ExceptionInfo *exception)
2870 % A description of each parameter follows:
2872 % o status: Method XSaveImage return True if the image is
2873 % written. False is returned is there is a memory shortage or if the
2874 % image fails to write.
2876 % o display: Specifies a connection to an X server; returned from
2879 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2881 % o windows: Specifies a pointer to a XWindows structure.
2883 % o image: the image.
2886 static MagickBooleanType XSaveImage(Display *display,
2887 XResourceInfo *resource_info,XWindows *windows,Image *image,
2888 ExceptionInfo *exception)
2891 filename[MaxTextExtent];
2900 Request file name from user.
2902 if (resource_info->write_filename != (char *) NULL)
2903 (void) CopyMagickString(filename,resource_info->write_filename,
2908 path[MaxTextExtent];
2913 GetPathComponent(image->filename,HeadPath,path);
2914 GetPathComponent(image->filename,TailPath,filename);
2917 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2918 "UnableToOpenFile","%s",path);
2920 XFileBrowserWidget(display,windows,"Save",filename);
2921 if (*filename == '\0')
2923 if (IsPathAccessible(filename) != MagickFalse)
2929 File exists-- seek user's permission before overwriting.
2931 status=XConfirmWidget(display,windows,"Overwrite",filename);
2935 image_info=CloneImageInfo(resource_info->image_info);
2936 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2937 (void) SetImageInfo(image_info,1,exception);
2938 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2939 (LocaleCompare(image_info->magick,"JPG") == 0))
2942 quality[MaxTextExtent];
2948 Request JPEG quality from user.
2950 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
2951 image_info->quality);
2952 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2954 if (*quality == '\0')
2956 image->quality=StringToUnsignedLong(quality);
2957 image_info->interlace=status != MagickFalse ? NoInterlace :
2960 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2961 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2962 (LocaleCompare(image_info->magick,"PS") == 0) ||
2963 (LocaleCompare(image_info->magick,"PS2") == 0))
2966 geometry[MaxTextExtent];
2969 Request page geometry from user.
2971 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2972 if (LocaleCompare(image_info->magick,"PDF") == 0)
2973 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2974 if (image_info->page != (char *) NULL)
2975 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
2976 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2977 "Select page geometry:",geometry);
2978 if (*geometry != '\0')
2979 image_info->page=GetPageGeometry(geometry);
2984 image=GetFirstImageInList(image);
2985 status=WriteImages(image_info,image,filename,exception);
2986 if (status != MagickFalse)
2987 image->taint=MagickFalse;
2988 image_info=DestroyImageInfo(image_info);
2989 XSetCursorState(display,windows,MagickFalse);
2990 return(status != 0 ? MagickTrue : MagickFalse);
2995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2999 + A n i m a t e I m a g e s %
3003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3005 % AnimateImages() repeatedly displays an image sequence to any X window
3006 % screen. It returns a value other than 0 if successful. Check the
3007 % exception member of image to determine the reason for any failure.
3009 % The format of the AnimateImages method is:
3011 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3014 % A description of each parameter follows:
3016 % o image_info: the image info.
3018 % o image: the image.
3020 % o exception: return any errors or warnings in this structure.
3023 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3024 Image *image,ExceptionInfo *exception)
3026 assert(image_info != (const ImageInfo *) NULL);
3027 assert(image_info->signature == MagickSignature);
3028 assert(image != (Image *) NULL);
3029 assert(image->signature == MagickSignature);
3030 if (image->debug != MagickFalse)
3031 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3032 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
3033 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
3034 return(MagickFalse);