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)
547 message[MaxTextExtent];
549 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
550 exception->reason != (char *) NULL ? exception->reason : "",
551 exception->description != (char *) NULL ? exception->description :
553 XNoticeWidget(display,windows,"Unable to save file:",message);
560 resource_info->delay++;
565 if (resource_info->delay == 0)
567 resource_info->delay--;
572 *state=ForwardAnimationState;
573 *state&=(~AutoReverseAnimationState);
578 *state&=(~ForwardAnimationState);
579 *state&=(~AutoReverseAnimationState);
584 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 (IsPixelPacketEquivalent(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 (IsPixelPacketEquivalent(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,
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 (void) TransformImageColorspace(image_list[scene],RGBColorspace);
1933 windows->image.pixmap=(Pixmap) NULL;
1934 windows->image.matte_pixmap=(Pixmap) NULL;
1935 if ((resource_info->map_type != (char *) NULL) ||
1936 (visual_info->klass == TrueColor) ||
1937 (visual_info->klass == DirectColor))
1938 if (image_list[scene]->storage_class == PseudoClass)
1939 XGetPixelInfo(display,visual_info,map_info,resource_info,
1940 image_list[scene],windows->image.pixel_info);
1941 columns=(unsigned int) image_list[scene]->columns;
1942 rows=(unsigned int) image_list[scene]->rows;
1943 if ((image_list[scene]->columns != columns) ||
1944 (image_list[scene]->rows != rows))
1945 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1946 image_list[scene]->filename);
1947 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1948 columns,rows,exception);
1949 if (status == MagickFalse)
1950 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1952 if (image_list[scene]->debug != MagickFalse)
1954 (void) LogMagickEvent(X11Event,GetMagickModule(),
1955 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1956 image_list[scene]->filename,(double) columns,(double) rows);
1957 if (image_list[scene]->colors != 0)
1958 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1959 image_list[scene]->colors);
1960 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1961 image_list[scene]->magick);
1964 Window name is the base of the filename.
1966 if (resource_info->title != (char *) NULL)
1971 title=InterpretImageProperties(resource_info->image_info,
1972 image_list[scene],resource_info->title,exception);
1973 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1974 title=DestroyString(title);
1978 p=image_list[scene]->magick_filename+
1979 strlen(image_list[scene]->magick_filename)-1;
1980 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1982 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1983 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1984 (double) number_scenes);
1986 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1987 if (status != Success)
1989 XSetWMName(display,windows->image.id,&window_name);
1990 (void) XFree((void *) window_name.value);
1992 windows->image.pixmaps[scene]=windows->image.pixmap;
1993 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1998 event.xexpose.width=(int) image_list[scene]->columns;
1999 event.xexpose.height=(int) image_list[scene]->rows;
2000 XRefreshWindow(display,&windows->image,&event);
2001 (void) XSync(display,MagickFalse);
2004 XSetCursorState(display,windows,MagickFalse);
2005 if (windows->command.mapped)
2006 (void) XMapRaised(display,windows->command.id);
2010 nexus=NewImageList();
2014 image=image_list[0];
2015 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2016 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2020 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2021 if ((state & PlayAnimationState) || (state & StepAnimationState))
2027 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2028 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2029 if (state & ForwardAnimationState)
2032 Forward animation: increment scene number.
2034 if (scene < ((ssize_t) number_scenes-1))
2039 if (iterations == (ssize_t) image_list[0]->iterations)
2044 if ((state & AutoReverseAnimationState) != 0)
2046 state&=(~ForwardAnimationState);
2051 if ((state & RepeatAnimationState) == 0)
2052 state&=(~PlayAnimationState);
2061 Reverse animation: decrement scene number.
2063 if (scene > first_scene)
2068 if (iterations == (ssize_t) image_list[0]->iterations)
2071 state&=(~RepeatAnimationState);
2073 if (state & AutoReverseAnimationState)
2075 state|=ForwardAnimationState;
2081 if ((state & RepeatAnimationState) == MagickFalse)
2082 state&=(~PlayAnimationState);
2083 scene=(ssize_t) number_scenes-1;
2087 scene=MagickMax(scene,0);
2088 image=image_list[scene];
2089 if ((image != (Image *) NULL) && (image->start_loop != 0))
2091 if ((state & StepAnimationState) ||
2092 (resource_info->title != (char *) NULL))
2095 Update window title.
2097 p=image_list[scene]->filename+
2098 strlen(image_list[scene]->filename)-1;
2099 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2101 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
2102 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2103 scene+1,(double) number_scenes);
2104 if (resource_info->title != (char *) NULL)
2109 title=InterpretImageProperties(resource_info->image_info,
2110 image,resource_info->title,exception);
2111 (void) CopyMagickString(windows->image.name,title,
2113 title=DestroyString(title);
2115 status=XStringListToTextProperty(&windows->image.name,1,
2117 if (status != Success)
2119 XSetWMName(display,windows->image.id,&window_name);
2120 (void) XFree((void *) window_name.value);
2124 Copy X pixmap to Image window.
2126 XGetPixelInfo(display,visual_info,map_info,resource_info,
2127 image_list[scene],windows->image.pixel_info);
2128 windows->image.ximage->width=(int) image->columns;
2129 windows->image.ximage->height=(int) image->rows;
2130 windows->image.pixmap=windows->image.pixmaps[scene];
2131 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2134 event.xexpose.width=(int) image->columns;
2135 event.xexpose.height=(int) image->rows;
2136 if ((state & ExitState) == 0)
2138 XRefreshWindow(display,&windows->image,&event);
2139 (void) XSync(display,MagickFalse);
2141 state&=(~StepAnimationState);
2142 if (pause != MagickFalse)
2143 for (i=0; i < (ssize_t) resource_info->pause; i++)
2148 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2155 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2156 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2157 *(command+length)='\0';
2158 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2160 XClientMessage(display,windows->image.id,
2161 windows->im_protocols,windows->im_exit,CurrentTime);
2170 Handle a window event.
2172 timestamp=time((time_t *) NULL);
2173 (void) XNextEvent(display,&event);
2174 if (windows->image.stasis == MagickFalse)
2175 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2176 MagickTrue : MagickFalse;
2177 if (event.xany.window == windows->command.id)
2183 Select a command from the Command widget.
2185 id=XCommandWidget(display,windows,CommandMenu,&event);
2188 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
2189 command_type=CommandMenus[id];
2190 if (id < MagickMenus)
2196 Select a command from a pop-up menu.
2198 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2202 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
2203 command_type=Commands[id][entry];
2205 if (command_type != NullCommand)
2206 nexus=XMagickCommand(display,resource_info,windows,
2207 command_type,&image,&state,exception);
2214 if (display_image->debug != MagickFalse)
2215 (void) LogMagickEvent(X11Event,GetMagickModule(),
2216 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2217 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2218 if ((event.xbutton.button == Button3) &&
2219 (event.xbutton.state & Mod1Mask))
2222 Convert Alt-Button3 to Button2.
2224 event.xbutton.button=Button2;
2225 event.xbutton.state&=(~Mod1Mask);
2227 if (event.xbutton.window == windows->backdrop.id)
2229 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2230 event.xbutton.time);
2233 if (event.xbutton.window == windows->image.id)
2235 if (resource_info->immutable != MagickFalse)
2241 Map/unmap Command widget.
2243 if (windows->command.mapped)
2244 (void) XWithdrawWindow(display,windows->command.id,
2245 windows->command.screen);
2248 (void) XCommandWidget(display,windows,CommandMenu,
2250 (void) XMapRaised(display,windows->command.id);
2257 if (display_image->debug != MagickFalse)
2258 (void) LogMagickEvent(X11Event,GetMagickModule(),
2259 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2260 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2265 if (display_image->debug != MagickFalse)
2266 (void) LogMagickEvent(X11Event,GetMagickModule(),
2267 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2268 event.xclient.window,(unsigned long) event.xclient.message_type,
2269 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2270 if (event.xclient.message_type == windows->im_protocols)
2272 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2275 Update graphic context and window colormap.
2277 for (i=0; i < (ssize_t) number_windows; i++)
2279 if (magick_windows[i]->id == windows->icon.id)
2281 context_values.background=pixel->background_color.pixel;
2282 context_values.foreground=pixel->foreground_color.pixel;
2283 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2284 context_mask,&context_values);
2285 (void) XChangeGC(display,magick_windows[i]->widget_context,
2286 context_mask,&context_values);
2287 context_values.background=pixel->foreground_color.pixel;
2288 context_values.foreground=pixel->background_color.pixel;
2289 context_values.plane_mask=
2290 context_values.background ^ context_values.foreground;
2291 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2292 (size_t) (context_mask | GCPlaneMask),
2294 magick_windows[i]->attributes.background_pixel=
2295 pixel->background_color.pixel;
2296 magick_windows[i]->attributes.border_pixel=
2297 pixel->border_color.pixel;
2298 magick_windows[i]->attributes.colormap=map_info->colormap;
2299 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2300 (unsigned long) magick_windows[i]->mask,
2301 &magick_windows[i]->attributes);
2303 if (windows->backdrop.id != (Window) NULL)
2304 (void) XInstallColormap(display,map_info->colormap);
2307 if (*event.xclient.data.l == (long) windows->im_exit)
2314 if (event.xclient.message_type == windows->dnd_protocols)
2332 Display image named by the Drag-and-Drop selection.
2334 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2336 selection=XInternAtom(display,"DndSelection",MagickFalse);
2337 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2338 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2340 if ((status != Success) || (length == 0))
2342 if (*event.xclient.data.l == 2)
2347 (void) CopyMagickString(resource_info->image_info->filename,
2348 (char *) data,MaxTextExtent);
2355 if (LocaleNCompare((char *) data,"file:",5) != 0)
2357 (void) XFree((void *) data);
2360 (void) CopyMagickString(resource_info->image_info->filename,
2361 ((char *) data)+5,MaxTextExtent);
2363 nexus=ReadImage(resource_info->image_info,exception);
2364 CatchException(exception);
2365 if (nexus != (Image *) NULL)
2367 (void) XFree((void *) data);
2371 If client window delete message, exit.
2373 if (event.xclient.message_type != windows->wm_protocols)
2375 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2377 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2378 (Time) event.xclient.data.l[1]);
2381 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2383 (void) XWithdrawWindow(display,event.xclient.window,
2384 visual_info->screen);
2385 if (event.xclient.window == windows->image.id)
2392 case ConfigureNotify:
2394 if (display_image->debug != MagickFalse)
2395 (void) LogMagickEvent(X11Event,GetMagickModule(),
2396 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2397 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2398 event.xconfigure.y,event.xconfigure.send_event);
2399 if (event.xconfigure.window == windows->image.id)
2401 if (event.xconfigure.send_event != 0)
2407 Position the transient windows relative of the Image window.
2409 if (windows->command.geometry == (char *) NULL)
2410 if (windows->command.mapped == MagickFalse)
2413 event.xconfigure.x-windows->command.width-25;
2414 windows->command.y=event.xconfigure.y;
2415 XConstrainWindowPosition(display,&windows->command);
2416 window_changes.x=windows->command.x;
2417 window_changes.y=windows->command.y;
2418 (void) XReconfigureWMWindow(display,windows->command.id,
2419 windows->command.screen,(unsigned int) (CWX | CWY),
2422 if (windows->widget.geometry == (char *) NULL)
2423 if (windows->widget.mapped == MagickFalse)
2426 event.xconfigure.x+event.xconfigure.width/10;
2428 event.xconfigure.y+event.xconfigure.height/10;
2429 XConstrainWindowPosition(display,&windows->widget);
2430 window_changes.x=windows->widget.x;
2431 window_changes.y=windows->widget.y;
2432 (void) XReconfigureWMWindow(display,windows->widget.id,
2433 windows->widget.screen,(unsigned int) (CWX | CWY),
2438 Image window has a new configuration.
2440 windows->image.width=(unsigned int) event.xconfigure.width;
2441 windows->image.height=(unsigned int) event.xconfigure.height;
2444 if (event.xconfigure.window == windows->icon.id)
2447 Icon window has a new configuration.
2449 windows->icon.width=(unsigned int) event.xconfigure.width;
2450 windows->icon.height=(unsigned int) event.xconfigure.height;
2458 Group leader has exited.
2460 if (display_image->debug != MagickFalse)
2461 (void) LogMagickEvent(X11Event,GetMagickModule(),
2462 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2463 if (event.xdestroywindow.window == windows->group_leader.id)
2473 Selectively install colormap.
2475 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2476 if (event.xcrossing.mode != NotifyUngrab)
2477 XInstallColormap(display,map_info->colormap);
2482 if (display_image->debug != MagickFalse)
2483 (void) LogMagickEvent(X11Event,GetMagickModule(),
2484 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2485 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2488 Repaint windows that are now exposed.
2490 if (event.xexpose.window == windows->image.id)
2492 windows->image.pixmap=windows->image.pixmaps[scene];
2493 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2494 XRefreshWindow(display,&windows->image,&event);
2497 if (event.xexpose.window == windows->icon.id)
2498 if (event.xexpose.count == 0)
2500 XRefreshWindow(display,&windows->icon,&event);
2511 Respond to a user key press.
2513 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2514 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2515 *(command+length)='\0';
2516 if (display_image->debug != MagickFalse)
2517 (void) LogMagickEvent(X11Event,GetMagickModule(),
2518 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2519 command_type=NullCommand;
2524 if ((event.xkey.state & ControlMask) == MagickFalse)
2526 command_type=OpenCommand;
2531 command_type=StepBackwardCommand;
2536 command_type=StepForwardCommand;
2541 command_type=FasterCommand;
2546 command_type=SlowerCommand;
2551 command_type=HelpCommand;
2556 command_type=BrowseDocumentationCommand;
2561 command_type=InfoCommand;
2567 command_type=QuitCommand;
2573 if (command_type != NullCommand)
2574 nexus=XMagickCommand(display,resource_info,windows,
2575 command_type,&image,&state,exception);
2581 Respond to a user key release.
2583 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2584 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2585 if (display_image->debug != MagickFalse)
2586 (void) LogMagickEvent(X11Event,GetMagickModule(),
2587 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2593 Selectively uninstall colormap.
2595 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2596 if (event.xcrossing.mode != NotifyUngrab)
2597 XUninstallColormap(display,map_info->colormap);
2602 if (display_image->debug != MagickFalse)
2603 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2605 if (event.xmap.window == windows->backdrop.id)
2607 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2609 windows->backdrop.mapped=MagickTrue;
2612 if (event.xmap.window == windows->image.id)
2614 if (windows->backdrop.id != (Window) NULL)
2615 (void) XInstallColormap(display,map_info->colormap);
2616 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2618 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2619 nexus=XMagickCommand(display,resource_info,windows,
2620 OpenCommand,&image,&state,exception);
2624 windows->image.mapped=MagickTrue;
2627 if (event.xmap.window == windows->info.id)
2629 windows->info.mapped=MagickTrue;
2632 if (event.xmap.window == windows->icon.id)
2635 Create an icon image.
2637 XMakeStandardColormap(display,icon_visual,icon_resources,
2638 display_image,icon_map,icon_pixel);
2639 (void) XMakeImage(display,icon_resources,&windows->icon,
2640 display_image,windows->icon.width,windows->icon.height,
2642 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2643 windows->icon.pixmap);
2644 (void) XClearWindow(display,windows->icon.id);
2645 (void) XWithdrawWindow(display,windows->info.id,
2646 windows->info.screen);
2647 windows->icon.mapped=MagickTrue;
2650 if (event.xmap.window == windows->command.id)
2652 windows->command.mapped=MagickTrue;
2655 if (event.xmap.window == windows->popup.id)
2657 windows->popup.mapped=MagickTrue;
2660 if (event.xmap.window == windows->widget.id)
2662 windows->widget.mapped=MagickTrue;
2669 (void) XRefreshKeyboardMapping(&event.xmapping);
2674 case PropertyNotify:
2690 if (display_image->debug != MagickFalse)
2691 (void) LogMagickEvent(X11Event,GetMagickModule(),
2692 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2693 event.xproperty.window,(unsigned long) event.xproperty.atom,
2694 event.xproperty.state);
2695 if (event.xproperty.atom != windows->im_remote_command)
2698 Display image named by the remote command protocol.
2700 status=XGetWindowProperty(display,event.xproperty.window,
2701 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
2702 AnyPropertyType,&type,&format,&length,&after,&data);
2703 if ((status != Success) || (length == 0))
2705 (void) CopyMagickString(resource_info->image_info->filename,
2706 (char *) data,MaxTextExtent);
2707 nexus=ReadImage(resource_info->image_info,exception);
2708 CatchException(exception);
2709 if (nexus != (Image *) NULL)
2711 (void) XFree((void *) data);
2714 case ReparentNotify:
2716 if (display_image->debug != MagickFalse)
2717 (void) LogMagickEvent(X11Event,GetMagickModule(),
2718 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2719 event.xreparent.window);
2724 if (display_image->debug != MagickFalse)
2725 (void) LogMagickEvent(X11Event,GetMagickModule(),
2726 "Unmap Notify: 0x%lx",event.xunmap.window);
2727 if (event.xunmap.window == windows->backdrop.id)
2729 windows->backdrop.mapped=MagickFalse;
2732 if (event.xunmap.window == windows->image.id)
2734 windows->image.mapped=MagickFalse;
2737 if (event.xunmap.window == windows->info.id)
2739 windows->info.mapped=MagickFalse;
2742 if (event.xunmap.window == windows->icon.id)
2744 if (map_info->colormap == icon_map->colormap)
2745 XConfigureImageColormap(display,resource_info,windows,
2747 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2749 windows->icon.mapped=MagickFalse;
2752 if (event.xunmap.window == windows->command.id)
2754 windows->command.mapped=MagickFalse;
2757 if (event.xunmap.window == windows->popup.id)
2759 if (windows->backdrop.id != (Window) NULL)
2760 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2762 windows->popup.mapped=MagickFalse;
2765 if (event.xunmap.window == windows->widget.id)
2767 if (windows->backdrop.id != (Window) NULL)
2768 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2770 windows->widget.mapped=MagickFalse;
2777 if (display_image->debug != MagickFalse)
2778 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2784 while (!(state & ExitState));
2785 image_list=(Image **) RelinquishMagickMemory(image_list);
2786 images=DestroyImageList(images);
2787 if ((windows->visual_info->klass == GrayScale) ||
2788 (windows->visual_info->klass == PseudoColor) ||
2789 (windows->visual_info->klass == DirectColor))
2794 if (windows->info.mapped)
2795 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2796 if (windows->command.mapped)
2797 (void) XWithdrawWindow(display,windows->command.id,
2798 windows->command.screen);
2800 if (resource_info->backdrop == MagickFalse)
2801 if (windows->backdrop.mapped)
2803 (void) XWithdrawWindow(display,windows->backdrop.id,\
2804 windows->backdrop.screen);
2805 (void) XDestroyWindow(display,windows->backdrop.id);
2806 windows->backdrop.id=(Window) NULL;
2807 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2808 (void) XDestroyWindow(display,windows->image.id);
2809 windows->image.id=(Window) NULL;
2811 XSetCursorState(display,windows,MagickTrue);
2812 XCheckRefreshWindows(display,windows);
2813 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2815 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2816 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2817 windows->image.pixmaps[scene]=(Pixmap) NULL;
2818 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2819 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2820 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2822 XSetCursorState(display,windows,MagickFalse);
2823 windows->image.pixmaps=(Pixmap *)
2824 RelinquishMagickMemory(windows->image.pixmaps);
2825 windows->image.matte_pixmaps=(Pixmap *)
2826 RelinquishMagickMemory(windows->image.matte_pixmaps);
2827 if (nexus == (Image *) NULL)
2832 if (windows->image.mapped != MagickFalse)
2833 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime);
2834 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2835 if (resource_info->map_type == (char *) NULL)
2836 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2837 DestroyXResources();
2839 (void) XSync(display,MagickFalse);
2841 Restore our progress monitor and warning handlers.
2843 (void) SetErrorHandler(warning_handler);
2844 (void) SetWarningHandler(warning_handler);
2846 Change to home directory.
2848 directory=getcwd(working_directory,MaxTextExtent);
2850 status=chdir(resource_info->home_directory);
2852 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2853 "UnableToOpenFile","%s",resource_info->home_directory);
2858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2862 + X S a v e I m a g e %
2866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2868 % XSaveImage() saves an image to a file.
2870 % The format of the XSaveImage method is:
2872 % MagickBooleanType XSaveImage(Display *display,
2873 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2874 % ExceptionInfo *exception)
2876 % A description of each parameter follows:
2878 % o status: Method XSaveImage return True if the image is
2879 % written. False is returned is there is a memory shortage or if the
2880 % image fails to write.
2882 % o display: Specifies a connection to an X server; returned from
2885 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2887 % o windows: Specifies a pointer to a XWindows structure.
2889 % o image: the image.
2892 static MagickBooleanType XSaveImage(Display *display,
2893 XResourceInfo *resource_info,XWindows *windows,Image *image,
2894 ExceptionInfo *exception)
2897 filename[MaxTextExtent];
2906 Request file name from user.
2908 if (resource_info->write_filename != (char *) NULL)
2909 (void) CopyMagickString(filename,resource_info->write_filename,
2914 path[MaxTextExtent];
2919 GetPathComponent(image->filename,HeadPath,path);
2920 GetPathComponent(image->filename,TailPath,filename);
2923 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2924 "UnableToOpenFile","%s",path);
2926 XFileBrowserWidget(display,windows,"Save",filename);
2927 if (*filename == '\0')
2929 if (IsPathAccessible(filename) != MagickFalse)
2935 File exists-- seek user's permission before overwriting.
2937 status=XConfirmWidget(display,windows,"Overwrite",filename);
2941 image_info=CloneImageInfo(resource_info->image_info);
2942 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2943 (void) SetImageInfo(image_info,1,exception);
2944 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2945 (LocaleCompare(image_info->magick,"JPG") == 0))
2948 quality[MaxTextExtent];
2954 Request JPEG quality from user.
2956 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
2957 image_info->quality);
2958 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2960 if (*quality == '\0')
2962 image->quality=StringToUnsignedLong(quality);
2963 image_info->interlace=status != MagickFalse ? NoInterlace :
2966 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2967 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2968 (LocaleCompare(image_info->magick,"PS") == 0) ||
2969 (LocaleCompare(image_info->magick,"PS2") == 0))
2972 geometry[MaxTextExtent];
2975 Request page geometry from user.
2977 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2978 if (LocaleCompare(image_info->magick,"PDF") == 0)
2979 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2980 if (image_info->page != (char *) NULL)
2981 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
2982 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2983 "Select page geometry:",geometry);
2984 if (*geometry != '\0')
2985 image_info->page=GetPageGeometry(geometry);
2990 image=GetFirstImageInList(image);
2991 status=WriteImages(image_info,image,filename,exception);
2992 if (status != MagickFalse)
2993 image->taint=MagickFalse;
2994 image_info=DestroyImageInfo(image_info);
2995 XSetCursorState(display,windows,MagickFalse);
2996 return(status != 0 ? MagickTrue : MagickFalse);
3001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3005 + A n i m a t e I m a g e s %
3009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3011 % AnimateImages() repeatedly displays an image sequence to any X window
3012 % screen. It returns a value other than 0 if successful. Check the
3013 % exception member of image to determine the reason for any failure.
3015 % The format of the AnimateImages method is:
3017 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3020 % A description of each parameter follows:
3022 % o image_info: the image info.
3024 % o image: the image.
3026 % o exception: return any errors or warnings in this structure.
3029 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3030 Image *image,ExceptionInfo *exception)
3032 assert(image_info != (const ImageInfo *) NULL);
3033 assert(image_info->signature == MagickSignature);
3034 assert(image != (Image *) NULL);
3035 assert(image->signature == MagickSignature);
3036 if (image->debug != MagickFalse)
3037 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3038 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
3039 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
3040 return(MagickFalse);