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,
593 XTextViewWidget(display,resource_info,windows,MagickFalse,
594 "Help Viewer - Animate",AnimateHelp);
597 case BrowseDocumentationCommand:
607 Browse the ImageMagick documentation.
609 root_window=XRootWindow(display,XDefaultScreen(display));
610 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
611 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
612 if (mozilla_window != (Window) NULL)
615 command[MaxTextExtent],
619 Display documentation using Netscape remote control.
621 url=GetMagickHomeURL();
622 (void) FormatLocaleString(command,MaxTextExtent,
623 "openurl(%s,new-tab)",url);
624 url=DestroyString(url);
625 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
626 (void) XChangeProperty(display,mozilla_window,mozilla_atom,
627 XA_STRING,8,PropModeReplace,(unsigned char *) command,
628 (int) strlen(command));
629 XSetCursorState(display,windows,MagickFalse);
632 XSetCursorState(display,windows,MagickTrue);
633 XCheckRefreshWindows(display,windows);
634 status=InvokeDelegate(resource_info->image_info,*image,"browse",
635 (char *) NULL,exception);
636 if (status == MagickFalse)
637 XNoticeWidget(display,windows,"Unable to browse documentation",
639 XDelay(display,1500);
640 XSetCursorState(display,windows,MagickFalse);
645 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
646 GetMagickCopyright());
654 if (resource_info->confirm_exit == MagickFalse)
655 XClientMessage(display,windows->image.id,windows->im_protocols,
656 windows->im_exit,CurrentTime);
663 Confirm program exit.
665 status=XConfirmWidget(display,windows,"Do you really want to exit",
666 resource_info->client_name);
668 XClientMessage(display,windows->image.id,windows->im_protocols,
669 windows->im_exit,CurrentTime);
680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684 + X A n i m a t e B a c k g r o u n d I m a g e %
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
690 % XAnimateBackgroundImage() animates an image sequence in the background of
693 % The format of the XAnimateBackgroundImage method is:
695 % void XAnimateBackgroundImage(Display *display,
696 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
698 % A description of each parameter follows:
700 % o display: Specifies a connection to an X server; returned from
703 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
705 % o images: the image list.
707 % o exception: return any errors or warnings in this structure.
711 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
718 #if defined(__cplusplus) || defined(c_plusplus)
722 static int SceneCompare(const void *x,const void *y)
728 image_1=(const Image **) x;
729 image_2=(const Image **) y;
730 return((int) ((*image_1)->scene-(*image_2)->scene));
733 #if defined(__cplusplus) || defined(c_plusplus)
737 MagickExport void XAnimateBackgroundImage(Display *display,
738 XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
741 geometry[MaxTextExtent],
742 visual_type[MaxTextExtent];
767 static XStandardColormap
771 *visual_info = (XVisualInfo *) NULL;
799 Determine target window.
801 assert(images != (Image *) NULL);
802 assert(images->signature == MagickSignature);
803 if (images->debug != MagickFalse)
804 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
805 resources=(*resource_info);
806 window_info.id=(Window) NULL;
807 root_window=XRootWindow(display,XDefaultScreen(display));
808 if (LocaleCompare(resources.window_id,"root") == 0)
809 window_info.id=root_window;
812 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
813 window_info.id=XWindowByID(display,root_window,
814 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
815 if (window_info.id == (Window) NULL)
817 XWindowByName(display,root_window,resources.window_id);
819 if (window_info.id == (Window) NULL)
821 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
822 resources.window_id);
826 Determine window visual id.
828 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
829 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
830 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
831 status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
832 MagickTrue : MagickFalse;
833 if (status != MagickFalse)
834 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
835 XVisualIDFromVisual(window_attributes.visual));
836 if (visual_info == (XVisualInfo *) NULL)
839 Allocate standard colormap.
841 map_info=XAllocStandardColormap();
842 if (map_info == (XStandardColormap *) NULL)
843 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
845 map_info->colormap=(Colormap) NULL;
846 pixel.pixels=(unsigned long *) NULL;
848 Initialize visual info.
850 resources.map_type=(char *) NULL;
851 resources.visual_type=visual_type;
852 visual_info=XBestVisualInfo(display,map_info,&resources);
853 if (visual_info == (XVisualInfo *) NULL)
854 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
857 Initialize window info.
859 window_info.ximage=(XImage *) NULL;
860 window_info.matte_image=(XImage *) NULL;
861 window_info.pixmap=(Pixmap) NULL;
862 window_info.matte_pixmap=(Pixmap) NULL;
865 Free previous root colors.
867 if (window_info.id == root_window)
868 XDestroyWindowColors(display,root_window);
869 coalesce_image=CoalesceImages(images,exception);
870 if (coalesce_image == (Image *) NULL)
871 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
873 images=coalesce_image;
874 if (resources.map_type == (char *) NULL)
875 if ((visual_info->klass != TrueColor) &&
876 (visual_info->klass != DirectColor))
882 Determine if the sequence of images has the identical colormap.
884 for (next=images; next != (Image *) NULL; )
886 next->matte=MagickFalse;
887 if ((next->storage_class == DirectClass) ||
888 (next->colors != images->colors) ||
889 (next->colors > (size_t) visual_info->colormap_size))
891 for (i=0; i < (ssize_t) images->colors; i++)
892 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
894 if (i < (ssize_t) images->colors)
896 next=GetNextImageInList(next);
898 if (next != (Image *) NULL)
899 (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
903 Sort images by increasing scene number.
905 number_scenes=GetImageListLength(images);
906 image_list=ImageListToArray(images,exception);
907 if (image_list == (Image **) NULL)
908 ThrowXWindowFatalException(ResourceLimitFatalError,
909 "MemoryAllocationFailed",images->filename);
910 for (i=0; i < (ssize_t) number_scenes; i++)
911 if (image_list[i]->scene == 0)
913 if (i == (ssize_t) number_scenes)
914 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
916 Initialize Standard Colormap.
918 resources.colormap=SharedColormap;
919 display_image=image_list[0];
920 for (scene=0; scene < (int) number_scenes; scene++)
922 if ((resource_info->map_type != (char *) NULL) ||
923 (visual_info->klass == TrueColor) ||
924 (visual_info->klass == DirectColor))
925 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
926 MagickFalse ? TrueColorType : TrueColorMatteType,exception);
927 if ((display_image->columns < image_list[scene]->columns) &&
928 (display_image->rows < image_list[scene]->rows))
929 display_image=image_list[scene];
931 if ((resource_info->map_type != (char *) NULL) ||
932 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
933 (void) SetImageType(display_image,display_image->matte == MagickFalse ?
934 TrueColorType : TrueColorMatteType,exception);
935 XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
938 Graphic context superclass.
940 context_values.background=pixel.background_color.pixel;
941 context_values.foreground=pixel.foreground_color.pixel;
942 pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
943 (GCBackground | GCForeground),&context_values);
944 if (pixel.annotate_context == (GC) NULL)
945 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
948 Initialize Image window attributes.
950 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
951 &resources,&window_info);
955 window_info.width=(unsigned int) image_list[0]->columns;
956 window_info.height=(unsigned int) image_list[0]->rows;
957 if ((image_list[0]->columns != window_info.width) ||
958 (image_list[0]->rows != window_info.height))
959 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
960 image_list[0]->filename);
961 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
962 window_attributes.width,window_attributes.height);
963 geometry_info.width=window_info.width;
964 geometry_info.height=window_info.height;
965 geometry_info.x=(ssize_t) window_info.x;
966 geometry_info.y=(ssize_t) window_info.y;
967 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
968 &geometry_info.width,&geometry_info.height);
969 window_info.width=(unsigned int) geometry_info.width;
970 window_info.height=(unsigned int) geometry_info.height;
971 window_info.x=(int) geometry_info.x;
972 window_info.y=(int) geometry_info.y;
973 status=XMakeImage(display,&resources,&window_info,image_list[0],
974 window_info.width,window_info.height,exception);
975 if (status == MagickFalse)
976 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
980 if (display_image->debug != MagickFalse)
982 (void) LogMagickEvent(X11Event,GetMagickModule(),
983 "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
984 image_list[0]->scene,(double) image_list[0]->columns,(double)
985 image_list[0]->rows);
986 if (image_list[0]->colors != 0)
987 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
988 image_list[0]->colors);
989 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
990 image_list[0]->magick);
993 Adjust image dimensions as specified by backdrop or geometry options.
995 width=window_info.width;
996 height=window_info.height;
997 if (resources.backdrop != MagickFalse)
1000 Center image on window.
1002 window_info.x=(int) (window_attributes.width/2)-
1003 (window_info.ximage->width/2);
1004 window_info.y=(int) (window_attributes.height/2)-
1005 (window_info.ximage->height/2);
1006 width=(unsigned int) window_attributes.width;
1007 height=(unsigned int) window_attributes.height;
1009 if (resources.image_geometry != (char *) NULL)
1012 default_geometry[MaxTextExtent];
1022 User specified geometry.
1024 size_hints=XAllocSizeHints();
1025 if (size_hints == (XSizeHints *) NULL)
1026 ThrowXWindowFatalException(ResourceLimitFatalError,
1027 "MemoryAllocationFailed",images->filename);
1028 size_hints->flags=0L;
1029 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%ux%u",width,
1031 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1032 default_geometry,window_info.border_width,size_hints,&window_info.x,
1033 &window_info.y,(int *) &width,(int *) &height,&gravity);
1034 if (((flags & (XValue | YValue))) != 0)
1036 width=(unsigned int) window_attributes.width;
1037 height=(unsigned int) window_attributes.height;
1039 (void) XFree((void *) size_hints);
1042 Create the X pixmap.
1044 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1045 (unsigned int) height,window_info.depth);
1046 if (window_info.pixmap == (Pixmap) NULL)
1047 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1050 Display pixmap on the window.
1052 if (((unsigned int) width > window_info.width) ||
1053 ((unsigned int) height > window_info.height))
1054 (void) XFillRectangle(display,window_info.pixmap,
1055 window_info.annotate_context,0,0,(unsigned int) width,
1056 (unsigned int) height);
1057 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1058 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1059 window_info.height);
1060 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1061 (void) XClearWindow(display,window_info.id);
1063 Initialize image pixmaps structure.
1065 window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1066 sizeof(*window_info.pixmaps));
1067 window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1068 sizeof(*window_info.matte_pixmaps));
1069 if ((window_info.pixmaps == (Pixmap *) NULL) ||
1070 (window_info.matte_pixmaps == (Pixmap *) NULL))
1071 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1073 window_info.pixmaps[0]=window_info.pixmap;
1074 window_info.matte_pixmaps[0]=window_info.pixmap;
1075 for (scene=1; scene < (int) number_scenes; scene++)
1084 window_info.pixmap=(Pixmap) NULL;
1085 window_info.matte_pixmap=(Pixmap) NULL;
1086 if ((resources.map_type != (char *) NULL) ||
1087 (visual_info->klass == TrueColor) ||
1088 (visual_info->klass == DirectColor))
1089 if (image_list[scene]->storage_class == PseudoClass)
1090 XGetPixelInfo(display,visual_info,map_info,&resources,
1091 image_list[scene],window_info.pixel_info);
1092 columns=(unsigned int) image_list[scene]->columns;
1093 rows=(unsigned int) image_list[scene]->rows;
1094 if ((image_list[scene]->columns != columns) ||
1095 (image_list[scene]->rows != rows))
1096 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1097 image_list[scene]->filename);
1098 status=XMakeImage(display,&resources,&window_info,image_list[scene],
1099 columns,rows,exception);
1100 if (status == MagickFalse)
1101 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1103 if (display_image->debug != MagickFalse)
1105 (void) LogMagickEvent(X11Event,GetMagickModule(),
1106 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1107 image_list[scene]->filename,(double) columns,(double) rows);
1108 if (image_list[scene]->colors != 0)
1109 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1110 image_list[scene]->colors);
1111 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1112 image_list[scene]->magick);
1115 Create the X pixmap.
1117 window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1119 if (window_info.pixmap == (Pixmap) NULL)
1120 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1123 Display pixmap on the window.
1125 if ((width > window_info.width) || (height > window_info.height))
1126 (void) XFillRectangle(display,window_info.pixmap,
1127 window_info.annotate_context,0,0,width,height);
1128 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1129 window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1130 window_info.height);
1131 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1132 window_info.pixmap);
1133 (void) XClearWindow(display,window_info.id);
1134 window_info.pixmaps[scene]=window_info.pixmap;
1135 window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1136 if (image_list[scene]->matte)
1137 (void) XClearWindow(display,window_info.id);
1138 delay=1000*image_list[scene]->delay/MagickMax(
1139 image_list[scene]->ticks_per_second,1L);
1140 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1142 window_info.pixel_info=(&pixel);
1144 Display pixmap on the window.
1146 (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1150 for (scene=0; scene < (int) number_scenes; scene++)
1152 if (XEventsQueued(display,QueuedAfterFlush) > 0)
1154 (void) XNextEvent(display,&event);
1155 if (event.type == DestroyNotify)
1158 window_info.pixmap=window_info.pixmaps[scene];
1159 window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1160 (void) XSetWindowBackgroundPixmap(display,window_info.id,
1161 window_info.pixmap);
1162 (void) XClearWindow(display,window_info.id);
1163 (void) XSync(display,MagickFalse);
1164 delay=1000*image_list[scene]->delay/MagickMax(
1165 image_list[scene]->ticks_per_second,1L);
1166 XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1168 } while (event.type != DestroyNotify);
1169 (void) XSync(display,MagickFalse);
1170 image_list=(Image **) RelinquishMagickMemory(image_list);
1171 images=DestroyImageList(images);
1175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1179 + X A n i m a t e I m a g e s %
1183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 % XAnimateImages() displays an image via X11.
1187 % The format of the XAnimateImages method is:
1189 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1190 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1192 % A description of each parameter follows:
1194 % o display: Specifies a connection to an X server; returned from
1197 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1199 % o argv: Specifies the application's argument list.
1201 % o argc: Specifies the number of arguments.
1203 % o images: the image list.
1205 % o exception: return any errors or warnings in this structure.
1208 MagickExport Image *XAnimateImages(Display *display,
1209 XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1210 ExceptionInfo *exception)
1212 #define MagickMenus 4
1213 #define MaXWindows 8
1214 #define MagickTitle "Commands"
1252 "Browse Documentation",
1258 **Menus[MagickMenus]=
1266 static const CommandType
1290 DirectionCommands[]=
1298 BrowseDocumentationCommand,
1302 static const CommandType
1303 *Commands[MagickMenus]=
1312 command[MaxTextExtent],
1314 geometry[MaxTextExtent],
1315 resource_name[MaxTextExtent];
1352 working_directory[MaxTextExtent];
1358 *magick_windows[MaXWindows];
1412 assert(images != (Image *) NULL);
1413 assert(images->signature == MagickSignature);
1414 if (images->debug != MagickFalse)
1415 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1416 warning_handler=(WarningHandler) NULL;
1417 windows=XSetWindows((XWindows *) ~0);
1418 if (windows != (XWindows *) NULL)
1423 status=chdir(working_directory);
1425 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
1426 "UnableToOpenFile","%s",working_directory);
1427 warning_handler=resource_info->display_warnings ?
1428 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1429 warning_handler=resource_info->display_warnings ?
1430 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1438 Initialize window structure.
1440 for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1442 if (p->storage_class == DirectClass)
1444 resource_info->colors=0;
1447 if (p->colors > resource_info->colors)
1448 resource_info->colors=p->colors;
1450 windows=XSetWindows(XInitializeWindows(display,resource_info));
1451 if (windows == (XWindows *) NULL)
1452 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1455 Initialize window id's.
1458 magick_windows[number_windows++]=(&windows->icon);
1459 magick_windows[number_windows++]=(&windows->backdrop);
1460 magick_windows[number_windows++]=(&windows->image);
1461 magick_windows[number_windows++]=(&windows->info);
1462 magick_windows[number_windows++]=(&windows->command);
1463 magick_windows[number_windows++]=(&windows->widget);
1464 magick_windows[number_windows++]=(&windows->popup);
1465 for (i=0; i < (ssize_t) number_windows; i++)
1466 magick_windows[i]->id=(Window) NULL;
1469 Initialize font info.
1471 if (windows->font_info != (XFontStruct *) NULL)
1472 (void) XFreeFont(display,windows->font_info);
1473 windows->font_info=XBestFont(display,resource_info,MagickFalse);
1474 if (windows->font_info == (XFontStruct *) NULL)
1475 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1476 resource_info->font);
1478 Initialize Standard Colormap.
1480 map_info=windows->map_info;
1481 icon_map=windows->icon_map;
1482 visual_info=windows->visual_info;
1483 icon_visual=windows->icon_visual;
1484 pixel=windows->pixel_info;
1485 icon_pixel=windows->icon_pixel;
1486 font_info=windows->font_info;
1487 icon_resources=windows->icon_resources;
1488 class_hints=windows->class_hints;
1489 manager_hints=windows->manager_hints;
1490 root_window=XRootWindow(display,visual_info->screen);
1491 coalesce_image=CoalesceImages(images,exception);
1492 if (coalesce_image == (Image *) NULL)
1493 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1495 images=coalesce_image;
1496 if (resource_info->map_type == (char *) NULL)
1497 if ((visual_info->klass != TrueColor) &&
1498 (visual_info->klass != DirectColor))
1504 Determine if the sequence of images has the identical colormap.
1506 for (next=images; next != (Image *) NULL; )
1508 next->matte=MagickFalse;
1509 if ((next->storage_class == DirectClass) ||
1510 (next->colors != images->colors) ||
1511 (next->colors > (size_t) visual_info->colormap_size))
1513 for (i=0; i < (ssize_t) images->colors; i++)
1514 if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1516 if (i < (ssize_t) images->colors)
1518 next=GetNextImageInList(next);
1520 if (next != (Image *) NULL)
1521 (void) RemapImages(resource_info->quantize_info,images,
1522 (Image *) NULL,exception);
1525 Sort images by increasing scene number.
1527 number_scenes=GetImageListLength(images);
1528 image_list=ImageListToArray(images,exception);
1529 if (image_list == (Image **) NULL)
1530 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1532 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1533 if (image_list[scene]->scene == 0)
1535 if (scene == (ssize_t) number_scenes)
1536 qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1538 Initialize Standard Colormap.
1540 nexus=NewImageList();
1541 display_image=image_list[0];
1542 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1544 if ((resource_info->map_type != (char *) NULL) ||
1545 (visual_info->klass == TrueColor) ||
1546 (visual_info->klass == DirectColor))
1547 (void) SetImageType(image_list[scene],image_list[scene]->matte ==
1548 MagickFalse ? TrueColorType : TrueColorMatteType,exception);
1549 if ((display_image->columns < image_list[scene]->columns) &&
1550 (display_image->rows < image_list[scene]->rows))
1551 display_image=image_list[scene];
1553 if (display_image->debug != MagickFalse)
1555 (void) LogMagickEvent(X11Event,GetMagickModule(),
1556 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1557 display_image->scene,(double) display_image->columns,(double)
1558 display_image->rows);
1559 if (display_image->colors != 0)
1560 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1561 display_image->colors);
1562 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1563 display_image->magick);
1565 XMakeStandardColormap(display,visual_info,resource_info,display_image,
1566 map_info,pixel,exception);
1568 Initialize graphic context.
1570 windows->context.id=(Window) NULL;
1571 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1572 resource_info,&windows->context);
1573 (void) CloneString(&class_hints->res_name,resource_info->client_name);
1574 (void) CloneString(&class_hints->res_class,resource_info->client_name);
1575 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
1576 manager_hints->flags=InputHint | StateHint;
1577 manager_hints->input=MagickFalse;
1578 manager_hints->initial_state=WithdrawnState;
1579 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1581 if (display_image->debug != MagickFalse)
1582 (void) LogMagickEvent(X11Event,GetMagickModule(),
1583 "Window id: 0x%lx (context)",windows->context.id);
1584 context_values.background=pixel->background_color.pixel;
1585 context_values.font=font_info->fid;
1586 context_values.foreground=pixel->foreground_color.pixel;
1587 context_values.graphics_exposures=MagickFalse;
1588 context_mask=(MagickStatusType)
1589 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1590 if (pixel->annotate_context != (GC) NULL)
1591 (void) XFreeGC(display,pixel->annotate_context);
1592 pixel->annotate_context=
1593 XCreateGC(display,windows->context.id,context_mask,&context_values);
1594 if (pixel->annotate_context == (GC) NULL)
1595 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1597 context_values.background=pixel->depth_color.pixel;
1598 if (pixel->widget_context != (GC) NULL)
1599 (void) XFreeGC(display,pixel->widget_context);
1600 pixel->widget_context=
1601 XCreateGC(display,windows->context.id,context_mask,&context_values);
1602 if (pixel->widget_context == (GC) NULL)
1603 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1605 context_values.background=pixel->foreground_color.pixel;
1606 context_values.foreground=pixel->background_color.pixel;
1607 context_values.plane_mask=
1608 context_values.background ^ context_values.foreground;
1609 if (pixel->highlight_context != (GC) NULL)
1610 (void) XFreeGC(display,pixel->highlight_context);
1611 pixel->highlight_context=XCreateGC(display,windows->context.id,
1612 (size_t) (context_mask | GCPlaneMask),&context_values);
1613 if (pixel->highlight_context == (GC) NULL)
1614 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1616 (void) XDestroyWindow(display,windows->context.id);
1618 Initialize icon window.
1620 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1621 icon_resources,&windows->icon);
1622 windows->icon.geometry=resource_info->icon_geometry;
1623 XBestIconSize(display,&windows->icon,display_image);
1624 windows->icon.attributes.colormap=
1625 XDefaultColormap(display,icon_visual->screen);
1626 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1627 manager_hints->flags=InputHint | StateHint;
1628 manager_hints->input=MagickFalse;
1629 manager_hints->initial_state=IconicState;
1630 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1632 if (display_image->debug != MagickFalse)
1633 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1636 Initialize graphic context for icon window.
1638 if (icon_pixel->annotate_context != (GC) NULL)
1639 (void) XFreeGC(display,icon_pixel->annotate_context);
1640 context_values.background=icon_pixel->background_color.pixel;
1641 context_values.foreground=icon_pixel->foreground_color.pixel;
1642 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1643 (size_t) (GCBackground | GCForeground),&context_values);
1644 if (icon_pixel->annotate_context == (GC) NULL)
1645 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1647 windows->icon.annotate_context=icon_pixel->annotate_context;
1649 Initialize Image window.
1651 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1652 resource_info,&windows->image);
1653 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1654 if (resource_info->use_shared_memory == MagickFalse)
1655 windows->image.shared_memory=MagickFalse;
1656 if (resource_info->title != (char *) NULL)
1661 title=InterpretImageProperties(resource_info->image_info,display_image,
1662 resource_info->title,exception);
1663 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1664 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
1665 title=DestroyString(title);
1670 filename[MaxTextExtent];
1673 Window name is the base of the filename.
1675 GetPathComponent(display_image->magick_filename,TailPath,filename);
1676 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1677 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1678 display_image->scene,(double) number_scenes);
1679 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
1681 if (resource_info->immutable != MagickFalse)
1682 windows->image.immutable=MagickTrue;
1683 windows->image.shape=MagickTrue;
1684 windows->image.geometry=resource_info->image_geometry;
1685 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
1686 XDisplayWidth(display,visual_info->screen),
1687 XDisplayHeight(display,visual_info->screen));
1688 geometry_info.width=display_image->columns;
1689 geometry_info.height=display_image->rows;
1692 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1693 &geometry_info.width,&geometry_info.height);
1694 windows->image.width=(unsigned int) geometry_info.width;
1695 windows->image.height=(unsigned int) geometry_info.height;
1696 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1697 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1698 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1699 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1700 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1701 resource_info,&windows->backdrop);
1702 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1705 Initialize backdrop window.
1707 windows->backdrop.x=0;
1708 windows->backdrop.y=0;
1709 (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1710 windows->backdrop.flags=(size_t) (USSize | USPosition);
1711 windows->backdrop.width=(unsigned int)
1712 XDisplayWidth(display,visual_info->screen);
1713 windows->backdrop.height=(unsigned int)
1714 XDisplayHeight(display,visual_info->screen);
1715 windows->backdrop.border_width=0;
1716 windows->backdrop.immutable=MagickTrue;
1717 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1719 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1720 StructureNotifyMask;
1721 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1722 manager_hints->icon_window=windows->icon.id;
1723 manager_hints->input=MagickTrue;
1724 manager_hints->initial_state=
1725 resource_info->iconic ? IconicState : NormalState;
1726 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1727 &windows->backdrop);
1728 if (display_image->debug != MagickFalse)
1729 (void) LogMagickEvent(X11Event,GetMagickModule(),
1730 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1731 (void) XMapWindow(display,windows->backdrop.id);
1732 (void) XClearWindow(display,windows->backdrop.id);
1733 if (windows->image.id != (Window) NULL)
1735 (void) XDestroyWindow(display,windows->image.id);
1736 windows->image.id=(Window) NULL;
1739 Position image in the center the backdrop.
1741 windows->image.flags|=USPosition;
1742 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1743 (windows->image.width/2);
1744 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1745 (windows->image.height/2);
1747 manager_hints->flags=IconWindowHint | InputHint | StateHint;
1748 manager_hints->icon_window=windows->icon.id;
1749 manager_hints->input=MagickTrue;
1750 manager_hints->initial_state=
1751 resource_info->iconic ? IconicState : NormalState;
1752 if (windows->group_leader.id != (Window) NULL)
1757 manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1758 manager_hints->window_group=windows->group_leader.id;
1759 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1760 if (display_image->debug != MagickFalse)
1761 (void) LogMagickEvent(X11Event,GetMagickModule(),
1762 "Window id: 0x%lx (group leader)",windows->group_leader.id);
1764 XMakeWindow(display,
1765 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1766 argv,argc,class_hints,manager_hints,&windows->image);
1767 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1768 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1769 if (windows->group_leader.id != (Window) NULL)
1770 (void) XSetTransientForHint(display,windows->image.id,
1771 windows->group_leader.id);
1772 if (display_image->debug != MagickFalse)
1773 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1776 Initialize Info widget.
1778 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1779 resource_info,&windows->info);
1780 (void) CloneString(&windows->info.name,"Info");
1781 (void) CloneString(&windows->info.icon_name,"Info");
1782 windows->info.border_width=1;
1785 windows->info.flags|=PPosition;
1786 windows->info.attributes.win_gravity=UnmapGravity;
1787 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1788 StructureNotifyMask;
1789 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1790 manager_hints->input=MagickFalse;
1791 manager_hints->initial_state=NormalState;
1792 manager_hints->window_group=windows->image.id;
1793 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1795 windows->info.highlight_stipple=XCreateBitmapFromData(display,
1796 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1797 windows->info.shadow_stipple=XCreateBitmapFromData(display,
1798 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1799 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1800 if (windows->image.mapped)
1801 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1802 if (display_image->debug != MagickFalse)
1803 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1806 Initialize Command widget.
1808 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1809 resource_info,&windows->command);
1810 windows->command.data=MagickMenus;
1811 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1812 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
1813 resource_info->client_name);
1814 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1815 resource_name,"geometry",(char *) NULL);
1816 (void) CloneString(&windows->command.name,MagickTitle);
1817 windows->command.border_width=0;
1818 windows->command.flags|=PPosition;
1819 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1820 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1821 OwnerGrabButtonMask | StructureNotifyMask;
1822 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1823 manager_hints->input=MagickTrue;
1824 manager_hints->initial_state=NormalState;
1825 manager_hints->window_group=windows->image.id;
1826 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1828 windows->command.highlight_stipple=XCreateBitmapFromData(display,
1829 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1831 windows->command.shadow_stipple=XCreateBitmapFromData(display,
1832 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1833 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1834 if (display_image->debug != MagickFalse)
1835 (void) LogMagickEvent(X11Event,GetMagickModule(),
1836 "Window id: 0x%lx (command)",windows->command.id);
1838 Initialize Widget window.
1840 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1841 resource_info,&windows->widget);
1842 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
1843 resource_info->client_name);
1844 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1845 resource_name,"geometry",(char *) NULL);
1846 windows->widget.border_width=0;
1847 windows->widget.flags|=PPosition;
1848 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1849 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1850 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1851 StructureNotifyMask;
1852 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1853 manager_hints->input=MagickTrue;
1854 manager_hints->initial_state=NormalState;
1855 manager_hints->window_group=windows->image.id;
1856 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1858 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1859 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1860 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1861 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1862 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1863 if (display_image->debug != MagickFalse)
1864 (void) LogMagickEvent(X11Event,GetMagickModule(),
1865 "Window id: 0x%lx (widget)",windows->widget.id);
1867 Initialize popup window.
1869 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1870 resource_info,&windows->popup);
1871 windows->popup.border_width=0;
1872 windows->popup.flags|=PPosition;
1873 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1874 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1875 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1876 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1877 manager_hints->input=MagickTrue;
1878 manager_hints->initial_state=NormalState;
1879 manager_hints->window_group=windows->image.id;
1880 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1882 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1883 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1884 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1885 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1886 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1887 if (display_image->debug != MagickFalse)
1888 (void) LogMagickEvent(X11Event,GetMagickModule(),
1889 "Window id: 0x%lx (pop up)",windows->popup.id);
1891 Set out progress and warning handlers.
1893 if (warning_handler == (WarningHandler) NULL)
1895 warning_handler=resource_info->display_warnings ?
1896 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1897 warning_handler=resource_info->display_warnings ?
1898 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
1901 Initialize X image structure.
1906 Initialize image pixmaps structure.
1908 window_changes.width=(int) windows->image.width;
1909 window_changes.height=(int) windows->image.height;
1910 (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1911 (unsigned int) (CWWidth | CWHeight),&window_changes);
1912 windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1913 sizeof(*windows->image.pixmaps));
1914 windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1915 sizeof(*windows->image.pixmaps));
1916 if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1917 (windows->image.matte_pixmaps == (Pixmap *) NULL))
1918 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1920 if ((windows->image.mapped == MagickFalse) ||
1921 (windows->backdrop.id != (Window) NULL))
1922 (void) XMapWindow(display,windows->image.id);
1923 XSetCursorState(display,windows,MagickTrue);
1924 for (scene=0; scene < (ssize_t) number_scenes; scene++)
1933 (void) TransformImageColorspace(image_list[scene],RGBColorspace,exception);
1934 windows->image.pixmap=(Pixmap) NULL;
1935 windows->image.matte_pixmap=(Pixmap) NULL;
1936 if ((resource_info->map_type != (char *) NULL) ||
1937 (visual_info->klass == TrueColor) ||
1938 (visual_info->klass == DirectColor))
1939 if (image_list[scene]->storage_class == PseudoClass)
1940 XGetPixelInfo(display,visual_info,map_info,resource_info,
1941 image_list[scene],windows->image.pixel_info);
1942 columns=(unsigned int) image_list[scene]->columns;
1943 rows=(unsigned int) image_list[scene]->rows;
1944 if ((image_list[scene]->columns != columns) ||
1945 (image_list[scene]->rows != rows))
1946 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1947 image_list[scene]->filename);
1948 status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1949 columns,rows,exception);
1950 if (status == MagickFalse)
1951 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1953 if (image_list[scene]->debug != MagickFalse)
1955 (void) LogMagickEvent(X11Event,GetMagickModule(),
1956 "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1957 image_list[scene]->filename,(double) columns,(double) rows);
1958 if (image_list[scene]->colors != 0)
1959 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1960 image_list[scene]->colors);
1961 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1962 image_list[scene]->magick);
1965 Window name is the base of the filename.
1967 if (resource_info->title != (char *) NULL)
1972 title=InterpretImageProperties(resource_info->image_info,
1973 image_list[scene],resource_info->title,exception);
1974 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
1975 title=DestroyString(title);
1979 p=image_list[scene]->magick_filename+
1980 strlen(image_list[scene]->magick_filename)-1;
1981 while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1983 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
1984 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1985 (double) number_scenes);
1987 status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1988 if (status != Success)
1990 XSetWMName(display,windows->image.id,&window_name);
1991 (void) XFree((void *) window_name.value);
1993 windows->image.pixmaps[scene]=windows->image.pixmap;
1994 windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1999 event.xexpose.width=(int) image_list[scene]->columns;
2000 event.xexpose.height=(int) image_list[scene]->rows;
2001 XRefreshWindow(display,&windows->image,&event);
2002 (void) XSync(display,MagickFalse);
2005 XSetCursorState(display,windows,MagickFalse);
2006 if (windows->command.mapped)
2007 (void) XMapRaised(display,windows->command.id);
2011 nexus=NewImageList();
2015 image=image_list[0];
2016 state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2017 (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2021 if (XEventsQueued(display,QueuedAfterFlush) == 0)
2022 if ((state & PlayAnimationState) || (state & StepAnimationState))
2028 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2029 XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2030 if (state & ForwardAnimationState)
2033 Forward animation: increment scene number.
2035 if (scene < ((ssize_t) number_scenes-1))
2040 if (iterations == (ssize_t) image_list[0]->iterations)
2045 if ((state & AutoReverseAnimationState) != 0)
2047 state&=(~ForwardAnimationState);
2052 if ((state & RepeatAnimationState) == 0)
2053 state&=(~PlayAnimationState);
2062 Reverse animation: decrement scene number.
2064 if (scene > first_scene)
2069 if (iterations == (ssize_t) image_list[0]->iterations)
2072 state&=(~RepeatAnimationState);
2074 if (state & AutoReverseAnimationState)
2076 state|=ForwardAnimationState;
2082 if ((state & RepeatAnimationState) == MagickFalse)
2083 state&=(~PlayAnimationState);
2084 scene=(ssize_t) number_scenes-1;
2088 scene=MagickMax(scene,0);
2089 image=image_list[scene];
2090 if ((image != (Image *) NULL) && (image->start_loop != 0))
2092 if ((state & StepAnimationState) ||
2093 (resource_info->title != (char *) NULL))
2096 Update window title.
2098 p=image_list[scene]->filename+
2099 strlen(image_list[scene]->filename)-1;
2100 while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2102 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
2103 "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2104 scene+1,(double) number_scenes);
2105 if (resource_info->title != (char *) NULL)
2110 title=InterpretImageProperties(resource_info->image_info,
2111 image,resource_info->title,exception);
2112 (void) CopyMagickString(windows->image.name,title,
2114 title=DestroyString(title);
2116 status=XStringListToTextProperty(&windows->image.name,1,
2118 if (status != Success)
2120 XSetWMName(display,windows->image.id,&window_name);
2121 (void) XFree((void *) window_name.value);
2125 Copy X pixmap to Image window.
2127 XGetPixelInfo(display,visual_info,map_info,resource_info,
2128 image_list[scene],windows->image.pixel_info);
2129 windows->image.ximage->width=(int) image->columns;
2130 windows->image.ximage->height=(int) image->rows;
2131 windows->image.pixmap=windows->image.pixmaps[scene];
2132 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2135 event.xexpose.width=(int) image->columns;
2136 event.xexpose.height=(int) image->rows;
2137 if ((state & ExitState) == 0)
2139 XRefreshWindow(display,&windows->image,&event);
2140 (void) XSync(display,MagickFalse);
2142 state&=(~StepAnimationState);
2143 if (pause != MagickFalse)
2144 for (i=0; i < (ssize_t) resource_info->pause; i++)
2149 status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2156 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2157 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2158 *(command+length)='\0';
2159 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2161 XClientMessage(display,windows->image.id,
2162 windows->im_protocols,windows->im_exit,CurrentTime);
2171 Handle a window event.
2173 timestamp=time((time_t *) NULL);
2174 (void) XNextEvent(display,&event);
2175 if (windows->image.stasis == MagickFalse)
2176 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
2177 MagickTrue : MagickFalse;
2178 if (event.xany.window == windows->command.id)
2184 Select a command from the Command widget.
2186 id=XCommandWidget(display,windows,CommandMenu,&event);
2189 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
2190 command_type=CommandMenus[id];
2191 if (id < MagickMenus)
2197 Select a command from a pop-up menu.
2199 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2203 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
2204 command_type=Commands[id][entry];
2206 if (command_type != NullCommand)
2207 nexus=XMagickCommand(display,resource_info,windows,
2208 command_type,&image,&state,exception);
2215 if (display_image->debug != MagickFalse)
2216 (void) LogMagickEvent(X11Event,GetMagickModule(),
2217 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2218 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2219 if ((event.xbutton.button == Button3) &&
2220 (event.xbutton.state & Mod1Mask))
2223 Convert Alt-Button3 to Button2.
2225 event.xbutton.button=Button2;
2226 event.xbutton.state&=(~Mod1Mask);
2228 if (event.xbutton.window == windows->backdrop.id)
2230 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2231 event.xbutton.time);
2234 if (event.xbutton.window == windows->image.id)
2236 if (resource_info->immutable != MagickFalse)
2242 Map/unmap Command widget.
2244 if (windows->command.mapped)
2245 (void) XWithdrawWindow(display,windows->command.id,
2246 windows->command.screen);
2249 (void) XCommandWidget(display,windows,CommandMenu,
2251 (void) XMapRaised(display,windows->command.id);
2258 if (display_image->debug != MagickFalse)
2259 (void) LogMagickEvent(X11Event,GetMagickModule(),
2260 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2261 event.xbutton.button,event.xbutton.x,event.xbutton.y);
2266 if (display_image->debug != MagickFalse)
2267 (void) LogMagickEvent(X11Event,GetMagickModule(),
2268 "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2269 event.xclient.window,(unsigned long) event.xclient.message_type,
2270 event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2271 if (event.xclient.message_type == windows->im_protocols)
2273 if (*event.xclient.data.l == (long) windows->im_update_colormap)
2276 Update graphic context and window colormap.
2278 for (i=0; i < (ssize_t) number_windows; i++)
2280 if (magick_windows[i]->id == windows->icon.id)
2282 context_values.background=pixel->background_color.pixel;
2283 context_values.foreground=pixel->foreground_color.pixel;
2284 (void) XChangeGC(display,magick_windows[i]->annotate_context,
2285 context_mask,&context_values);
2286 (void) XChangeGC(display,magick_windows[i]->widget_context,
2287 context_mask,&context_values);
2288 context_values.background=pixel->foreground_color.pixel;
2289 context_values.foreground=pixel->background_color.pixel;
2290 context_values.plane_mask=
2291 context_values.background ^ context_values.foreground;
2292 (void) XChangeGC(display,magick_windows[i]->highlight_context,
2293 (size_t) (context_mask | GCPlaneMask),
2295 magick_windows[i]->attributes.background_pixel=
2296 pixel->background_color.pixel;
2297 magick_windows[i]->attributes.border_pixel=
2298 pixel->border_color.pixel;
2299 magick_windows[i]->attributes.colormap=map_info->colormap;
2300 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2301 (unsigned long) magick_windows[i]->mask,
2302 &magick_windows[i]->attributes);
2304 if (windows->backdrop.id != (Window) NULL)
2305 (void) XInstallColormap(display,map_info->colormap);
2308 if (*event.xclient.data.l == (long) windows->im_exit)
2315 if (event.xclient.message_type == windows->dnd_protocols)
2333 Display image named by the Drag-and-Drop selection.
2335 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2337 selection=XInternAtom(display,"DndSelection",MagickFalse);
2338 status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2339 MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2341 if ((status != Success) || (length == 0))
2343 if (*event.xclient.data.l == 2)
2348 (void) CopyMagickString(resource_info->image_info->filename,
2349 (char *) data,MaxTextExtent);
2356 if (LocaleNCompare((char *) data,"file:",5) != 0)
2358 (void) XFree((void *) data);
2361 (void) CopyMagickString(resource_info->image_info->filename,
2362 ((char *) data)+5,MaxTextExtent);
2364 nexus=ReadImage(resource_info->image_info,exception);
2365 CatchException(exception);
2366 if (nexus != (Image *) NULL)
2368 (void) XFree((void *) data);
2372 If client window delete message, exit.
2374 if (event.xclient.message_type != windows->wm_protocols)
2376 if (*event.xclient.data.l == (long) windows->wm_take_focus)
2378 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2379 (Time) event.xclient.data.l[1]);
2382 if (*event.xclient.data.l != (long) windows->wm_delete_window)
2384 (void) XWithdrawWindow(display,event.xclient.window,
2385 visual_info->screen);
2386 if (event.xclient.window == windows->image.id)
2393 case ConfigureNotify:
2395 if (display_image->debug != MagickFalse)
2396 (void) LogMagickEvent(X11Event,GetMagickModule(),
2397 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2398 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2399 event.xconfigure.y,event.xconfigure.send_event);
2400 if (event.xconfigure.window == windows->image.id)
2402 if (event.xconfigure.send_event != 0)
2408 Position the transient windows relative of the Image window.
2410 if (windows->command.geometry == (char *) NULL)
2411 if (windows->command.mapped == MagickFalse)
2414 event.xconfigure.x-windows->command.width-25;
2415 windows->command.y=event.xconfigure.y;
2416 XConstrainWindowPosition(display,&windows->command);
2417 window_changes.x=windows->command.x;
2418 window_changes.y=windows->command.y;
2419 (void) XReconfigureWMWindow(display,windows->command.id,
2420 windows->command.screen,(unsigned int) (CWX | CWY),
2423 if (windows->widget.geometry == (char *) NULL)
2424 if (windows->widget.mapped == MagickFalse)
2427 event.xconfigure.x+event.xconfigure.width/10;
2429 event.xconfigure.y+event.xconfigure.height/10;
2430 XConstrainWindowPosition(display,&windows->widget);
2431 window_changes.x=windows->widget.x;
2432 window_changes.y=windows->widget.y;
2433 (void) XReconfigureWMWindow(display,windows->widget.id,
2434 windows->widget.screen,(unsigned int) (CWX | CWY),
2439 Image window has a new configuration.
2441 windows->image.width=(unsigned int) event.xconfigure.width;
2442 windows->image.height=(unsigned int) event.xconfigure.height;
2445 if (event.xconfigure.window == windows->icon.id)
2448 Icon window has a new configuration.
2450 windows->icon.width=(unsigned int) event.xconfigure.width;
2451 windows->icon.height=(unsigned int) event.xconfigure.height;
2459 Group leader has exited.
2461 if (display_image->debug != MagickFalse)
2462 (void) LogMagickEvent(X11Event,GetMagickModule(),
2463 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2464 if (event.xdestroywindow.window == windows->group_leader.id)
2474 Selectively install colormap.
2476 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2477 if (event.xcrossing.mode != NotifyUngrab)
2478 XInstallColormap(display,map_info->colormap);
2483 if (display_image->debug != MagickFalse)
2484 (void) LogMagickEvent(X11Event,GetMagickModule(),
2485 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2486 event.xexpose.width,event.xexpose.height,event.xexpose.x,
2489 Repaint windows that are now exposed.
2491 if (event.xexpose.window == windows->image.id)
2493 windows->image.pixmap=windows->image.pixmaps[scene];
2494 windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2495 XRefreshWindow(display,&windows->image,&event);
2498 if (event.xexpose.window == windows->icon.id)
2499 if (event.xexpose.count == 0)
2501 XRefreshWindow(display,&windows->icon,&event);
2512 Respond to a user key press.
2514 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2515 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2516 *(command+length)='\0';
2517 if (display_image->debug != MagickFalse)
2518 (void) LogMagickEvent(X11Event,GetMagickModule(),
2519 "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2520 command_type=NullCommand;
2525 if ((event.xkey.state & ControlMask) == MagickFalse)
2527 command_type=OpenCommand;
2532 command_type=StepBackwardCommand;
2537 command_type=StepForwardCommand;
2542 command_type=FasterCommand;
2547 command_type=SlowerCommand;
2552 command_type=HelpCommand;
2557 command_type=BrowseDocumentationCommand;
2562 command_type=InfoCommand;
2568 command_type=QuitCommand;
2574 if (command_type != NullCommand)
2575 nexus=XMagickCommand(display,resource_info,windows,
2576 command_type,&image,&state,exception);
2582 Respond to a user key release.
2584 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2585 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2586 if (display_image->debug != MagickFalse)
2587 (void) LogMagickEvent(X11Event,GetMagickModule(),
2588 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2594 Selectively uninstall colormap.
2596 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2597 if (event.xcrossing.mode != NotifyUngrab)
2598 XUninstallColormap(display,map_info->colormap);
2603 if (display_image->debug != MagickFalse)
2604 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2606 if (event.xmap.window == windows->backdrop.id)
2608 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2610 windows->backdrop.mapped=MagickTrue;
2613 if (event.xmap.window == windows->image.id)
2615 if (windows->backdrop.id != (Window) NULL)
2616 (void) XInstallColormap(display,map_info->colormap);
2617 if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2619 if (LocaleCompare(display_image->filename,"LOGO") == 0)
2620 nexus=XMagickCommand(display,resource_info,windows,
2621 OpenCommand,&image,&state,exception);
2625 windows->image.mapped=MagickTrue;
2628 if (event.xmap.window == windows->info.id)
2630 windows->info.mapped=MagickTrue;
2633 if (event.xmap.window == windows->icon.id)
2636 Create an icon image.
2638 XMakeStandardColormap(display,icon_visual,icon_resources,
2639 display_image,icon_map,icon_pixel,exception);
2640 (void) XMakeImage(display,icon_resources,&windows->icon,
2641 display_image,windows->icon.width,windows->icon.height,
2643 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2644 windows->icon.pixmap);
2645 (void) XClearWindow(display,windows->icon.id);
2646 (void) XWithdrawWindow(display,windows->info.id,
2647 windows->info.screen);
2648 windows->icon.mapped=MagickTrue;
2651 if (event.xmap.window == windows->command.id)
2653 windows->command.mapped=MagickTrue;
2656 if (event.xmap.window == windows->popup.id)
2658 windows->popup.mapped=MagickTrue;
2661 if (event.xmap.window == windows->widget.id)
2663 windows->widget.mapped=MagickTrue;
2670 (void) XRefreshKeyboardMapping(&event.xmapping);
2675 case PropertyNotify:
2691 if (display_image->debug != MagickFalse)
2692 (void) LogMagickEvent(X11Event,GetMagickModule(),
2693 "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2694 event.xproperty.window,(unsigned long) event.xproperty.atom,
2695 event.xproperty.state);
2696 if (event.xproperty.atom != windows->im_remote_command)
2699 Display image named by the remote command protocol.
2701 status=XGetWindowProperty(display,event.xproperty.window,
2702 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
2703 AnyPropertyType,&type,&format,&length,&after,&data);
2704 if ((status != Success) || (length == 0))
2706 (void) CopyMagickString(resource_info->image_info->filename,
2707 (char *) data,MaxTextExtent);
2708 nexus=ReadImage(resource_info->image_info,exception);
2709 CatchException(exception);
2710 if (nexus != (Image *) NULL)
2712 (void) XFree((void *) data);
2715 case ReparentNotify:
2717 if (display_image->debug != MagickFalse)
2718 (void) LogMagickEvent(X11Event,GetMagickModule(),
2719 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2720 event.xreparent.window);
2725 if (display_image->debug != MagickFalse)
2726 (void) LogMagickEvent(X11Event,GetMagickModule(),
2727 "Unmap Notify: 0x%lx",event.xunmap.window);
2728 if (event.xunmap.window == windows->backdrop.id)
2730 windows->backdrop.mapped=MagickFalse;
2733 if (event.xunmap.window == windows->image.id)
2735 windows->image.mapped=MagickFalse;
2738 if (event.xunmap.window == windows->info.id)
2740 windows->info.mapped=MagickFalse;
2743 if (event.xunmap.window == windows->icon.id)
2745 if (map_info->colormap == icon_map->colormap)
2746 XConfigureImageColormap(display,resource_info,windows,
2747 display_image,exception);
2748 (void) XFreeStandardColormap(display,icon_visual,icon_map,
2750 windows->icon.mapped=MagickFalse;
2753 if (event.xunmap.window == windows->command.id)
2755 windows->command.mapped=MagickFalse;
2758 if (event.xunmap.window == windows->popup.id)
2760 if (windows->backdrop.id != (Window) NULL)
2761 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2763 windows->popup.mapped=MagickFalse;
2766 if (event.xunmap.window == windows->widget.id)
2768 if (windows->backdrop.id != (Window) NULL)
2769 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2771 windows->widget.mapped=MagickFalse;
2778 if (display_image->debug != MagickFalse)
2779 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2785 while (!(state & ExitState));
2786 image_list=(Image **) RelinquishMagickMemory(image_list);
2787 images=DestroyImageList(images);
2788 if ((windows->visual_info->klass == GrayScale) ||
2789 (windows->visual_info->klass == PseudoColor) ||
2790 (windows->visual_info->klass == DirectColor))
2795 if (windows->info.mapped)
2796 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2797 if (windows->command.mapped)
2798 (void) XWithdrawWindow(display,windows->command.id,
2799 windows->command.screen);
2801 if (resource_info->backdrop == MagickFalse)
2802 if (windows->backdrop.mapped)
2804 (void) XWithdrawWindow(display,windows->backdrop.id,\
2805 windows->backdrop.screen);
2806 (void) XDestroyWindow(display,windows->backdrop.id);
2807 windows->backdrop.id=(Window) NULL;
2808 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2809 (void) XDestroyWindow(display,windows->image.id);
2810 windows->image.id=(Window) NULL;
2812 XSetCursorState(display,windows,MagickTrue);
2813 XCheckRefreshWindows(display,windows);
2814 for (scene=1; scene < (ssize_t) number_scenes; scene++)
2816 if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2817 (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2818 windows->image.pixmaps[scene]=(Pixmap) NULL;
2819 if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2820 (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2821 windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2823 XSetCursorState(display,windows,MagickFalse);
2824 windows->image.pixmaps=(Pixmap *)
2825 RelinquishMagickMemory(windows->image.pixmaps);
2826 windows->image.matte_pixmaps=(Pixmap *)
2827 RelinquishMagickMemory(windows->image.matte_pixmaps);
2828 if (nexus == (Image *) NULL)
2833 if (windows->image.mapped != MagickFalse)
2834 (void) XWithdrawWindow(display,windows->image.id,windows->image.screen); XDelay(display,SuspendTime);
2835 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2836 if (resource_info->map_type == (char *) NULL)
2837 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2838 DestroyXResources();
2840 (void) XSync(display,MagickFalse);
2842 Restore our progress monitor and warning handlers.
2844 (void) SetErrorHandler(warning_handler);
2845 (void) SetWarningHandler(warning_handler);
2847 Change to home directory.
2849 directory=getcwd(working_directory,MaxTextExtent);
2851 status=chdir(resource_info->home_directory);
2853 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2854 "UnableToOpenFile","%s",resource_info->home_directory);
2859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2863 + X S a v e I m a g e %
2867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2869 % XSaveImage() saves an image to a file.
2871 % The format of the XSaveImage method is:
2873 % MagickBooleanType XSaveImage(Display *display,
2874 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2875 % ExceptionInfo *exception)
2877 % A description of each parameter follows:
2879 % o status: Method XSaveImage return True if the image is
2880 % written. False is returned is there is a memory shortage or if the
2881 % image fails to write.
2883 % o display: Specifies a connection to an X server; returned from
2886 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2888 % o windows: Specifies a pointer to a XWindows structure.
2890 % o image: the image.
2893 static MagickBooleanType XSaveImage(Display *display,
2894 XResourceInfo *resource_info,XWindows *windows,Image *image,
2895 ExceptionInfo *exception)
2898 filename[MaxTextExtent];
2907 Request file name from user.
2909 if (resource_info->write_filename != (char *) NULL)
2910 (void) CopyMagickString(filename,resource_info->write_filename,
2915 path[MaxTextExtent];
2920 GetPathComponent(image->filename,HeadPath,path);
2921 GetPathComponent(image->filename,TailPath,filename);
2924 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
2925 "UnableToOpenFile","%s",path);
2927 XFileBrowserWidget(display,windows,"Save",filename);
2928 if (*filename == '\0')
2930 if (IsPathAccessible(filename) != MagickFalse)
2936 File exists-- seek user's permission before overwriting.
2938 status=XConfirmWidget(display,windows,"Overwrite",filename);
2942 image_info=CloneImageInfo(resource_info->image_info);
2943 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
2944 (void) SetImageInfo(image_info,1,exception);
2945 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2946 (LocaleCompare(image_info->magick,"JPG") == 0))
2949 quality[MaxTextExtent];
2955 Request JPEG quality from user.
2957 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
2958 image_info->quality);
2959 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2961 if (*quality == '\0')
2963 image->quality=StringToUnsignedLong(quality);
2964 image_info->interlace=status != MagickFalse ? NoInterlace :
2967 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2968 (LocaleCompare(image_info->magick,"PDF") == 0) ||
2969 (LocaleCompare(image_info->magick,"PS") == 0) ||
2970 (LocaleCompare(image_info->magick,"PS2") == 0))
2973 geometry[MaxTextExtent];
2976 Request page geometry from user.
2978 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2979 if (LocaleCompare(image_info->magick,"PDF") == 0)
2980 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
2981 if (image_info->page != (char *) NULL)
2982 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
2983 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2984 "Select page geometry:",geometry);
2985 if (*geometry != '\0')
2986 image_info->page=GetPageGeometry(geometry);
2991 image=GetFirstImageInList(image);
2992 status=WriteImages(image_info,image,filename,exception);
2993 if (status != MagickFalse)
2994 image->taint=MagickFalse;
2995 image_info=DestroyImageInfo(image_info);
2996 XSetCursorState(display,windows,MagickFalse);
2997 return(status != 0 ? MagickTrue : MagickFalse);
3002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3006 + A n i m a t e I m a g e s %
3010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3012 % AnimateImages() repeatedly displays an image sequence to any X window
3013 % screen. It returns a value other than 0 if successful. Check the
3014 % exception member of image to determine the reason for any failure.
3016 % The format of the AnimateImages method is:
3018 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3021 % A description of each parameter follows:
3023 % o image_info: the image info.
3025 % o image: the image.
3027 % o exception: return any errors or warnings in this structure.
3030 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
3031 Image *image,ExceptionInfo *exception)
3033 assert(image_info != (const ImageInfo *) NULL);
3034 assert(image_info->signature == MagickSignature);
3035 assert(image != (Image *) NULL);
3036 assert(image->signature == MagickSignature);
3037 if (image->debug != MagickFalse)
3038 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3039 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
3040 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
3041 return(MagickFalse);