2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % DDDD IIIII SSSSS PPPP L AAA Y Y %
7 % D D I SS P P L A A Y Y %
8 % D D I SSS PPPP L AAAAA Y %
10 % DDDD IIIII SSSSS P LLLLL A A Y %
13 % MagickCore Methods to Interactively Display and Edit an Image %
20 % Copyright 1999-2010 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 "magick/studio.h"
43 #include "magick/artifact.h"
44 #include "magick/blob.h"
45 #include "magick/cache.h"
46 #include "magick/client.h"
47 #include "magick/color.h"
48 #include "magick/colorspace.h"
49 #include "magick/composite.h"
50 #include "magick/constitute.h"
51 #include "magick/decorate.h"
52 #include "magick/delegate.h"
53 #include "magick/display.h"
54 #include "magick/display-private.h"
55 #include "magick/draw.h"
56 #include "magick/effect.h"
57 #include "magick/enhance.h"
58 #include "magick/exception.h"
59 #include "magick/exception-private.h"
60 #include "magick/fx.h"
61 #include "magick/geometry.h"
62 #include "magick/image.h"
63 #include "magick/image-private.h"
64 #include "magick/list.h"
65 #include "magick/log.h"
66 #include "magick/magick.h"
67 #include "magick/memory_.h"
68 #include "magick/monitor.h"
69 #include "magick/monitor-private.h"
70 #include "magick/montage.h"
71 #include "magick/option.h"
72 #include "magick/paint.h"
73 #include "magick/pixel.h"
74 #include "magick/pixel-private.h"
75 #include "magick/PreRvIcccm.h"
76 #include "magick/property.h"
77 #include "magick/quantum.h"
78 #include "magick/resize.h"
79 #include "magick/resource_.h"
80 #include "magick/shear.h"
81 #include "magick/segment.h"
82 #include "magick/string_.h"
83 #include "magick/string-private.h"
84 #include "magick/transform.h"
85 #include "magick/threshold.h"
86 #include "magick/utility.h"
87 #include "magick/version.h"
88 #include "magick/widget.h"
89 #include "magick/xwindow-private.h"
91 #if defined(MAGICKCORE_X11_DELEGATE)
95 #define MaxColors MagickMin(windows->visual_info->colormap_size,256L)
98 Constant declarations.
100 static const unsigned char
103 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
131 Help widget declarations.
134 *ImageAnnotateHelp[] =
136 "In annotate mode, the Command widget has these options:",
186 "Choose a font name from the Font Name sub-menu. Additional",
187 "font names can be specified with the font browser. You can",
188 "change the menu names by setting the X resources font1",
191 "Choose a font color from the Font Color sub-menu.",
192 "Additional font colors can be specified with the color",
193 "browser. You can change the menu colors by setting the X",
194 "resources pen1 through pen9.",
196 "If you select the color browser and press Grab, you can",
197 "choose the font color by moving the pointer to the desired",
198 "color on the screen and press any button.",
200 "If you choose to rotate the text, choose Rotate Text from the",
201 "menu and select an angle. Typically you will only want to",
202 "rotate one line of text at a time. Depending on the angle you",
203 "choose, subsequent lines may end up overwriting each other.",
205 "Choosing a font and its color is optional. The default font",
206 "is fixed and the default color is black. However, you must",
207 "choose a location to begin entering text and press button 1.",
208 "An underscore character will appear at the location of the",
209 "pointer. The cursor changes to a pencil to indicate you are",
210 "in text mode. To exit immediately, press Dismiss.",
212 "In text mode, any key presses will display the character at",
213 "the location of the underscore and advance the underscore",
214 "cursor. Enter your text and once completed press Apply to",
215 "finish your image annotation. To correct errors press BACK",
216 "SPACE. To delete an entire line of text, press DELETE. Any",
217 "text that exceeds the boundaries of the image window is",
218 "automagically continued onto the next line.",
220 "The actual color you request for the font is saved in the",
221 "image. However, the color that appears in your image window",
222 "may be different. For example, on a monochrome screen the",
223 "text will appear black or white even if you choose the color",
224 "red as the font color. However, the image saved to a file",
225 "with -write is written with red lettering. To assure the",
226 "correct color text in the final image, any PseudoClass image",
227 "is promoted to DirectClass (see miff(5)). To force a",
228 "PseudoClass image to remain PseudoClass, use -colors.",
233 "In chop mode, the Command widget has these options:",
241 "If the you choose the horizontal direction (this the",
242 "default), the area of the image between the two horizontal",
243 "endpoints of the chop line is removed. Otherwise, the area",
244 "of the image between the two vertical endpoints of the chop",
247 "Select a location within the image window to begin your chop,",
248 "press and hold any button. Next, move the pointer to",
249 "another location in the image. As you move a line will",
250 "connect the initial location and the pointer. When you",
251 "release the button, the area within the image to chop is",
252 "determined by which direction you choose from the Command",
255 "To cancel the image chopping, move the pointer back to the",
256 "starting point of the line and release the button.",
259 *ImageColorEditHelp[] =
261 "In color edit mode, the Command widget has these options:",
302 "Choose a color editing method from the Method sub-menu",
303 "of the Command widget. The point method recolors any pixel",
304 "selected with the pointer until the button is released. The",
305 "replace method recolors any pixel that matches the color of",
306 "the pixel you select with a button press. Floodfill recolors",
307 "any pixel that matches the color of the pixel you select with",
308 "a button press and is a neighbor. Whereas filltoborder recolors",
309 "any neighbor pixel that is not the border color. Finally reset",
310 "changes the entire image to the designated color.",
312 "Next, choose a pixel color from the Pixel Color sub-menu.",
313 "Additional pixel colors can be specified with the color",
314 "browser. You can change the menu colors by setting the X",
315 "resources pen1 through pen9.",
317 "Now press button 1 to select a pixel within the image window",
318 "to change its color. Additional pixels may be recolored as",
319 "prescribed by the method you choose.",
321 "If the Magnify widget is mapped, it can be helpful in positioning",
322 "your pointer within the image (refer to button 2).",
324 "The actual color you request for the pixels is saved in the",
325 "image. However, the color that appears in your image window",
326 "may be different. For example, on a monochrome screen the",
327 "pixel will appear black or white even if you choose the",
328 "color red as the pixel color. However, the image saved to a",
329 "file with -write is written with red pixels. To assure the",
330 "correct color text in the final image, any PseudoClass image",
331 "is promoted to DirectClass (see miff(5)). To force a",
332 "PseudoClass image to remain PseudoClass, use -colors.",
335 *ImageCompositeHelp[] =
337 "First a widget window is displayed requesting you to enter an",
338 "image name. Press Composite, Grab or type a file name.",
339 "Press Cancel if you choose not to create a composite image.",
340 "When you choose Grab, move the pointer to the desired window",
341 "and press any button.",
343 "If the Composite image does not have any matte information,",
344 "you are informed and the file browser is displayed again.",
345 "Enter the name of a mask image. The image is typically",
346 "grayscale and the same size as the composite image. If the",
347 "image is not grayscale, it is converted to grayscale and the",
348 "resulting intensities are used as matte information.",
350 "A small window appears showing the location of the cursor in",
351 "the image window. You are now in composite mode. To exit",
352 "immediately, press Dismiss. In composite mode, the Command",
353 "widget has these options:",
379 "Choose a composite operation from the Operators sub-menu of",
380 "the Command widget. How each operator behaves is described",
381 "below. Image window is the image currently displayed on",
382 "your X server and image is the image obtained with the File",
385 "Over The result is the union of the two image shapes,",
386 " with image obscuring image window in the region of",
389 "In The result is simply image cut by the shape of",
390 " image window. None of the image data of image",
391 " window is in the result.",
393 "Out The resulting image is image with the shape of",
394 " image window cut out.",
396 "Atop The result is the same shape as image image window,",
397 " with image obscuring image window where the image",
398 " shapes overlap. Note this differs from over",
399 " because the portion of image outside image window's",
400 " shape does not appear in the result.",
402 "Xor The result is the image data from both image and",
403 " image window that is outside the overlap region.",
404 " The overlap region is blank.",
406 "Plus The result is just the sum of the image data.",
407 " Output values are cropped to QuantumRange (no overflow).",
409 "Minus The result of image - image window, with underflow",
412 "Add The result of image + image window, with overflow",
413 " wrapping around (mod 256).",
415 "Subtract The result of image - image window, with underflow",
416 " wrapping around (mod 256). The add and subtract",
417 " operators can be used to perform reversible",
421 " The result of abs(image - image window). This",
422 " useful for comparing two very similar images.",
425 " The result of image * image window. This",
426 " useful for the creation of drop-shadows.",
428 "Bumpmap The result of surface normals from image * image",
431 "Copy The resulting image is image window replaced with",
432 " image. Here the matte information is ignored.",
434 "CopyRed The red layer of the image window is replace with",
435 " the red layer of the image. The other layers are",
439 " The green layer of the image window is replace with",
440 " the green layer of the image. The other layers are",
443 "CopyBlue The blue layer of the image window is replace with",
444 " the blue layer of the image. The other layers are",
448 " The matte layer of the image window is replace with",
449 " the matte layer of the image. The other layers are",
452 "The image compositor requires a matte, or alpha channel in",
453 "the image for some operations. This extra channel usually",
454 "defines a mask which represents a sort of a cookie-cutter",
455 "for the image. This the case when matte is opaque (full",
456 "coverage) for pixels inside the shape, zero outside, and",
457 "between 0 and QuantumRange on the boundary. If image does not",
458 "have a matte channel, it is initialized with 0 for any pixel",
459 "matching in color to pixel location (0,0), otherwise QuantumRange.",
461 "If you choose Dissolve, the composite operator becomes Over. The",
462 "image matte channel percent transparency is initialized to factor.",
463 "The image window is initialized to (100-factor). Where factor is the",
464 "value you specify in the Dialog widget.",
466 "Displace shifts the image pixels as defined by a displacement",
467 "map. With this option, image is used as a displacement map.",
468 "Black, within the displacement map, is a maximum positive",
469 "displacement. White is a maximum negative displacement and",
470 "middle gray is neutral. The displacement is scaled to determine",
471 "the pixel shift. By default, the displacement applies in both the",
472 "horizontal and vertical directions. However, if you specify a mask,",
473 "image is the horizontal X displacement and mask the vertical Y",
476 "Note that matte information for image window is not retained",
477 "for colormapped X server visuals (e.g. StaticColor,",
478 "StaticColor, GrayScale, PseudoColor). Correct compositing",
479 "behavior may require a TrueColor or DirectColor visual or a",
480 "Standard Colormap.",
482 "Choosing a composite operator is optional. The default",
483 "operator is replace. However, you must choose a location to",
484 "composite your image and press button 1. Press and hold the",
485 "button before releasing and an outline of the image will",
486 "appear to help you identify your location.",
488 "The actual colors of the composite image is saved. However,",
489 "the color that appears in image window may be different.",
490 "For example, on a monochrome screen image window will appear",
491 "black or white even though your composited image may have",
492 "many colors. If the image is saved to a file it is written",
493 "with the correct colors. To assure the correct colors are",
494 "saved in the final image, any PseudoClass image is promoted",
495 "to DirectClass (see miff(5)). To force a PseudoClass image",
496 "to remain PseudoClass, use -colors.",
501 "In cut mode, the Command widget has these options:",
506 "To define a cut region, press button 1 and drag. The",
507 "cut region is defined by a highlighted rectangle that",
508 "expands or contracts as it follows the pointer. Once you",
509 "are satisfied with the cut region, release the button.",
510 "You are now in rectify mode. In rectify mode, the Command",
511 "widget has these options:",
517 "You can make adjustments by moving the pointer to one of the",
518 "cut rectangle corners, pressing a button, and dragging.",
519 "Finally, press Cut to commit your copy region. To",
520 "exit without cutting the image, press Dismiss.",
525 "In copy mode, the Command widget has these options:",
530 "To define a copy region, press button 1 and drag. The",
531 "copy region is defined by a highlighted rectangle that",
532 "expands or contracts as it follows the pointer. Once you",
533 "are satisfied with the copy region, release the button.",
534 "You are now in rectify mode. In rectify mode, the Command",
535 "widget has these options:",
541 "You can make adjustments by moving the pointer to one of the",
542 "copy rectangle corners, pressing a button, and dragging.",
543 "Finally, press Copy to commit your copy region. To",
544 "exit without copying the image, press Dismiss.",
549 "In crop mode, the Command widget has these options:",
554 "To define a cropping region, press button 1 and drag. The",
555 "cropping region is defined by a highlighted rectangle that",
556 "expands or contracts as it follows the pointer. Once you",
557 "are satisfied with the cropping region, release the button.",
558 "You are now in rectify mode. In rectify mode, the Command",
559 "widget has these options:",
565 "You can make adjustments by moving the pointer to one of the",
566 "cropping rectangle corners, pressing a button, and dragging.",
567 "Finally, press Crop to commit your cropping region. To",
568 "exit without cropping the image, press Dismiss.",
573 "The cursor changes to a crosshair to indicate you are in",
574 "draw mode. To exit immediately, press Dismiss. In draw mode,",
575 "the Command widget has these options:",
620 "Choose a drawing primitive from the Element sub-menu.",
622 "Choose a color from the Color sub-menu. Additional",
623 "colors can be specified with the color browser.",
625 "If you choose the color browser and press Grab, you can",
626 "select the color by moving the pointer to the desired",
627 "color on the screen and press any button. The transparent",
628 "color updates the image matte channel and is useful for",
629 "image compositing.",
631 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
632 "Additional stipples can be specified with the file browser.",
633 "Stipples obtained from the file browser must be on disk in the",
634 "X11 bitmap format.",
636 "Choose a width, if appropriate, from the Width sub-menu. To",
637 "choose a specific width select the Dialog widget.",
639 "Choose a point in the Image window and press button 1 and",
640 "hold. Next, move the pointer to another location in the",
641 "image. As you move, a line connects the initial location and",
642 "the pointer. When you release the button, the image is",
643 "updated with the primitive you just drew. For polygons, the",
644 "image is updated when you press and release the button without",
645 "moving the pointer.",
647 "To cancel image drawing, move the pointer back to the",
648 "starting point of the line and release the button.",
654 " The effects of each button press is described below. Three",
655 " buttons are required. If you have a two button mouse,",
656 " button 1 and 3 are returned. Press ALT and button 3 to",
657 " simulate button 2.",
659 " 1 Press this button to map or unmap the Command widget.",
661 " 2 Press and drag to define a region of the image to",
664 " 3 Press and drag to choose from a select set of commands.",
665 " This button behaves differently if the image being",
666 " displayed is a visual image directory. Here, choose a",
667 " particular tile of the directory and press this button and",
668 " drag to select a command from a pop-up menu. Choose from",
669 " these menu items:",
677 " If you choose Open, the image represented by the tile is",
678 " displayed. To return to the visual image directory, choose",
679 " Next from the Command widget. Next and Former moves to the",
680 " next or former image respectively. Choose Delete to delete",
681 " a particular image tile. Finally, choose Update to",
682 " synchronize all the image tiles with their respective",
686 " The Command widget lists a number of sub-menus and commands.",
698 " Visual Directory...",
732 " Contrast Stretch...",
733 " Sigmoidal Contrast...",
761 " Charcoal Drawing...",
772 " Region of Interest...",
784 " Browse Documentation",
787 " Menu items with a indented triangle have a sub-menu. They",
788 " are represented above as the indented items. To access a",
789 " sub-menu item, move the pointer to the appropriate menu and",
790 " press a button and drag. When you find the desired sub-menu",
791 " item, release the button and the command is executed. Move",
792 " the pointer away from the sub-menu if you decide not to",
793 " execute a particular command.",
795 "KEYBOARD ACCELERATORS",
796 " Accelerators are one or two key presses that effect a",
797 " particular command. The keyboard accelerators that",
798 " display(1) understands is:",
800 " Ctl+O Press to open an image from a file.",
802 " space Press to display the next image.",
804 " If the image is a multi-paged document such as a Postscript",
805 " document, you can skip ahead several pages by preceding",
806 " this command with a number. For example to display the",
807 " third page beyond the current page, press 3<space>.",
809 " backspace Press to display the former image.",
811 " If the image is a multi-paged document such as a Postscript",
812 " document, you can skip behind several pages by preceding",
813 " this command with a number. For example to display the",
814 " third page preceding the current page, press 3<backspace>.",
816 " Ctl+S Press to write the image to a file.",
818 " Ctl+P Press to print the image to a Postscript printer.",
820 " Ctl+D Press to delete an image file.",
822 " Ctl+N Press to create a blank canvas.",
824 " Ctl+Q Press to discard all images and exit program.",
826 " Ctl+Z Press to undo last image transformation.",
828 " Ctl+R Press to redo last image transformation.",
830 " Ctl+X Press to cut a region of the image.",
832 " Ctl+C Press to copy a region of the image.",
834 " Ctl+V Press to paste a region to the image.",
836 " < Press to half the image size.",
838 " - Press to return to the original image size.",
840 " > Press to double the image size.",
842 " % Press to resize the image to a width and height you",
845 "Cmd-A Press to make any image transformations permanent."
847 " By default, any image size transformations are applied",
848 " to the original image to create the image displayed on",
849 " the X server. However, the transformations are not",
850 " permanent (i.e. the original image does not change",
851 " size only the X image does). For example, if you",
852 " press > the X image will appear to double in size,",
853 " but the original image will in fact remain the same size.",
854 " To force the original image to double in size, press >",
855 " followed by Cmd-A.",
857 " @ Press to refresh the image window.",
859 " C Press to cut out a rectangular region of the image.",
861 " [ Press to chop the image.",
863 " H Press to flop image in the horizontal direction.",
865 " V Press to flip image in the vertical direction.",
867 " / Press to rotate the image 90 degrees clockwise.",
869 " \\ Press to rotate the image 90 degrees counter-clockwise.",
871 " * Press to rotate the image the number of degrees you",
874 " S Press to shear the image the number of degrees you",
877 " R Press to roll the image.",
879 " T Press to trim the image edges.",
881 " Shft-H Press to vary the image hue.",
883 " Shft-S Press to vary the color saturation.",
885 " Shft-L Press to vary the color brightness.",
887 " Shft-G Press to gamma correct the image.",
889 " Shft-C Press to sharpen the image contrast.",
891 " Shft-Z Press to dull the image contrast.",
893 " = Press to perform histogram equalization on the image.",
895 " Shft-N Press to perform histogram normalization on the image.",
897 " Shft-~ Press to negate the colors of the image.",
899 " . Press to convert the image colors to gray.",
901 " Shft-# Press to set the maximum number of unique colors in the",
904 " F2 Press to reduce the speckles in an image.",
906 " F3 Press to eliminate peak noise from an image.",
908 " F4 Press to add noise to an image.",
910 " F5 Press to sharpen an image.",
912 " F6 Press to delete an image file.",
914 " F7 Press to threshold the image.",
916 " F8 Press to detect edges within an image.",
918 " F9 Press to emboss an image.",
920 " F10 Press to displace pixels by a random amount.",
922 " F11 Press to negate all pixels above the threshold level.",
924 " F12 Press to shade the image using a distant light source.",
926 " F13 Press to lighten or darken image edges to create a 3-D effect.",
928 " F14 Press to segment the image by color.",
930 " Meta-S Press to swirl image pixels about the center.",
932 " Meta-I Press to implode image pixels about the center.",
934 " Meta-W Press to alter an image along a sine wave.",
936 " Meta-P Press to simulate an oil painting.",
938 " Meta-C Press to simulate a charcoal drawing.",
940 " Alt-A Press to annotate the image with text.",
942 " Alt-D Press to draw on an image.",
944 " Alt-P Press to edit an image pixel color.",
946 " Alt-M Press to edit the image matte information.",
948 " Alt-V Press to composite the image with another.",
950 " Alt-B Press to add a border to the image.",
952 " Alt-F Press to add an ornamental border to the image.",
955 " Press to add an image comment.",
957 " Ctl-A Press to apply image processing techniques to a region",
960 " Shft-? Press to display information about the image.",
962 " Shft-+ Press to map the zoom image window.",
964 " Shft-P Press to preview an image enhancement, effect, or f/x.",
966 " F1 Press to display helpful information about display(1).",
968 " Find Press to browse documentation about ImageMagick.",
970 " 1-9 Press to change the level of magnification.",
972 " Use the arrow keys to move the image one pixel up, down,",
973 " left, or right within the magnify window. Be sure to first",
974 " map the magnify window by pressing button 2.",
976 " Press ALT and one of the arrow keys to trim off one pixel",
977 " from any side of the image.",
980 *ImageMatteEditHelp[] =
982 "Matte information within an image is useful for some",
983 "operations such as image compositing (See IMAGE",
984 "COMPOSITING). This extra channel usually defines a mask",
985 "which represents a sort of a cookie-cutter for the image.",
986 "This the case when matte is opaque (full coverage) for",
987 "pixels inside the shape, zero outside, and between 0 and",
988 "QuantumRange on the boundary.",
990 "A small window appears showing the location of the cursor in",
991 "the image window. You are now in matte edit mode. To exit",
992 "immediately, press Dismiss. In matte edit mode, the Command",
993 "widget has these options:",
1027 "Choose a matte editing method from the Method sub-menu of",
1028 "the Command widget. The point method changes the matte value",
1029 "of any pixel selected with the pointer until the button is",
1030 "is released. The replace method changes the matte value of",
1031 "any pixel that matches the color of the pixel you select with",
1032 "a button press. Floodfill changes the matte value of any pixel",
1033 "that matches the color of the pixel you select with a button",
1034 "press and is a neighbor. Whereas filltoborder changes the matte",
1035 "value any neighbor pixel that is not the border color. Finally",
1036 "reset changes the entire image to the designated matte value.",
1038 "Choose Matte Value and pick Opaque or Transarent. For other values",
1039 "select the Dialog entry. Here a dialog appears requesting a matte",
1040 "value. The value you select is assigned as the opacity value of the",
1041 "selected pixel or pixels.",
1043 "Now, press any button to select a pixel within the image",
1044 "window to change its matte value.",
1046 "If the Magnify widget is mapped, it can be helpful in positioning",
1047 "your pointer within the image (refer to button 2).",
1049 "Matte information is only valid in a DirectClass image.",
1050 "Therefore, any PseudoClass image is promoted to DirectClass",
1051 "(see miff(5)). Note that matte information for PseudoClass",
1052 "is not retained for colormapped X server visuals (e.g.",
1053 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1054 "immediately save your image to a file (refer to Write).",
1055 "Correct matte editing behavior may require a TrueColor or",
1056 "DirectColor visual or a Standard Colormap.",
1061 "When an image exceeds the width or height of the X server",
1062 "screen, display maps a small panning icon. The rectangle",
1063 "within the panning icon shows the area that is currently",
1064 "displayed in the image window. To pan about the image,",
1065 "press any button and drag the pointer within the panning",
1066 "icon. The pan rectangle moves with the pointer and the",
1067 "image window is updated to reflect the location of the",
1068 "rectangle within the panning icon. When you have selected",
1069 "the area of the image you wish to view, release the button.",
1071 "Use the arrow keys to pan the image one pixel up, down,",
1072 "left, or right within the image window.",
1074 "The panning icon is withdrawn if the image becomes smaller",
1075 "than the dimensions of the X server screen.",
1080 "A small window appears showing the location of the cursor in",
1081 "the image window. You are now in paste mode. To exit",
1082 "immediately, press Dismiss. In paste mode, the Command",
1083 "widget has these options:",
1100 "Choose a composite operation from the Operators sub-menu of",
1101 "the Command widget. How each operator behaves is described",
1102 "below. Image window is the image currently displayed on",
1103 "your X server and image is the image obtained with the File",
1106 "Over The result is the union of the two image shapes,",
1107 " with image obscuring image window in the region of",
1110 "In The result is simply image cut by the shape of",
1111 " image window. None of the image data of image",
1112 " window is in the result.",
1114 "Out The resulting image is image with the shape of",
1115 " image window cut out.",
1117 "Atop The result is the same shape as image image window,",
1118 " with image obscuring image window where the image",
1119 " shapes overlap. Note this differs from over",
1120 " because the portion of image outside image window's",
1121 " shape does not appear in the result.",
1123 "Xor The result is the image data from both image and",
1124 " image window that is outside the overlap region.",
1125 " The overlap region is blank.",
1127 "Plus The result is just the sum of the image data.",
1128 " Output values are cropped to QuantumRange (no overflow).",
1129 " This operation is independent of the matte",
1132 "Minus The result of image - image window, with underflow",
1133 " cropped to zero.",
1135 "Add The result of image + image window, with overflow",
1136 " wrapping around (mod 256).",
1138 "Subtract The result of image - image window, with underflow",
1139 " wrapping around (mod 256). The add and subtract",
1140 " operators can be used to perform reversible",
1141 " transformations.",
1144 " The result of abs(image - image window). This",
1145 " useful for comparing two very similar images.",
1147 "Copy The resulting image is image window replaced with",
1148 " image. Here the matte information is ignored.",
1150 "CopyRed The red layer of the image window is replace with",
1151 " the red layer of the image. The other layers are",
1155 " The green layer of the image window is replace with",
1156 " the green layer of the image. The other layers are",
1159 "CopyBlue The blue layer of the image window is replace with",
1160 " the blue layer of the image. The other layers are",
1164 " The matte layer of the image window is replace with",
1165 " the matte layer of the image. The other layers are",
1168 "The image compositor requires a matte, or alpha channel in",
1169 "the image for some operations. This extra channel usually",
1170 "defines a mask which represents a sort of a cookie-cutter",
1171 "for the image. This the case when matte is opaque (full",
1172 "coverage) for pixels inside the shape, zero outside, and",
1173 "between 0 and QuantumRange on the boundary. If image does not",
1174 "have a matte channel, it is initialized with 0 for any pixel",
1175 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1177 "Note that matte information for image window is not retained",
1178 "for colormapped X server visuals (e.g. StaticColor,",
1179 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1180 "behavior may require a TrueColor or DirectColor visual or a",
1181 "Standard Colormap.",
1183 "Choosing a composite operator is optional. The default",
1184 "operator is replace. However, you must choose a location to",
1185 "paste your image and press button 1. Press and hold the",
1186 "button before releasing and an outline of the image will",
1187 "appear to help you identify your location.",
1189 "The actual colors of the pasted image is saved. However,",
1190 "the color that appears in image window may be different.",
1191 "For example, on a monochrome screen image window will appear",
1192 "black or white even though your pasted image may have",
1193 "many colors. If the image is saved to a file it is written",
1194 "with the correct colors. To assure the correct colors are",
1195 "saved in the final image, any PseudoClass image is promoted",
1196 "to DirectClass (see miff(5)). To force a PseudoClass image",
1197 "to remain PseudoClass, use -colors.",
1202 "In region of interest mode, the Command widget has these",
1208 "To define a region of interest, press button 1 and drag.",
1209 "The region of interest is defined by a highlighted rectangle",
1210 "that expands or contracts as it follows the pointer. Once",
1211 "you are satisfied with the region of interest, release the",
1212 "button. You are now in apply mode. In apply mode the",
1213 "Command widget has these options:",
1233 " Contrast Stretch",
1234 " Sigmoidal Contrast...",
1261 " Charcoal Drawing...",
1271 "You can make adjustments to the region of interest by moving",
1272 "the pointer to one of the rectangle corners, pressing a",
1273 "button, and dragging. Finally, choose an image processing",
1274 "technique from the Command widget. You can choose more than",
1275 "one image processing technique to apply to an area.",
1276 "Alternatively, you can move the region of interest before",
1277 "applying another image processing technique. To exit, press",
1281 *ImageRotateHelp[] =
1283 "In rotate mode, the Command widget has these options:",
1302 "Choose a background color from the Pixel Color sub-menu.",
1303 "Additional background colors can be specified with the color",
1304 "browser. You can change the menu colors by setting the X",
1305 "resources pen1 through pen9.",
1307 "If you choose the color browser and press Grab, you can",
1308 "select the background color by moving the pointer to the",
1309 "desired color on the screen and press any button.",
1311 "Choose a point in the image window and press this button and",
1312 "hold. Next, move the pointer to another location in the",
1313 "image. As you move a line connects the initial location and",
1314 "the pointer. When you release the button, the degree of",
1315 "image rotation is determined by the slope of the line you",
1316 "just drew. The slope is relative to the direction you",
1317 "choose from the Direction sub-menu of the Command widget.",
1319 "To cancel the image rotation, move the pointer back to the",
1320 "starting point of the line and release the button.",
1325 Enumeration declarations.
1344 VisualDirectoryCommand,
1352 OriginalSizeCommand,
1374 ContrastStretchCommand,
1375 SigmoidalContrastCommand,
1401 CharcoalDrawCommand,
1411 RegionofInterestCommand,
1417 ShowHistogramCommand,
1423 BrowseDocumentationCommand,
1425 SaveToUndoBufferCommand,
1432 AnnotateNameCommand,
1433 AnnotateFontColorCommand,
1434 AnnotateBackgroundColorCommand,
1435 AnnotateRotateCommand,
1436 AnnotateHelpCommand,
1437 AnnotateDismissCommand,
1440 ChopDirectionCommand,
1443 HorizontalChopCommand,
1444 VerticalChopCommand,
1445 ColorEditMethodCommand,
1446 ColorEditColorCommand,
1447 ColorEditBorderCommand,
1448 ColorEditFuzzCommand,
1449 ColorEditUndoCommand,
1450 ColorEditHelpCommand,
1451 ColorEditDismissCommand,
1452 CompositeOperatorsCommand,
1453 CompositeDissolveCommand,
1454 CompositeDisplaceCommand,
1455 CompositeHelpCommand,
1456 CompositeDismissCommand,
1461 RectifyDismissCommand,
1470 MatteEditBorderCommand,
1471 MatteEditFuzzCommand,
1472 MatteEditValueCommand,
1473 MatteEditUndoCommand,
1474 MatteEditHelpCommand,
1475 MatteEditDismissCommand,
1476 PasteOperatorsCommand,
1478 PasteDismissCommand,
1480 RotateDirectionCommand,
1482 RotateSharpenCommand,
1484 RotateDismissCommand,
1485 HorizontalRotateCommand,
1486 VerticalRotateCommand,
1497 #define BricksWidth 20
1498 #define BricksHeight 20
1499 #define DiagonalWidth 16
1500 #define DiagonalHeight 16
1501 #define HighlightWidth 8
1502 #define HighlightHeight 8
1503 #define ScalesWidth 16
1504 #define ScalesHeight 16
1505 #define ShadowWidth 8
1506 #define ShadowHeight 8
1507 #define VerticalWidth 16
1508 #define VerticalHeight 16
1509 #define WavyWidth 16
1510 #define WavyHeight 16
1513 Constant declaration.
1518 static const unsigned char
1521 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1522 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1523 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1524 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1525 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1529 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1530 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1531 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1535 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1536 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1537 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1541 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1542 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1543 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1547 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1548 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1549 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1553 Function prototypes.
1556 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1557 const MagickStatusType,KeySym,Image **);
1560 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1562 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1563 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *),
1564 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *);
1566 static MagickBooleanType
1567 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *),
1568 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **),
1569 XChopImage(Display *,XResourceInfo *,XWindows *,Image **),
1570 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode),
1571 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **),
1572 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **),
1573 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *),
1574 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *),
1575 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **),
1576 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *),
1577 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *),
1578 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **),
1579 XROIImage(Display *,XResourceInfo *,XWindows *,Image **),
1580 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *),
1581 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *);
1584 XDrawPanRectangle(Display *,XWindows *),
1585 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **),
1586 XMagnifyImage(Display *,XWindows *,XEvent *),
1587 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *),
1588 XPanImage(Display *,XWindows *,XEvent *),
1589 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1591 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1592 XScreenEvent(Display *,XWindows *,XEvent *),
1593 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1600 % D i s p l a y I m a g e s %
1604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1606 % DisplayImages() displays an image sequence to any X window screen. It
1607 % returns a value other than 0 if successful. Check the exception member
1608 % of image to determine the reason for any failure.
1610 % The format of the DisplayImages method is:
1612 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1615 % A description of each parameter follows:
1617 % o image_info: the image info.
1619 % o image: the image.
1622 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1646 assert(image_info != (const ImageInfo *) NULL);
1647 assert(image_info->signature == MagickSignature);
1648 assert(images != (Image *) NULL);
1649 assert(images->signature == MagickSignature);
1650 if (images->debug != MagickFalse)
1651 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1652 display=XOpenDisplay(image_info->server_name);
1653 if (display == (Display *) NULL)
1655 (void) ThrowMagickException(&images->exception,GetMagickModule(),
1656 XServerError,"UnableToOpenXServer","`%s'",XDisplayName(
1657 image_info->server_name));
1658 return(MagickFalse);
1660 if (images->exception.severity != UndefinedException)
1661 CatchException(&images->exception);
1662 (void) XSetErrorHandler(XError);
1663 resource_database=XGetResourceDatabase(display,GetClientName());
1664 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1665 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1666 if (image_info->page != (char *) NULL)
1667 resource_info.image_geometry=AcquireString(image_info->page);
1668 resource_info.immutable=MagickTrue;
1669 argv[0]=AcquireString(GetClientName());
1671 for (i=0; (state & ExitState) == 0; i++)
1673 if ((images->iterations != 0) && (i >= (long) images->iterations))
1675 image=GetImageFromList(images,i % GetImageListLength(images));
1676 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state);
1678 argv[0]=DestroyString(argv[0]);
1679 (void) XCloseDisplay(display);
1680 XDestroyResourceInfo(&resource_info);
1681 if (images->exception.severity != UndefinedException)
1682 return(MagickFalse);
1687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1691 % R e m o t e D i s p l a y C o m m a n d %
1695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1697 % RemoteDisplayCommand() encourages a remote display program to display the
1698 % specified image filename.
1700 % The format of the RemoteDisplayCommand method is:
1702 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1703 % const char *window,const char *filename,ExceptionInfo *exception)
1705 % A description of each parameter follows:
1707 % o image_info: the image info.
1709 % o window: Specifies the name or id of an X window.
1711 % o filename: the name of the image filename to display.
1713 % o exception: return any errors or warnings in this structure.
1716 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1717 const char *window,const char *filename,ExceptionInfo *exception)
1725 assert(image_info != (const ImageInfo *) NULL);
1726 assert(image_info->signature == MagickSignature);
1727 assert(filename != (char *) NULL);
1728 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1729 display=XOpenDisplay(image_info->server_name);
1730 if (display == (Display *) NULL)
1732 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1733 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1734 return(MagickFalse);
1736 (void) XSetErrorHandler(XError);
1737 status=XRemoteCommand(display,window,filename);
1738 (void) XCloseDisplay(display);
1739 return(status != 0 ? MagickTrue : MagickFalse);
1743 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1747 + X A n n o t a t e E d i t I m a g e %
1751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1753 % XAnnotateEditImage() annotates the image with text.
1755 % The format of the XAnnotateEditImage method is:
1757 % MagickBooleanType XAnnotateEditImage(Display *display,
1758 % XResourceInfo *resource_info,XWindows *windows,Image *image)
1760 % A description of each parameter follows:
1762 % o display: Specifies a connection to an X server; returned from
1765 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1767 % o windows: Specifies a pointer to a XWindows structure.
1769 % o image: the image; returned from ReadImage.
1773 static inline long MagickMax(const long x,const long y)
1780 static inline long MagickMin(const long x,const long y)
1787 static MagickBooleanType XAnnotateEditImage(Display *display,
1788 XResourceInfo *resource_info,XWindows *windows,Image *image)
1808 static const ModeType
1809 AnnotateCommands[] =
1811 AnnotateNameCommand,
1812 AnnotateFontColorCommand,
1813 AnnotateBackgroundColorCommand,
1814 AnnotateRotateCommand,
1815 AnnotateHelpCommand,
1816 AnnotateDismissCommand
1824 static MagickBooleanType
1825 transparent_box = MagickTrue,
1826 transparent_pen = MagickFalse;
1828 static MagickRealType
1832 box_id = MaxNumberPens-2,
1837 command[MaxTextExtent],
1838 text[MaxTextExtent];
1841 *ColorMenu[MaxNumberPens+1];
1889 (void) CloneString(&windows->command.name,"Annotate");
1890 windows->command.data=4;
1891 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1892 (void) XMapRaised(display,windows->command.id);
1893 XClientMessage(display,windows->image.id,windows->im_protocols,
1894 windows->im_update_widget,CurrentTime);
1896 Track pointer until button 1 is pressed.
1898 XQueryPosition(display,windows->image.id,&x,&y);
1899 (void) XSelectInput(display,windows->image.id,
1900 windows->image.attributes.event_mask | PointerMotionMask);
1901 cursor=XCreateFontCursor(display,XC_left_side);
1902 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1906 if (windows->info.mapped != MagickFalse)
1909 Display pointer position.
1911 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
1912 x+windows->image.x,y+windows->image.y);
1913 XInfoWidget(display,windows,text);
1916 Wait for next event.
1918 XScreenEvent(display,windows,&event);
1919 if (event.xany.window == windows->command.id)
1922 Select a command from the Command widget.
1924 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1925 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1928 switch (AnnotateCommands[id])
1930 case AnnotateNameCommand:
1933 *FontMenu[MaxNumberFonts];
1939 Initialize menu selections.
1941 for (i=0; i < MaxNumberFonts; i++)
1942 FontMenu[i]=resource_info->font_name[i];
1943 FontMenu[MaxNumberFonts-2]="Browser...";
1944 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1946 Select a font name from the pop-up menu.
1948 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1949 (const char **) FontMenu,command);
1950 if (font_number < 0)
1952 if (font_number == (MaxNumberFonts-2))
1955 font_name[MaxTextExtent] = "fixed";
1958 Select a font name from a browser.
1960 resource_info->font_name[font_number]=font_name;
1961 XFontBrowserWidget(display,windows,"Select",font_name);
1962 if (*font_name == '\0')
1966 Initialize font info.
1968 font_info=XLoadQueryFont(display,resource_info->font_name[
1970 if (font_info == (XFontStruct *) NULL)
1972 XNoticeWidget(display,windows,"Unable to load font:",
1973 resource_info->font_name[font_number]);
1976 font_id=(unsigned int) font_number;
1977 (void) XFreeFont(display,font_info);
1980 case AnnotateFontColorCommand:
1983 Initialize menu selections.
1985 for (i=0; i < (int) (MaxNumberPens-2); i++)
1986 ColorMenu[i]=resource_info->pen_colors[i];
1987 ColorMenu[MaxNumberPens-2]="transparent";
1988 ColorMenu[MaxNumberPens-1]="Browser...";
1989 ColorMenu[MaxNumberPens]=(const char *) NULL;
1991 Select a pen color from the pop-up menu.
1993 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
1994 (const char **) ColorMenu,command);
1997 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
1999 if (transparent_pen != MagickFalse)
2001 if (pen_number == (MaxNumberPens-1))
2004 color_name[MaxTextExtent] = "gray";
2007 Select a pen color from a dialog.
2009 resource_info->pen_colors[pen_number]=color_name;
2010 XColorBrowserWidget(display,windows,"Select",color_name);
2011 if (*color_name == '\0')
2017 (void) XParseColor(display,windows->map_info->colormap,
2018 resource_info->pen_colors[pen_number],&color);
2019 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2020 (unsigned int) MaxColors,&color);
2021 windows->pixel_info->pen_colors[pen_number]=color;
2022 pen_id=(unsigned int) pen_number;
2025 case AnnotateBackgroundColorCommand:
2028 Initialize menu selections.
2030 for (i=0; i < (int) (MaxNumberPens-2); i++)
2031 ColorMenu[i]=resource_info->pen_colors[i];
2032 ColorMenu[MaxNumberPens-2]="transparent";
2033 ColorMenu[MaxNumberPens-1]="Browser...";
2034 ColorMenu[MaxNumberPens]=(const char *) NULL;
2036 Select a pen color from the pop-up menu.
2038 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2039 (const char **) ColorMenu,command);
2042 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2044 if (transparent_box != MagickFalse)
2046 if (pen_number == (MaxNumberPens-1))
2049 color_name[MaxTextExtent] = "gray";
2052 Select a pen color from a dialog.
2054 resource_info->pen_colors[pen_number]=color_name;
2055 XColorBrowserWidget(display,windows,"Select",color_name);
2056 if (*color_name == '\0')
2062 (void) XParseColor(display,windows->map_info->colormap,
2063 resource_info->pen_colors[pen_number],&color);
2064 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2065 (unsigned int) MaxColors,&color);
2066 windows->pixel_info->pen_colors[pen_number]=color;
2067 box_id=(unsigned int) pen_number;
2070 case AnnotateRotateCommand:
2076 angle[MaxTextExtent] = "30.0";
2094 Select a command from the pop-up menu.
2096 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2102 degrees=StringToDouble(RotateMenu[entry]);
2105 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2109 degrees=StringToDouble(angle);
2112 case AnnotateHelpCommand:
2114 XTextViewWidget(display,resource_info,windows,MagickFalse,
2115 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2118 case AnnotateDismissCommand:
2136 if (event.xbutton.button != Button1)
2138 if (event.xbutton.window != windows->image.id)
2141 Change to text entering mode.
2154 if (event.xkey.window != windows->image.id)
2157 Respond to a user key press.
2159 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2160 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2161 switch ((int) key_symbol)
2176 XTextViewWidget(display,resource_info,windows,MagickFalse,
2177 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2182 (void) XBell(display,0);
2191 Map and unmap Info widget as cursor crosses its boundaries.
2195 if (windows->info.mapped != MagickFalse)
2197 if ((x < (int) (windows->info.x+windows->info.width)) &&
2198 (y < (int) (windows->info.y+windows->info.height)))
2199 (void) XWithdrawWindow(display,windows->info.id,
2200 windows->info.screen);
2203 if ((x > (int) (windows->info.x+windows->info.width)) ||
2204 (y > (int) (windows->info.y+windows->info.height)))
2205 (void) XMapWindow(display,windows->info.id);
2211 } while ((state & ExitState) == 0);
2212 (void) XSelectInput(display,windows->image.id,
2213 windows->image.attributes.event_mask);
2214 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2215 if ((state & EscapeState) != 0)
2218 Set font info and check boundary conditions.
2220 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2221 if (font_info == (XFontStruct *) NULL)
2223 XNoticeWidget(display,windows,"Unable to load font:",
2224 resource_info->font_name[font_id]);
2225 font_info=windows->font_info;
2227 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2228 x=(int) windows->image.width-font_info->max_bounds.width;
2229 if (y < (int) (font_info->ascent+font_info->descent))
2230 y=(int) font_info->ascent+font_info->descent;
2231 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2232 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2233 return(MagickFalse);
2235 Initialize annotate structure.
2237 annotate_info=(XAnnotateInfo *) AcquireAlignedMemory(1,sizeof(*annotate_info));
2238 if (annotate_info == (XAnnotateInfo *) NULL)
2239 return(MagickFalse);
2240 XGetAnnotateInfo(annotate_info);
2243 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
2244 annotate_info->stencil=OpaqueStencil;
2246 if (transparent_box == MagickFalse)
2247 annotate_info->stencil=BackgroundStencil;
2249 annotate_info->stencil=ForegroundStencil;
2250 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2251 annotate_info->degrees=degrees;
2252 annotate_info->font_info=font_info;
2253 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2254 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
2255 sizeof(*annotate_info->text));
2256 if (annotate_info->text == (char *) NULL)
2257 return(MagickFalse);
2259 Create cursor and set graphic context.
2261 cursor=XCreateFontCursor(display,XC_pencil);
2262 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2263 annotate_context=windows->image.annotate_context;
2264 (void) XSetFont(display,annotate_context,font_info->fid);
2265 (void) XSetBackground(display,annotate_context,
2266 windows->pixel_info->pen_colors[box_id].pixel);
2267 (void) XSetForeground(display,annotate_context,
2268 windows->pixel_info->pen_colors[pen_id].pixel);
2270 Begin annotating the image with text.
2272 (void) CloneString(&windows->command.name,"Text");
2273 windows->command.data=0;
2274 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2276 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2277 text_event.xexpose.width=(int) font_info->max_bounds.width;
2278 text_event.xexpose.height=font_info->max_bounds.ascent+
2279 font_info->max_bounds.descent;
2280 p=annotate_info->text;
2284 Display text cursor.
2287 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2289 Wait for next event.
2291 XScreenEvent(display,windows,&event);
2292 if (event.xany.window == windows->command.id)
2295 Select a command from the Command widget.
2297 (void) XSetBackground(display,annotate_context,
2298 windows->pixel_info->background_color.pixel);
2299 (void) XSetForeground(display,annotate_context,
2300 windows->pixel_info->foreground_color.pixel);
2301 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2302 (void) XSetBackground(display,annotate_context,
2303 windows->pixel_info->pen_colors[box_id].pixel);
2304 (void) XSetForeground(display,annotate_context,
2305 windows->pixel_info->pen_colors[pen_id].pixel);
2308 switch (TextCommands[id])
2310 case TextHelpCommand:
2312 XTextViewWidget(display,resource_info,windows,MagickFalse,
2313 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2314 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2317 case TextApplyCommand:
2320 Finished annotating.
2322 annotate_info->width=(unsigned int) XTextWidth(font_info,
2323 annotate_info->text,(int) strlen(annotate_info->text));
2324 XRefreshWindow(display,&windows->image,&text_event);
2336 text_event.xexpose.x=x;
2337 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2338 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2339 (unsigned int) text_event.xexpose.width,(unsigned int)
2340 text_event.xexpose.height,MagickFalse);
2341 XRefreshWindow(display,&windows->image,&text_event);
2346 if (event.xbutton.window != windows->image.id)
2348 if (event.xbutton.button == Button2)
2351 Request primary selection.
2353 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2354 windows->image.id,CurrentTime);
2361 if (event.xexpose.count == 0)
2367 Refresh Image window.
2369 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2370 text_info=annotate_info;
2371 while (text_info != (XAnnotateInfo *) NULL)
2373 if (annotate_info->stencil == ForegroundStencil)
2374 (void) XDrawString(display,windows->image.id,annotate_context,
2375 text_info->x,text_info->y,text_info->text,
2376 (int) strlen(text_info->text));
2378 (void) XDrawImageString(display,windows->image.id,
2379 annotate_context,text_info->x,text_info->y,text_info->text,
2380 (int) strlen(text_info->text));
2381 text_info=text_info->previous;
2383 (void) XDrawString(display,windows->image.id,annotate_context,
2393 if (event.xkey.window != windows->image.id)
2396 Respond to a user key press.
2398 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2399 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2400 *(command+length)='\0';
2401 if (((event.xkey.state & ControlMask) != 0) ||
2402 ((event.xkey.state & Mod1Mask) != 0))
2403 state|=ModifierState;
2404 if ((state & ModifierState) != 0)
2405 switch ((int) key_symbol)
2410 key_symbol=DeleteCommand;
2416 switch ((int) key_symbol)
2421 Erase one character.
2423 if (p == annotate_info->text)
2425 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2430 Go to end of the previous line of text.
2432 annotate_info=annotate_info->previous;
2433 p=annotate_info->text;
2434 x=annotate_info->x+annotate_info->width;
2436 if (annotate_info->width != 0)
2437 p+=strlen(annotate_info->text);
2442 x-=XTextWidth(font_info,p,1);
2443 text_event.xexpose.x=x;
2444 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2445 XRefreshWindow(display,&windows->image,&text_event);
2448 case XK_bracketleft:
2450 key_symbol=XK_Escape;
2456 Erase the entire line of text.
2458 while (p != annotate_info->text)
2461 x-=XTextWidth(font_info,p,1);
2462 text_event.xexpose.x=x;
2463 XRefreshWindow(display,&windows->image,&text_event);
2471 Finished annotating.
2473 annotate_info->width=(unsigned int) XTextWidth(font_info,
2474 annotate_info->text,(int) strlen(annotate_info->text));
2475 XRefreshWindow(display,&windows->image,&text_event);
2482 Draw a single character on the Image window.
2484 if ((state & ModifierState) != 0)
2486 if (*command == '\0')
2489 if (annotate_info->stencil == ForegroundStencil)
2490 (void) XDrawString(display,windows->image.id,annotate_context,
2493 (void) XDrawImageString(display,windows->image.id,
2494 annotate_context,x,y,p,1);
2495 x+=XTextWidth(font_info,p,1);
2497 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2504 Advance to the next line of text.
2507 annotate_info->width=(unsigned int) XTextWidth(font_info,
2508 annotate_info->text,(int) strlen(annotate_info->text));
2509 if (annotate_info->next != (XAnnotateInfo *) NULL)
2512 Line of text already exists.
2514 annotate_info=annotate_info->next;
2517 p=annotate_info->text;
2520 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2521 sizeof(*annotate_info->next));
2522 if (annotate_info->next == (XAnnotateInfo *) NULL)
2523 return(MagickFalse);
2524 *annotate_info->next=(*annotate_info);
2525 annotate_info->next->previous=annotate_info;
2526 annotate_info=annotate_info->next;
2527 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2528 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
2529 sizeof(*annotate_info->text));
2530 if (annotate_info->text == (char *) NULL)
2531 return(MagickFalse);
2532 annotate_info->y+=annotate_info->height;
2533 if (annotate_info->y > (int) windows->image.height)
2534 annotate_info->y=(int) annotate_info->height;
2535 annotate_info->next=(XAnnotateInfo *) NULL;
2538 p=annotate_info->text;
2547 Respond to a user key release.
2549 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2550 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2551 state&=(~ModifierState);
2554 case SelectionNotify:
2570 Obtain response from primary selection.
2572 if (event.xselection.property == (Atom) None)
2574 status=XGetWindowProperty(display,event.xselection.requestor,
2575 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2576 &type,&format,&length,&after,&data);
2577 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2581 Annotate Image window with primary selection.
2583 for (i=0; i < (long) length; i++)
2585 if ((char) data[i] != '\n')
2588 Draw a single character on the Image window.
2591 (void) XDrawString(display,windows->image.id,annotate_context,
2593 x+=XTextWidth(font_info,p,1);
2595 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2599 Advance to the next line of text.
2602 annotate_info->width=(unsigned int) XTextWidth(font_info,
2603 annotate_info->text,(int) strlen(annotate_info->text));
2604 if (annotate_info->next != (XAnnotateInfo *) NULL)
2607 Line of text already exists.
2609 annotate_info=annotate_info->next;
2612 p=annotate_info->text;
2615 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2616 sizeof(*annotate_info->next));
2617 if (annotate_info->next == (XAnnotateInfo *) NULL)
2618 return(MagickFalse);
2619 *annotate_info->next=(*annotate_info);
2620 annotate_info->next->previous=annotate_info;
2621 annotate_info=annotate_info->next;
2622 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2623 windows->image.width/MagickMax(font_info->min_bounds.width,1)+2UL,
2624 sizeof(*annotate_info->text));
2625 if (annotate_info->text == (char *) NULL)
2626 return(MagickFalse);
2627 annotate_info->y+=annotate_info->height;
2628 if (annotate_info->y > (int) windows->image.height)
2629 annotate_info->y=(int) annotate_info->height;
2630 annotate_info->next=(XAnnotateInfo *) NULL;
2633 p=annotate_info->text;
2635 (void) XFree((void *) data);
2641 } while ((state & ExitState) == 0);
2642 (void) XFreeCursor(display,cursor);
2644 Annotation is relative to image configuration.
2646 width=(unsigned int) image->columns;
2647 height=(unsigned int) image->rows;
2650 if (windows->image.crop_geometry != (char *) NULL)
2651 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2653 Initialize annotated image.
2655 XSetCursorState(display,windows,MagickTrue);
2656 XCheckRefreshWindows(display,windows);
2657 while (annotate_info != (XAnnotateInfo *) NULL)
2659 if (annotate_info->width == 0)
2662 No text on this line-- go to the next line of text.
2664 previous_info=annotate_info->previous;
2665 annotate_info->text=(char *)
2666 RelinquishMagickMemory(annotate_info->text);
2667 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2668 annotate_info=previous_info;
2672 Determine pixel index for box and pen color.
2674 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2675 if (windows->pixel_info->colors != 0)
2676 for (i=0; i < (long) windows->pixel_info->colors; i++)
2677 if (windows->pixel_info->pixels[i] ==
2678 windows->pixel_info->pen_colors[box_id].pixel)
2680 windows->pixel_info->box_index=(unsigned short) i;
2683 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2684 if (windows->pixel_info->colors != 0)
2685 for (i=0; i < (long) windows->pixel_info->colors; i++)
2686 if (windows->pixel_info->pixels[i] ==
2687 windows->pixel_info->pen_colors[pen_id].pixel)
2689 windows->pixel_info->pen_index=(unsigned short) i;
2693 Define the annotate geometry string.
2695 annotate_info->x=(int)
2696 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2697 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2698 windows->image.y)/windows->image.ximage->height;
2699 (void) FormatMagickString(annotate_info->geometry,MaxTextExtent,
2700 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2701 height*annotate_info->height/windows->image.ximage->height,
2702 annotate_info->x+x,annotate_info->y+y);
2704 Annotate image with text.
2706 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image);
2708 return(MagickFalse);
2712 previous_info=annotate_info->previous;
2713 annotate_info->text=DestroyString(annotate_info->text);
2714 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2715 annotate_info=previous_info;
2717 (void) XSetForeground(display,annotate_context,
2718 windows->pixel_info->foreground_color.pixel);
2719 (void) XSetBackground(display,annotate_context,
2720 windows->pixel_info->background_color.pixel);
2721 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2722 XSetCursorState(display,windows,MagickFalse);
2723 (void) XFreeFont(display,font_info);
2725 Update image configuration.
2727 XConfigureImageColormap(display,resource_info,windows,image);
2728 (void) XConfigureImage(display,resource_info,windows,image);
2733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2737 + X B a c k g r o u n d I m a g e %
2741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2743 % XBackgroundImage() displays the image in the background of a window.
2745 % The format of the XBackgroundImage method is:
2747 % MagickBooleanType XBackgroundImage(Display *display,
2748 % XResourceInfo *resource_info,XWindows *windows,Image **image)
2750 % A description of each parameter follows:
2752 % o display: Specifies a connection to an X server; returned from
2755 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2757 % o windows: Specifies a pointer to a XWindows structure.
2759 % o image: the image.
2762 static MagickBooleanType XBackgroundImage(Display *display,
2763 XResourceInfo *resource_info,XWindows *windows,Image **image)
2765 #define BackgroundImageTag "Background/Image"
2771 window_id[MaxTextExtent] = "root";
2774 background_resources;
2777 Put image in background.
2779 status=XDialogWidget(display,windows,"Background",
2780 "Enter window id (id 0x00 selects window with pointer):",window_id);
2781 if (*window_id == '\0')
2782 return(MagickFalse);
2783 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
2784 XInfoWidget(display,windows,BackgroundImageTag);
2785 XSetCursorState(display,windows,MagickTrue);
2786 XCheckRefreshWindows(display,windows);
2787 background_resources=(*resource_info);
2788 background_resources.window_id=window_id;
2789 background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse;
2790 status=XDisplayBackgroundImage(display,&background_resources,*image);
2791 if (status != MagickFalse)
2792 XClientMessage(display,windows->image.id,windows->im_protocols,
2793 windows->im_retain_colors,CurrentTime);
2794 XSetCursorState(display,windows,MagickFalse);
2795 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image);
2800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2804 + X C h o p I m a g e %
2808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2810 % XChopImage() chops the X image.
2812 % The format of the XChopImage method is:
2814 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2815 % XWindows *windows,Image **image)
2817 % A description of each parameter follows:
2819 % o display: Specifies a connection to an X server; returned from
2822 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2824 % o windows: Specifies a pointer to a XWindows structure.
2826 % o image: the image.
2829 static MagickBooleanType XChopImage(Display *display,
2830 XResourceInfo *resource_info,XWindows *windows,Image **image)
2842 direction = HorizontalChopCommand;
2844 static const ModeType
2847 ChopDirectionCommand,
2851 DirectionCommands[] =
2853 HorizontalChopCommand,
2858 text[MaxTextExtent];
2891 (void) CloneString(&windows->command.name,"Chop");
2892 windows->command.data=1;
2893 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2894 (void) XMapRaised(display,windows->command.id);
2895 XClientMessage(display,windows->image.id,windows->im_protocols,
2896 windows->im_update_widget,CurrentTime);
2898 Track pointer until button 1 is pressed.
2900 XQueryPosition(display,windows->image.id,&x,&y);
2901 (void) XSelectInput(display,windows->image.id,
2902 windows->image.attributes.event_mask | PointerMotionMask);
2906 if (windows->info.mapped != MagickFalse)
2909 Display pointer position.
2911 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
2912 x+windows->image.x,y+windows->image.y);
2913 XInfoWidget(display,windows,text);
2916 Wait for next event.
2918 XScreenEvent(display,windows,&event);
2919 if (event.xany.window == windows->command.id)
2922 Select a command from the Command widget.
2924 id=XCommandWidget(display,windows,ChopMenu,&event);
2927 switch (ChopCommands[id])
2929 case ChopDirectionCommand:
2932 command[MaxTextExtent];
2943 Select a command from the pop-up menu.
2945 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2947 direction=DirectionCommands[id];
2950 case ChopHelpCommand:
2952 XTextViewWidget(display,resource_info,windows,MagickFalse,
2953 "Help Viewer - Image Chop",ImageChopHelp);
2956 case ChopDismissCommand:
2974 if (event.xbutton.button != Button1)
2976 if (event.xbutton.window != windows->image.id)
2979 User has committed to start point of chopping line.
2981 segment_info.x1=(short int) event.xbutton.x;
2982 segment_info.x2=(short int) event.xbutton.x;
2983 segment_info.y1=(short int) event.xbutton.y;
2984 segment_info.y2=(short int) event.xbutton.y;
2995 command[MaxTextExtent];
3000 if (event.xkey.window != windows->image.id)
3003 Respond to a user key press.
3005 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3006 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3007 switch ((int) key_symbol)
3022 (void) XSetFunction(display,windows->image.highlight_context,
3024 XTextViewWidget(display,resource_info,windows,MagickFalse,
3025 "Help Viewer - Image Chop",ImageChopHelp);
3026 (void) XSetFunction(display,windows->image.highlight_context,
3032 (void) XBell(display,0);
3041 Map and unmap Info widget as text cursor crosses its boundaries.
3045 if (windows->info.mapped != MagickFalse)
3047 if ((x < (int) (windows->info.x+windows->info.width)) &&
3048 (y < (int) (windows->info.y+windows->info.height)))
3049 (void) XWithdrawWindow(display,windows->info.id,
3050 windows->info.screen);
3053 if ((x > (int) (windows->info.x+windows->info.width)) ||
3054 (y > (int) (windows->info.y+windows->info.height)))
3055 (void) XMapWindow(display,windows->info.id);
3058 } while ((state & ExitState) == 0);
3059 (void) XSelectInput(display,windows->image.id,
3060 windows->image.attributes.event_mask);
3061 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3062 if ((state & EscapeState) != 0)
3065 Draw line as pointer moves until the mouse button is released.
3072 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3079 Display info and draw chopping line.
3081 if (windows->info.mapped == MagickFalse)
3082 (void) XMapWindow(display,windows->info.id);
3083 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
3084 chop_info.width,chop_info.height,chop_info.x,chop_info.y);
3085 XInfoWidget(display,windows,text);
3086 XHighlightLine(display,windows->image.id,
3087 windows->image.highlight_context,&segment_info);
3090 if (windows->info.mapped != MagickFalse)
3091 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3093 Wait for next event.
3095 XScreenEvent(display,windows,&event);
3097 XHighlightLine(display,windows->image.id,
3098 windows->image.highlight_context,&segment_info);
3103 segment_info.x2=(short int) event.xmotion.x;
3104 segment_info.y2=(short int) event.xmotion.y;
3110 User has committed to chopping line.
3112 segment_info.x2=(short int) event.xbutton.x;
3113 segment_info.y2=(short int) event.xbutton.y;
3121 segment_info.x2=(short int) event.xmotion.x;
3122 segment_info.y2=(short int) event.xmotion.y;
3128 Check boundary conditions.
3130 if (segment_info.x2 < 0)
3133 if (segment_info.x2 > windows->image.ximage->width)
3134 segment_info.x2=windows->image.ximage->width;
3135 if (segment_info.y2 < 0)
3138 if (segment_info.y2 > windows->image.ximage->height)
3139 segment_info.y2=windows->image.ximage->height;
3140 distance=(unsigned int)
3141 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3142 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3144 Compute chopping geometry.
3146 if (direction == HorizontalChopCommand)
3148 chop_info.width=(unsigned long) (segment_info.x2-segment_info.x1+1);
3149 chop_info.x=windows->image.x+segment_info.x1;
3152 if (segment_info.x1 > (int) segment_info.x2)
3154 chop_info.width=(unsigned long) (segment_info.x1-segment_info.x2+1);
3155 chop_info.x=windows->image.x+segment_info.x2;
3161 chop_info.height=(unsigned long) (segment_info.y2-segment_info.y1+1);
3163 chop_info.y=windows->image.y+segment_info.y1;
3164 if (segment_info.y1 > segment_info.y2)
3166 chop_info.height=(unsigned long)
3167 (segment_info.y1-segment_info.y2+1);
3168 chop_info.y=windows->image.y+segment_info.y2;
3171 } while ((state & ExitState) == 0);
3172 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3173 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3177 Image chopping is relative to image configuration.
3179 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
3180 XSetCursorState(display,windows,MagickTrue);
3181 XCheckRefreshWindows(display,windows);
3182 windows->image.window_changes.width=windows->image.ximage->width-
3183 (unsigned int) chop_info.width;
3184 windows->image.window_changes.height=windows->image.ximage->height-
3185 (unsigned int) chop_info.height;
3186 width=(unsigned int) (*image)->columns;
3187 height=(unsigned int) (*image)->rows;
3190 if (windows->image.crop_geometry != (char *) NULL)
3191 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3192 scale_factor=(MagickRealType) width/windows->image.ximage->width;
3194 chop_info.x=(int) (scale_factor*chop_info.x+0.5);
3195 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3196 scale_factor=(MagickRealType) height/windows->image.ximage->height;
3198 chop_info.y=(int) (scale_factor*chop_info.y+0.5);
3199 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3203 chop_image=ChopImage(*image,&chop_info,&(*image)->exception);
3204 XSetCursorState(display,windows,MagickFalse);
3205 if (chop_image == (Image *) NULL)
3206 return(MagickFalse);
3207 *image=DestroyImage(*image);
3210 Update image configuration.
3212 XConfigureImageColormap(display,resource_info,windows,*image);
3213 (void) XConfigureImage(display,resource_info,windows,*image);
3218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3222 + X C o l o r E d i t I m a g e %
3226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3228 % XColorEditImage() allows the user to interactively change the color of one
3229 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3231 % The format of the XColorEditImage method is:
3233 % MagickBooleanType XColorEditImage(Display *display,
3234 % XResourceInfo *resource_info,XWindows *windows,Image **image)
3236 % A description of each parameter follows:
3238 % o display: Specifies a connection to an X server; returned from
3241 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3243 % o windows: Specifies a pointer to a XWindows structure.
3245 % o image: the image; returned from ReadImage.
3250 static MagickBooleanType XColorEditImage(Display *display,
3251 XResourceInfo *resource_info,XWindows *windows,Image **image)
3266 static const ModeType
3267 ColorEditCommands[] =
3269 ColorEditMethodCommand,
3270 ColorEditColorCommand,
3271 ColorEditBorderCommand,
3272 ColorEditFuzzCommand,
3273 ColorEditUndoCommand,
3274 ColorEditHelpCommand,
3275 ColorEditDismissCommand
3279 method = PointMethod;
3285 border_color = { 0, 0, 0, 0, 0, 0 };
3288 command[MaxTextExtent],
3289 text[MaxTextExtent];
3305 register PixelPacket
3327 (void) CloneString(&windows->command.name,"Color Edit");
3328 windows->command.data=4;
3329 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3330 (void) XMapRaised(display,windows->command.id);
3331 XClientMessage(display,windows->image.id,windows->im_protocols,
3332 windows->im_update_widget,CurrentTime);
3336 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3337 resource_info->background_color,resource_info->foreground_color);
3338 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3340 Track pointer until button 1 is pressed.
3342 XQueryPosition(display,windows->image.id,&x,&y);
3343 (void) XSelectInput(display,windows->image.id,
3344 windows->image.attributes.event_mask | PointerMotionMask);
3348 if (windows->info.mapped != MagickFalse)
3351 Display pointer position.
3353 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
3354 x+windows->image.x,y+windows->image.y);
3355 XInfoWidget(display,windows,text);
3358 Wait for next event.
3360 XScreenEvent(display,windows,&event);
3361 if (event.xany.window == windows->command.id)
3364 Select a command from the Command widget.
3366 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3369 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3372 switch (ColorEditCommands[id])
3374 case ColorEditMethodCommand:
3380 Select a method from the pop-up menu.
3382 methods=(char **) GetMagickOptions(MagickMethodOptions);
3383 if (methods == (char **) NULL)
3385 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3386 (const char **) methods,command);
3388 method=(PaintMethod) ParseMagickOption(MagickMethodOptions,
3389 MagickFalse,methods[entry]);
3390 methods=DestroyStringList(methods);
3393 case ColorEditColorCommand:
3396 *ColorMenu[MaxNumberPens];
3402 Initialize menu selections.
3404 for (i=0; i < (int) (MaxNumberPens-2); i++)
3405 ColorMenu[i]=resource_info->pen_colors[i];
3406 ColorMenu[MaxNumberPens-2]="Browser...";
3407 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3409 Select a pen color from the pop-up menu.
3411 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3412 (const char **) ColorMenu,command);
3415 if (pen_number == (MaxNumberPens-2))
3418 color_name[MaxTextExtent] = "gray";
3421 Select a pen color from a dialog.
3423 resource_info->pen_colors[pen_number]=color_name;
3424 XColorBrowserWidget(display,windows,"Select",color_name);
3425 if (*color_name == '\0')
3431 (void) XParseColor(display,windows->map_info->colormap,
3432 resource_info->pen_colors[pen_number],&color);
3433 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3434 (unsigned int) MaxColors,&color);
3435 windows->pixel_info->pen_colors[pen_number]=color;
3436 pen_id=(unsigned int) pen_number;
3439 case ColorEditBorderCommand:
3442 *ColorMenu[MaxNumberPens];
3448 Initialize menu selections.
3450 for (i=0; i < (int) (MaxNumberPens-2); i++)
3451 ColorMenu[i]=resource_info->pen_colors[i];
3452 ColorMenu[MaxNumberPens-2]="Browser...";
3453 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3455 Select a pen color from the pop-up menu.
3457 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3458 (const char **) ColorMenu,command);
3461 if (pen_number == (MaxNumberPens-2))
3464 color_name[MaxTextExtent] = "gray";
3467 Select a pen color from a dialog.
3469 resource_info->pen_colors[pen_number]=color_name;
3470 XColorBrowserWidget(display,windows,"Select",color_name);
3471 if (*color_name == '\0')
3477 (void) XParseColor(display,windows->map_info->colormap,
3478 resource_info->pen_colors[pen_number],&border_color);
3481 case ColorEditFuzzCommand:
3484 fuzz[MaxTextExtent];
3499 Select a command from the pop-up menu.
3501 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3507 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*
3511 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3512 (void) XDialogWidget(display,windows,"Ok",
3513 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3516 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3517 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
3520 case ColorEditUndoCommand:
3522 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3526 case ColorEditHelpCommand:
3529 XTextViewWidget(display,resource_info,windows,MagickFalse,
3530 "Help Viewer - Image Annotation",ImageColorEditHelp);
3533 case ColorEditDismissCommand:
3543 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3550 if (event.xbutton.button != Button1)
3552 if ((event.xbutton.window != windows->image.id) &&
3553 (event.xbutton.window != windows->magnify.id))
3560 (void) XMagickCommand(display,resource_info,windows,
3561 SaveToUndoBufferCommand,image);
3562 state|=UpdateConfigurationState;
3567 if (event.xbutton.button != Button1)
3569 if ((event.xbutton.window != windows->image.id) &&
3570 (event.xbutton.window != windows->magnify.id))
3573 Update colormap information.
3577 XConfigureImageColormap(display,resource_info,windows,*image);
3578 (void) XConfigureImage(display,resource_info,windows,*image);
3579 XInfoWidget(display,windows,text);
3580 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3581 state&=(~UpdateConfigurationState);
3591 if (event.xkey.window == windows->magnify.id)
3596 window=windows->magnify.id;
3597 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3599 if (event.xkey.window != windows->image.id)
3602 Respond to a user key press.
3604 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3605 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3606 switch ((int) key_symbol)
3620 XTextViewWidget(display,resource_info,windows,MagickFalse,
3621 "Help Viewer - Image Annotation",ImageColorEditHelp);
3626 (void) XBell(display,0);
3635 Map and unmap Info widget as cursor crosses its boundaries.
3639 if (windows->info.mapped != MagickFalse)
3641 if ((x < (int) (windows->info.x+windows->info.width)) &&
3642 (y < (int) (windows->info.y+windows->info.height)))
3643 (void) XWithdrawWindow(display,windows->info.id,
3644 windows->info.screen);
3647 if ((x > (int) (windows->info.x+windows->info.width)) ||
3648 (y > (int) (windows->info.y+windows->info.height)))
3649 (void) XMapWindow(display,windows->info.id);
3655 if (event.xany.window == windows->magnify.id)
3657 x=windows->magnify.x-windows->image.x;
3658 y=windows->magnify.y-windows->image.y;
3662 if ((state & UpdateConfigurationState) != 0)
3669 Pixel edit is relative to image configuration.
3671 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3673 color=windows->pixel_info->pen_colors[pen_id];
3674 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3675 width=(unsigned int) (*image)->columns;
3676 height=(unsigned int) (*image)->rows;
3679 if (windows->image.crop_geometry != (char *) NULL)
3680 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3683 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3685 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3686 if ((x_offset < 0) || (y_offset < 0))
3688 if ((x_offset >= (long) (*image)->columns) ||
3689 (y_offset >= (long) (*image)->rows))
3691 exception=(&(*image)->exception);
3698 Update color information using point algorithm.
3700 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
3701 return(MagickFalse);
3702 q=GetAuthenticPixels(*image,x_offset,y_offset,1,1,exception);
3703 if (q == (PixelPacket *) NULL)
3705 q->red=ScaleShortToQuantum(color.red);
3706 q->green=ScaleShortToQuantum(color.green);
3707 q->blue=ScaleShortToQuantum(color.blue);
3708 (void) SyncAuthenticPixels(*image,&(*image)->exception);
3717 Update color information using replace algorithm.
3719 (void) GetOneVirtualPixel(*image,x_offset,y_offset,&target,
3720 &(*image)->exception);
3721 if ((*image)->storage_class == DirectClass)
3723 for (y=0; y < (long) (*image)->rows; y++)
3725 q=GetAuthenticPixels(*image,0,y,(*image)->columns,1,
3727 if (q == (PixelPacket *) NULL)
3729 for (x=0; x < (int) (*image)->columns; x++)
3731 if (IsColorSimilar(*image,q,&target))
3733 q->red=ScaleShortToQuantum(color.red);
3734 q->green=ScaleShortToQuantum(color.green);
3735 q->blue=ScaleShortToQuantum(color.blue);
3739 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
3745 for (i=0; i < (int) (*image)->colors; i++)
3746 if (IsColorSimilar(*image,(*image)->colormap+i,&target))
3748 (*image)->colormap[i].red=ScaleShortToQuantum(color.red);
3749 (*image)->colormap[i].green=ScaleShortToQuantum(
3751 (*image)->colormap[i].blue=ScaleShortToQuantum(
3754 (void) SyncImage(*image);
3758 case FloodfillMethod:
3759 case FillToBorderMethod:
3768 Update color information using floodfill algorithm.
3770 (void) GetOneVirtualMagickPixel(*image,x_offset,y_offset,&target,
3772 if (method == FillToBorderMethod)
3774 target.red=(MagickRealType)
3775 ScaleShortToQuantum(border_color.red);
3776 target.green=(MagickRealType)
3777 ScaleShortToQuantum(border_color.green);
3778 target.blue=(MagickRealType)
3779 ScaleShortToQuantum(border_color.blue);
3781 draw_info=CloneDrawInfo(resource_info->image_info,
3783 (void) QueryColorDatabase(resource_info->pen_colors[pen_id],
3784 &draw_info->fill,exception);
3785 (void) FloodfillPaintImage(*image,DefaultChannels,draw_info,&target,
3786 x_offset,y_offset,method == FloodfillMethod ? MagickFalse :
3788 draw_info=DestroyDrawInfo(draw_info);
3794 Update color information using reset algorithm.
3796 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
3797 return(MagickFalse);
3798 for (y=0; y < (long) (*image)->rows; y++)
3800 q=QueueAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
3801 if (q == (PixelPacket *) NULL)
3803 for (x=0; x < (int) (*image)->columns; x++)
3805 q->red=ScaleShortToQuantum(color.red);
3806 q->green=ScaleShortToQuantum(color.green);
3807 q->blue=ScaleShortToQuantum(color.blue);
3810 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
3816 state&=(~UpdateConfigurationState);
3818 } while ((state & ExitState) == 0);
3819 (void) XSelectInput(display,windows->image.id,
3820 windows->image.attributes.event_mask);
3821 XSetCursorState(display,windows,MagickFalse);
3822 (void) XFreeCursor(display,cursor);
3827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3831 + X C o m p o s i t e I m a g e %
3835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3837 % XCompositeImage() requests an image name from the user, reads the image and
3838 % composites it with the X window image at a location the user chooses with
3841 % The format of the XCompositeImage method is:
3843 % MagickBooleanType XCompositeImage(Display *display,
3844 % XResourceInfo *resource_info,XWindows *windows,Image *image)
3846 % A description of each parameter follows:
3848 % o display: Specifies a connection to an X server; returned from
3851 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3853 % o windows: Specifies a pointer to a XWindows structure.
3855 % o image: the image; returned from ReadImage.
3858 static MagickBooleanType XCompositeImage(Display *display,
3859 XResourceInfo *resource_info,XWindows *windows,Image *image)
3862 displacement_geometry[MaxTextExtent] = "30x30",
3863 filename[MaxTextExtent] = "\0";
3876 static CompositeOperator
3877 compose = CopyCompositeOp;
3879 static const ModeType
3880 CompositeCommands[] =
3882 CompositeOperatorsCommand,
3883 CompositeDissolveCommand,
3884 CompositeDisplaceCommand,
3885 CompositeHelpCommand,
3886 CompositeDismissCommand
3890 text[MaxTextExtent];
3923 Request image file name from user.
3925 XFileBrowserWidget(display,windows,"Composite",filename);
3926 if (*filename == '\0')
3931 XSetCursorState(display,windows,MagickTrue);
3932 XCheckRefreshWindows(display,windows);
3933 (void) CopyMagickString(resource_info->image_info->filename,filename,
3935 composite_image=ReadImage(resource_info->image_info,&image->exception);
3936 CatchException(&image->exception);
3937 XSetCursorState(display,windows,MagickFalse);
3938 if (composite_image == (Image *) NULL)
3939 return(MagickFalse);
3943 (void) CloneString(&windows->command.name,"Composite");
3944 windows->command.data=1;
3945 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
3946 (void) XMapRaised(display,windows->command.id);
3947 XClientMessage(display,windows->image.id,windows->im_protocols,
3948 windows->im_update_widget,CurrentTime);
3950 Track pointer until button 1 is pressed.
3952 XQueryPosition(display,windows->image.id,&x,&y);
3953 (void) XSelectInput(display,windows->image.id,
3954 windows->image.attributes.event_mask | PointerMotionMask);
3955 composite_info.x=windows->image.x+x;
3956 composite_info.y=windows->image.y+y;
3957 composite_info.width=0;
3958 composite_info.height=0;
3959 cursor=XCreateFontCursor(display,XC_ul_angle);
3960 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3965 if (windows->info.mapped != MagickFalse)
3968 Display pointer position.
3970 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
3971 composite_info.x,composite_info.y);
3972 XInfoWidget(display,windows,text);
3974 highlight_info=composite_info;
3975 highlight_info.x=composite_info.x-windows->image.x;
3976 highlight_info.y=composite_info.y-windows->image.y;
3977 XHighlightRectangle(display,windows->image.id,
3978 windows->image.highlight_context,&highlight_info);
3980 Wait for next event.
3982 XScreenEvent(display,windows,&event);
3983 XHighlightRectangle(display,windows->image.id,
3984 windows->image.highlight_context,&highlight_info);
3985 if (event.xany.window == windows->command.id)
3988 Select a command from the Command widget.
3990 id=XCommandWidget(display,windows,CompositeMenu,&event);
3993 switch (CompositeCommands[id])
3995 case CompositeOperatorsCommand:
3998 command[MaxTextExtent],
4002 Select a command from the pop-up menu.
4004 operators=GetMagickOptions(MagickComposeOptions);
4005 if (operators == (char **) NULL)
4007 entry=XMenuWidget(display,windows,CompositeMenu[id],
4008 (const char **) operators,command);
4010 compose=(CompositeOperator) ParseMagickOption(
4011 MagickComposeOptions,MagickFalse,operators[entry]);
4012 operators=DestroyStringList(operators);
4015 case CompositeDissolveCommand:
4018 factor[MaxTextExtent] = "20.0";
4021 Dissolve the two images a given percent.
4023 (void) XSetFunction(display,windows->image.highlight_context,
4025 (void) XDialogWidget(display,windows,"Dissolve",
4026 "Enter the blend factor (0.0 - 99.9%):",factor);
4027 (void) XSetFunction(display,windows->image.highlight_context,
4029 if (*factor == '\0')
4031 blend=StringToDouble(factor);
4032 compose=DissolveCompositeOp;
4035 case CompositeDisplaceCommand:
4038 Get horizontal and vertical scale displacement geometry.
4040 (void) XSetFunction(display,windows->image.highlight_context,
4042 (void) XDialogWidget(display,windows,"Displace",
4043 "Enter the horizontal and vertical scale:",displacement_geometry);
4044 (void) XSetFunction(display,windows->image.highlight_context,
4046 if (*displacement_geometry == '\0')
4048 compose=DisplaceCompositeOp;
4051 case CompositeHelpCommand:
4053 (void) XSetFunction(display,windows->image.highlight_context,
4055 XTextViewWidget(display,resource_info,windows,MagickFalse,
4056 "Help Viewer - Image Composite",ImageCompositeHelp);
4057 (void) XSetFunction(display,windows->image.highlight_context,
4061 case CompositeDismissCommand:
4079 if (image->debug != MagickFalse)
4080 (void) LogMagickEvent(X11Event,GetMagickModule(),
4081 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4082 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4083 if (event.xbutton.button != Button1)
4085 if (event.xbutton.window != windows->image.id)
4090 composite_info.width=composite_image->columns;
4091 composite_info.height=composite_image->rows;
4092 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4093 composite_info.x=windows->image.x+event.xbutton.x;
4094 composite_info.y=windows->image.y+event.xbutton.y;
4099 if (image->debug != MagickFalse)
4100 (void) LogMagickEvent(X11Event,GetMagickModule(),
4101 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4102 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4103 if (event.xbutton.button != Button1)
4105 if (event.xbutton.window != windows->image.id)
4107 if ((composite_info.width != 0) && (composite_info.height != 0))
4110 User has selected the location of the composite image.
4112 composite_info.x=windows->image.x+event.xbutton.x;
4113 composite_info.y=windows->image.y+event.xbutton.y;
4123 command[MaxTextExtent];
4131 if (event.xkey.window != windows->image.id)
4134 Respond to a user key press.
4136 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4137 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4138 *(command+length)='\0';
4139 if (image->debug != MagickFalse)
4140 (void) LogMagickEvent(X11Event,GetMagickModule(),
4141 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4142 switch ((int) key_symbol)
4150 composite_image=DestroyImage(composite_image);
4158 (void) XSetFunction(display,windows->image.highlight_context,
4160 XTextViewWidget(display,resource_info,windows,MagickFalse,
4161 "Help Viewer - Image Composite",ImageCompositeHelp);
4162 (void) XSetFunction(display,windows->image.highlight_context,
4168 (void) XBell(display,0);
4177 Map and unmap Info widget as text cursor crosses its boundaries.
4181 if (windows->info.mapped != MagickFalse)
4183 if ((x < (int) (windows->info.x+windows->info.width)) &&
4184 (y < (int) (windows->info.y+windows->info.height)))
4185 (void) XWithdrawWindow(display,windows->info.id,
4186 windows->info.screen);
4189 if ((x > (int) (windows->info.x+windows->info.width)) ||
4190 (y > (int) (windows->info.y+windows->info.height)))
4191 (void) XMapWindow(display,windows->info.id);
4192 composite_info.x=windows->image.x+x;
4193 composite_info.y=windows->image.y+y;
4198 if (image->debug != MagickFalse)
4199 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4204 } while ((state & ExitState) == 0);
4205 (void) XSelectInput(display,windows->image.id,
4206 windows->image.attributes.event_mask);
4207 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4208 XSetCursorState(display,windows,MagickFalse);
4209 (void) XFreeCursor(display,cursor);
4210 if ((state & EscapeState) != 0)
4213 Image compositing is relative to image configuration.
4215 XSetCursorState(display,windows,MagickTrue);
4216 XCheckRefreshWindows(display,windows);
4217 width=(unsigned int) image->columns;
4218 height=(unsigned int) image->rows;
4221 if (windows->image.crop_geometry != (char *) NULL)
4222 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4223 scale_factor=(MagickRealType) width/windows->image.ximage->width;
4224 composite_info.x+=x;
4225 composite_info.x=(int) (scale_factor*composite_info.x+0.5);
4226 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4227 scale_factor=(MagickRealType) height/windows->image.ximage->height;
4228 composite_info.y+=y;
4229 composite_info.y=(int) (scale_factor*composite_info.y+0.5);
4230 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4231 if ((composite_info.width != composite_image->columns) ||
4232 (composite_info.height != composite_image->rows))
4238 Scale composite image.
4240 resize_image=ZoomImage(composite_image,composite_info.width,
4241 composite_info.height,&image->exception);
4242 composite_image=DestroyImage(composite_image);
4243 if (resize_image == (Image *) NULL)
4245 XSetCursorState(display,windows,MagickFalse);
4246 return(MagickFalse);
4248 composite_image=resize_image;
4250 if (compose == DisplaceCompositeOp)
4251 (void) SetImageArtifact(composite_image,"compose:args",
4252 displacement_geometry);
4267 register PixelPacket
4271 Create mattes for blending.
4273 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel);
4274 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
4275 ((long) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
4276 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
4277 return(MagickFalse);
4278 image->matte=MagickTrue;
4279 exception=(&image->exception);
4280 for (y=0; y < (long) image->rows; y++)
4282 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
4283 if (q == (PixelPacket *) NULL)
4285 for (x=0; x < (int) image->columns; x++)
4290 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4295 Composite image with X Image window.
4297 (void) CompositeImage(image,compose,composite_image,composite_info.x,
4299 composite_image=DestroyImage(composite_image);
4300 XSetCursorState(display,windows,MagickFalse);
4302 Update image configuration.
4304 XConfigureImageColormap(display,resource_info,windows,image);
4305 (void) XConfigureImage(display,resource_info,windows,image);
4310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4314 + X C o n f i g u r e I m a g e %
4318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4320 % XConfigureImage() creates a new X image. It also notifies the window
4321 % manager of the new image size and configures the transient widows.
4323 % The format of the XConfigureImage method is:
4325 % MagickBooleanType XConfigureImage(Display *display,
4326 % XResourceInfo *resource_info,XWindows *windows,Image *image)
4328 % A description of each parameter follows:
4330 % o display: Specifies a connection to an X server; returned from
4333 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4335 % o windows: Specifies a pointer to a XWindows structure.
4337 % o image: the image.
4341 static MagickBooleanType XConfigureImage(Display *display,
4342 XResourceInfo *resource_info,XWindows *windows,Image *image)
4345 geometry[MaxTextExtent];
4366 Dismiss if window dimensions are zero.
4368 width=(unsigned int) windows->image.window_changes.width;
4369 height=(unsigned int) windows->image.window_changes.height;
4370 if (image->debug != MagickFalse)
4371 (void) LogMagickEvent(X11Event,GetMagickModule(),
4372 "Configure Image: %dx%d=>%lux%lu",windows->image.ximage->width,
4373 windows->image.ximage->height,width,height);
4374 if ((width*height) == 0)
4379 Resize image to fit Image window dimensions.
4381 XSetCursorState(display,windows,MagickTrue);
4382 (void) XFlush(display);
4383 if (((int) width != windows->image.ximage->width) ||
4384 ((int) height != windows->image.ximage->height))
4385 image->taint=MagickTrue;
4386 windows->magnify.x=(int)
4387 width*windows->magnify.x/windows->image.ximage->width;
4388 windows->magnify.y=(int)
4389 height*windows->magnify.y/windows->image.ximage->height;
4390 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4391 windows->image.y=(int)
4392 (height*windows->image.y/windows->image.ximage->height);
4393 status=XMakeImage(display,resource_info,&windows->image,image,
4394 (unsigned int) width,(unsigned int) height);
4395 if (status == MagickFalse)
4396 XNoticeWidget(display,windows,"Unable to configure X image:",
4397 windows->image.name);
4399 Notify window manager of the new configuration.
4401 if (resource_info->image_geometry != (char *) NULL)
4402 (void) FormatMagickString(geometry,MaxTextExtent,"%s>!",
4403 resource_info->image_geometry);
4405 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4406 XDisplayWidth(display,windows->image.screen),
4407 XDisplayHeight(display,windows->image.screen));
4408 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4409 window_changes.width=(int) width;
4410 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4411 window_changes.width=XDisplayWidth(display,windows->image.screen);
4412 window_changes.height=(int) height;
4413 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4414 window_changes.height=XDisplayHeight(display,windows->image.screen);
4415 mask=(unsigned long) (CWWidth | CWHeight);
4416 if (resource_info->backdrop)
4419 window_changes.x=(int)
4420 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4421 window_changes.y=(int)
4422 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4424 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4425 (unsigned int) mask,&window_changes);
4426 (void) XClearWindow(display,windows->image.id);
4427 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4429 Update Magnify window configuration.
4431 if (windows->magnify.mapped != MagickFalse)
4432 XMakeMagnifyImage(display,windows);
4433 windows->pan.crop_geometry=windows->image.crop_geometry;
4434 XBestIconSize(display,&windows->pan,image);
4435 while (((windows->pan.width << 1) < MaxIconSize) &&
4436 ((windows->pan.height << 1) < MaxIconSize))
4438 windows->pan.width<<=1;
4439 windows->pan.height<<=1;
4441 if (windows->pan.geometry != (char *) NULL)
4442 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4443 &windows->pan.width,&windows->pan.height);
4444 window_changes.width=(int) windows->pan.width;
4445 window_changes.height=(int) windows->pan.height;
4446 size_hints=XAllocSizeHints();
4447 if (size_hints != (XSizeHints *) NULL)
4452 size_hints->flags=PSize | PMinSize | PMaxSize;
4453 size_hints->width=window_changes.width;
4454 size_hints->height=window_changes.height;
4455 size_hints->min_width=size_hints->width;
4456 size_hints->min_height=size_hints->height;
4457 size_hints->max_width=size_hints->width;
4458 size_hints->max_height=size_hints->height;
4459 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4460 (void) XFree((void *) size_hints);
4462 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4463 (unsigned int) (CWWidth | CWHeight),&window_changes);
4465 Update icon window configuration.
4467 windows->icon.crop_geometry=windows->image.crop_geometry;
4468 XBestIconSize(display,&windows->icon,image);
4469 window_changes.width=(int) windows->icon.width;
4470 window_changes.height=(int) windows->icon.height;
4471 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4472 (unsigned int) (CWWidth | CWHeight),&window_changes);
4473 XSetCursorState(display,windows,MagickFalse);
4474 return(status != 0 ? MagickTrue : MagickFalse);
4478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4482 + X C r o p I m a g e %
4486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4488 % XCropImage() allows the user to select a region of the image and crop, copy,
4489 % or cut it. For copy or cut, the image can subsequently be composited onto
4490 % the image with XPasteImage.
4492 % The format of the XCropImage method is:
4494 % MagickBooleanType XCropImage(Display *display,
4495 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4496 % const ClipboardMode mode)
4498 % A description of each parameter follows:
4500 % o display: Specifies a connection to an X server; returned from
4503 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4505 % o windows: Specifies a pointer to a XWindows structure.
4507 % o image: the image; returned from ReadImage.
4509 % o mode: This unsigned value specified whether the image should be
4510 % cropped, copied, or cut.
4513 static MagickBooleanType XCropImage(Display *display,
4514 XResourceInfo *resource_info,XWindows *windows,Image *image,
4515 const ClipboardMode mode)
4524 *RectifyModeMenu[] =
4532 static const ModeType
4542 RectifyDismissCommand
4546 command[MaxTextExtent],
4547 text[MaxTextExtent];
4573 register PixelPacket
4593 (void) CloneString(&windows->command.name,"Copy");
4598 (void) CloneString(&windows->command.name,"Crop");
4603 (void) CloneString(&windows->command.name,"Cut");
4607 RectifyModeMenu[0]=windows->command.name;
4608 windows->command.data=0;
4609 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4610 (void) XMapRaised(display,windows->command.id);
4611 XClientMessage(display,windows->image.id,windows->im_protocols,
4612 windows->im_update_widget,CurrentTime);
4614 Track pointer until button 1 is pressed.
4616 XQueryPosition(display,windows->image.id,&x,&y);
4617 (void) XSelectInput(display,windows->image.id,
4618 windows->image.attributes.event_mask | PointerMotionMask);
4619 crop_info.x=windows->image.x+x;
4620 crop_info.y=windows->image.y+y;
4623 cursor=XCreateFontCursor(display,XC_fleur);
4627 if (windows->info.mapped != MagickFalse)
4630 Display pointer position.
4632 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
4633 crop_info.x,crop_info.y);
4634 XInfoWidget(display,windows,text);
4637 Wait for next event.
4639 XScreenEvent(display,windows,&event);
4640 if (event.xany.window == windows->command.id)
4643 Select a command from the Command widget.
4645 id=XCommandWidget(display,windows,CropModeMenu,&event);
4648 switch (CropCommands[id])
4650 case CropHelpCommand:
4656 XTextViewWidget(display,resource_info,windows,MagickFalse,
4657 "Help Viewer - Image Copy",ImageCopyHelp);
4662 XTextViewWidget(display,resource_info,windows,MagickFalse,
4663 "Help Viewer - Image Crop",ImageCropHelp);
4668 XTextViewWidget(display,resource_info,windows,MagickFalse,
4669 "Help Viewer - Image Cut",ImageCutHelp);
4675 case CropDismissCommand:
4693 if (event.xbutton.button != Button1)
4695 if (event.xbutton.window != windows->image.id)
4698 Note first corner of cropping rectangle-- exit loop.
4700 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4701 crop_info.x=windows->image.x+event.xbutton.x;
4702 crop_info.y=windows->image.y+event.xbutton.y;
4712 if (event.xkey.window != windows->image.id)
4715 Respond to a user key press.
4717 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4718 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4719 switch ((int) key_symbol)
4738 XTextViewWidget(display,resource_info,windows,MagickFalse,
4739 "Help Viewer - Image Copy",ImageCopyHelp);
4744 XTextViewWidget(display,resource_info,windows,MagickFalse,
4745 "Help Viewer - Image Crop",ImageCropHelp);
4750 XTextViewWidget(display,resource_info,windows,MagickFalse,
4751 "Help Viewer - Image Cut",ImageCutHelp);
4759 (void) XBell(display,0);
4767 if (event.xmotion.window != windows->image.id)
4770 Map and unmap Info widget as text cursor crosses its boundaries.
4774 if (windows->info.mapped != MagickFalse)
4776 if ((x < (int) (windows->info.x+windows->info.width)) &&
4777 (y < (int) (windows->info.y+windows->info.height)))
4778 (void) XWithdrawWindow(display,windows->info.id,
4779 windows->info.screen);
4782 if ((x > (int) (windows->info.x+windows->info.width)) ||
4783 (y > (int) (windows->info.y+windows->info.height)))
4784 (void) XMapWindow(display,windows->info.id);
4785 crop_info.x=windows->image.x+x;
4786 crop_info.y=windows->image.y+y;
4792 } while ((state & ExitState) == 0);
4793 (void) XSelectInput(display,windows->image.id,
4794 windows->image.attributes.event_mask);
4795 if ((state & EscapeState) != 0)
4798 User want to exit without cropping.
4800 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4801 (void) XFreeCursor(display,cursor);
4804 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4808 Size rectangle as pointer moves until the mouse button is released.
4810 x=(int) crop_info.x;
4811 y=(int) crop_info.y;
4817 highlight_info=crop_info;
4818 highlight_info.x=crop_info.x-windows->image.x;
4819 highlight_info.y=crop_info.y-windows->image.y;
4820 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4823 Display info and draw cropping rectangle.
4825 if (windows->info.mapped == MagickFalse)
4826 (void) XMapWindow(display,windows->info.id);
4827 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
4828 crop_info.width,crop_info.height,crop_info.x,crop_info.y);
4829 XInfoWidget(display,windows,text);
4830 XHighlightRectangle(display,windows->image.id,
4831 windows->image.highlight_context,&highlight_info);
4834 if (windows->info.mapped != MagickFalse)
4835 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4837 Wait for next event.
4839 XScreenEvent(display,windows,&event);
4840 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4841 XHighlightRectangle(display,windows->image.id,
4842 windows->image.highlight_context,&highlight_info);
4847 crop_info.x=windows->image.x+event.xbutton.x;
4848 crop_info.y=windows->image.y+event.xbutton.y;
4854 User has committed to cropping rectangle.
4856 crop_info.x=windows->image.x+event.xbutton.x;
4857 crop_info.y=windows->image.y+event.xbutton.y;
4858 XSetCursorState(display,windows,MagickFalse);
4860 windows->command.data=0;
4861 (void) XCommandWidget(display,windows,RectifyModeMenu,
4869 crop_info.x=windows->image.x+event.xmotion.x;
4870 crop_info.y=windows->image.y+event.xmotion.y;
4875 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4876 ((state & ExitState) != 0))
4879 Check boundary conditions.
4881 if (crop_info.x < 0)
4884 if (crop_info.x > (int) windows->image.ximage->width)
4885 crop_info.x=windows->image.ximage->width;
4886 if ((int) crop_info.x < x)
4887 crop_info.width=(unsigned int) (x-crop_info.x);
4890 crop_info.width=(unsigned int) (crop_info.x-x);
4893 if (crop_info.y < 0)
4896 if (crop_info.y > (int) windows->image.ximage->height)
4897 crop_info.y=windows->image.ximage->height;
4898 if ((int) crop_info.y < y)
4899 crop_info.height=(unsigned int) (y-crop_info.y);
4902 crop_info.height=(unsigned int) (crop_info.y-y);
4906 } while ((state & ExitState) == 0);
4908 Wait for user to grab a corner of the rectangle or press return.
4911 (void) XMapWindow(display,windows->info.id);
4914 if (windows->info.mapped != MagickFalse)
4917 Display pointer position.
4919 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
4920 crop_info.width,crop_info.height,crop_info.x,crop_info.y);
4921 XInfoWidget(display,windows,text);
4923 highlight_info=crop_info;
4924 highlight_info.x=crop_info.x-windows->image.x;
4925 highlight_info.y=crop_info.y-windows->image.y;
4926 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
4932 XHighlightRectangle(display,windows->image.id,
4933 windows->image.highlight_context,&highlight_info);
4934 XScreenEvent(display,windows,&event);
4935 if (event.xany.window == windows->command.id)
4938 Select a command from the Command widget.
4940 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4941 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
4942 (void) XSetFunction(display,windows->image.highlight_context,
4944 XHighlightRectangle(display,windows->image.id,
4945 windows->image.highlight_context,&highlight_info);
4947 switch (RectifyCommands[id])
4949 case RectifyCopyCommand:
4954 case RectifyHelpCommand:
4956 (void) XSetFunction(display,windows->image.highlight_context,
4962 XTextViewWidget(display,resource_info,windows,MagickFalse,
4963 "Help Viewer - Image Copy",ImageCopyHelp);
4968 XTextViewWidget(display,resource_info,windows,MagickFalse,
4969 "Help Viewer - Image Crop",ImageCropHelp);
4974 XTextViewWidget(display,resource_info,windows,MagickFalse,
4975 "Help Viewer - Image Cut",ImageCutHelp);
4979 (void) XSetFunction(display,windows->image.highlight_context,
4983 case RectifyDismissCommand:
4997 XHighlightRectangle(display,windows->image.id,
4998 windows->image.highlight_context,&highlight_info);
5003 if (event.xbutton.button != Button1)
5005 if (event.xbutton.window != windows->image.id)
5007 x=windows->image.x+event.xbutton.x;
5008 y=windows->image.y+event.xbutton.y;
5009 if ((x < (int) (crop_info.x+RoiDelta)) &&
5010 (x > (int) (crop_info.x-RoiDelta)) &&
5011 (y < (int) (crop_info.y+RoiDelta)) &&
5012 (y > (int) (crop_info.y-RoiDelta)))
5014 crop_info.x=(long) (crop_info.x+crop_info.width);
5015 crop_info.y=(long) (crop_info.y+crop_info.height);
5016 state|=UpdateConfigurationState;
5019 if ((x < (int) (crop_info.x+RoiDelta)) &&
5020 (x > (int) (crop_info.x-RoiDelta)) &&
5021 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5022 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5024 crop_info.x=(long) (crop_info.x+crop_info.width);
5025 state|=UpdateConfigurationState;
5028 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5029 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5030 (y < (int) (crop_info.y+RoiDelta)) &&
5031 (y > (int) (crop_info.y-RoiDelta)))
5033 crop_info.y=(long) (crop_info.y+crop_info.height);
5034 state|=UpdateConfigurationState;
5037 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5038 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5039 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5040 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5042 state|=UpdateConfigurationState;
5048 if (event.xbutton.window == windows->pan.id)
5049 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5050 (highlight_info.y != crop_info.y-windows->image.y))
5051 XHighlightRectangle(display,windows->image.id,
5052 windows->image.highlight_context,&highlight_info);
5053 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5054 event.xbutton.time);
5059 if (event.xexpose.window == windows->image.id)
5060 if (event.xexpose.count == 0)
5062 event.xexpose.x=(int) highlight_info.x;
5063 event.xexpose.y=(int) highlight_info.y;
5064 event.xexpose.width=(int) highlight_info.width;
5065 event.xexpose.height=(int) highlight_info.height;
5066 XRefreshWindow(display,&windows->image,&event);
5068 if (event.xexpose.window == windows->info.id)
5069 if (event.xexpose.count == 0)
5070 XInfoWidget(display,windows,text);
5075 if (event.xkey.window != windows->image.id)
5078 Respond to a user key press.
5080 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5081 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5082 switch ((int) key_symbol)
5095 crop_info.x=(long) (windows->image.width/2L-crop_info.width/2L);
5096 crop_info.y=(long) (windows->image.height/2L-crop_info.height/2L);
5128 (void) XSetFunction(display,windows->image.highlight_context,
5134 XTextViewWidget(display,resource_info,windows,MagickFalse,
5135 "Help Viewer - Image Copy",ImageCopyHelp);
5140 XTextViewWidget(display,resource_info,windows,MagickFalse,
5141 "Help Viewer - Image Cropg",ImageCropHelp);
5146 XTextViewWidget(display,resource_info,windows,MagickFalse,
5147 "Help Viewer - Image Cutg",ImageCutHelp);
5151 (void) XSetFunction(display,windows->image.highlight_context,
5157 (void) XBell(display,0);
5161 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5169 if (event.xmotion.window != windows->image.id)
5172 Map and unmap Info widget as text cursor crosses its boundaries.
5176 if (windows->info.mapped != MagickFalse)
5178 if ((x < (int) (windows->info.x+windows->info.width)) &&
5179 (y < (int) (windows->info.y+windows->info.height)))
5180 (void) XWithdrawWindow(display,windows->info.id,
5181 windows->info.screen);
5184 if ((x > (int) (windows->info.x+windows->info.width)) ||
5185 (y > (int) (windows->info.y+windows->info.height)))
5186 (void) XMapWindow(display,windows->info.id);
5187 crop_info.x=windows->image.x+event.xmotion.x;
5188 crop_info.y=windows->image.y+event.xmotion.y;
5191 case SelectionRequest:
5196 XSelectionRequestEvent
5200 Set primary selection.
5202 (void) FormatMagickString(text,MaxTextExtent,"%lux%lu%+ld%+ld",
5203 crop_info.width,crop_info.height,crop_info.x,crop_info.y);
5204 request=(&(event.xselectionrequest));
5205 (void) XChangeProperty(request->display,request->requestor,
5206 request->property,request->target,8,PropModeReplace,
5207 (unsigned char *) text,(int) strlen(text));
5208 notify.type=SelectionNotify;
5209 notify.display=request->display;
5210 notify.requestor=request->requestor;
5211 notify.selection=request->selection;
5212 notify.target=request->target;
5213 notify.time=request->time;
5214 if (request->property == None)
5215 notify.property=request->target;
5217 notify.property=request->property;
5218 (void) XSendEvent(request->display,request->requestor,False,0,
5219 (XEvent *) ¬ify);
5224 if ((state & UpdateConfigurationState) != 0)
5226 (void) XPutBackEvent(display,&event);
5227 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5230 } while ((state & ExitState) == 0);
5231 } while ((state & ExitState) == 0);
5232 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5233 XSetCursorState(display,windows,MagickFalse);
5234 if ((state & EscapeState) != 0)
5236 if (mode == CropMode)
5237 if (((int) crop_info.width != windows->image.ximage->width) ||
5238 ((int) crop_info.height != windows->image.ximage->height))
5241 Reconfigure Image window as defined by cropping rectangle.
5243 XSetCropGeometry(display,windows,&crop_info,image);
5244 windows->image.window_changes.width=(int) crop_info.width;
5245 windows->image.window_changes.height=(int) crop_info.height;
5246 (void) XConfigureImage(display,resource_info,windows,image);
5250 Copy image before applying image transforms.
5252 XSetCursorState(display,windows,MagickTrue);
5253 XCheckRefreshWindows(display,windows);
5254 width=(unsigned int) image->columns;
5255 height=(unsigned int) image->rows;
5258 if (windows->image.crop_geometry != (char *) NULL)
5259 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5260 scale_factor=(MagickRealType) width/windows->image.ximage->width;
5262 crop_info.x=(int) (scale_factor*crop_info.x+0.5);
5263 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5264 scale_factor=(MagickRealType) height/windows->image.ximage->height;
5266 crop_info.y=(int) (scale_factor*crop_info.y+0.5);
5267 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5268 crop_image=CropImage(image,&crop_info,&image->exception);
5269 XSetCursorState(display,windows,MagickFalse);
5270 if (crop_image == (Image *) NULL)
5271 return(MagickFalse);
5272 if (resource_info->copy_image != (Image *) NULL)
5273 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5274 resource_info->copy_image=crop_image;
5275 if (mode == CopyMode)
5277 (void) XConfigureImage(display,resource_info,windows,image);
5283 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
5284 return(MagickFalse);
5285 image->matte=MagickTrue;
5286 exception=(&image->exception);
5287 for (y=0; y < (long) crop_info.height; y++)
5289 q=GetAuthenticPixels(image,crop_info.x,y+crop_info.y,crop_info.width,1,
5291 if (q == (PixelPacket *) NULL)
5293 for (x=0; x < (int) crop_info.width; x++)
5295 q->opacity=(Quantum) TransparentOpacity;
5298 if (SyncAuthenticPixels(image,exception) == MagickFalse)
5302 Update image configuration.
5304 XConfigureImageColormap(display,resource_info,windows,image);
5305 (void) XConfigureImage(display,resource_info,windows,image);
5310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5314 + X D r a w I m a g e %
5318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5320 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5323 % The format of the XDrawEditImage method is:
5325 % MagickBooleanType XDrawEditImage(Display *display,
5326 % XResourceInfo *resource_info,XWindows *windows,Image **image)
5328 % A description of each parameter follows:
5330 % o display: Specifies a connection to an X server; returned from
5333 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5335 % o windows: Specifies a pointer to a XWindows structure.
5337 % o image: the image.
5340 static MagickBooleanType XDrawEditImage(Display *display,
5341 XResourceInfo *resource_info,XWindows *windows,Image **image)
5357 element = PointElement;
5359 static const ModeType
5372 stipple = (Pixmap) NULL;
5379 command[MaxTextExtent],
5380 text[MaxTextExtent];
5429 Allocate polygon info.
5431 max_coordinates=2048;
5432 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5433 sizeof(*coordinate_info));
5434 if (coordinate_info == (XPoint *) NULL)
5436 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
5437 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5438 return(MagickFalse);
5443 (void) CloneString(&windows->command.name,"Draw");
5444 windows->command.data=4;
5445 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5446 (void) XMapRaised(display,windows->command.id);
5447 XClientMessage(display,windows->image.id,windows->im_protocols,
5448 windows->im_update_widget,CurrentTime);
5450 Wait for first button press.
5452 root_window=XRootWindow(display,XDefaultScreen(display));
5453 draw_info.stencil=OpaqueStencil;
5455 cursor=XCreateFontCursor(display,XC_tcross);
5458 XQueryPosition(display,windows->image.id,&x,&y);
5459 (void) XSelectInput(display,windows->image.id,
5460 windows->image.attributes.event_mask | PointerMotionMask);
5461 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5465 if (windows->info.mapped != MagickFalse)
5468 Display pointer position.
5470 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
5471 x+windows->image.x,y+windows->image.y);
5472 XInfoWidget(display,windows,text);
5475 Wait for next event.
5477 XScreenEvent(display,windows,&event);
5478 if (event.xany.window == windows->command.id)
5481 Select a command from the Command widget.
5483 id=XCommandWidget(display,windows,DrawMenu,&event);
5486 switch (DrawCommands[id])
5488 case DrawElementCommand:
5507 Select a command from the pop-up menu.
5509 element=(ElementType) (XMenuWidget(display,windows,
5510 DrawMenu[id],Elements,command)+1);
5513 case DrawColorCommand:
5516 *ColorMenu[MaxNumberPens+1];
5528 Initialize menu selections.
5530 for (i=0; i < (int) (MaxNumberPens-2); i++)
5531 ColorMenu[i]=resource_info->pen_colors[i];
5532 ColorMenu[MaxNumberPens-2]="transparent";
5533 ColorMenu[MaxNumberPens-1]="Browser...";
5534 ColorMenu[MaxNumberPens]=(char *) NULL;
5536 Select a pen color from the pop-up menu.
5538 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5539 (const char **) ColorMenu,command);
5542 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5544 if (transparent != MagickFalse)
5546 draw_info.stencil=TransparentStencil;
5549 if (pen_number == (MaxNumberPens-1))
5552 color_name[MaxTextExtent] = "gray";
5555 Select a pen color from a dialog.
5557 resource_info->pen_colors[pen_number]=color_name;
5558 XColorBrowserWidget(display,windows,"Select",color_name);
5559 if (*color_name == '\0')
5565 (void) XParseColor(display,windows->map_info->colormap,
5566 resource_info->pen_colors[pen_number],&color);
5567 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5568 (unsigned int) MaxColors,&color);
5569 windows->pixel_info->pen_colors[pen_number]=color;
5570 pen_id=(unsigned int) pen_number;
5571 draw_info.stencil=OpaqueStencil;
5574 case DrawStippleCommand:
5586 filename[MaxTextExtent] = "\0";
5603 Select a command from the pop-up menu.
5605 StipplesMenu[7]="Open...";
5606 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5610 if (stipple != (Pixmap) NULL)
5611 (void) XFreePixmap(display,stipple);
5612 stipple=(Pixmap) NULL;
5621 stipple=XCreateBitmapFromData(display,root_window,
5622 (char *) BricksBitmap,BricksWidth,BricksHeight);
5627 stipple=XCreateBitmapFromData(display,root_window,
5628 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5633 stipple=XCreateBitmapFromData(display,root_window,
5634 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5639 stipple=XCreateBitmapFromData(display,root_window,
5640 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5645 stipple=XCreateBitmapFromData(display,root_window,
5646 (char *) WavyBitmap,WavyWidth,WavyHeight);
5652 stipple=XCreateBitmapFromData(display,root_window,
5653 (char *) HighlightBitmap,HighlightWidth,
5660 XFileBrowserWidget(display,windows,"Stipple",filename);
5661 if (*filename == '\0')
5666 XSetCursorState(display,windows,MagickTrue);
5667 XCheckRefreshWindows(display,windows);
5668 image_info=AcquireImageInfo();
5669 (void) CopyMagickString(image_info->filename,filename,
5671 stipple_image=ReadImage(image_info,&(*image)->exception);
5672 CatchException(&(*image)->exception);
5673 XSetCursorState(display,windows,MagickFalse);
5674 if (stipple_image == (Image *) NULL)
5676 (void) AcquireUniqueFileResource(filename);
5677 (void) FormatMagickString(stipple_image->filename,MaxTextExtent,
5679 (void) WriteImage(image_info,stipple_image);
5680 stipple_image=DestroyImage(stipple_image);
5681 image_info=DestroyImageInfo(image_info);
5682 status=XReadBitmapFile(display,root_window,filename,&width,
5683 &height,&stipple,&x,&y);
5684 (void) RelinquishUniqueFileResource(filename);
5685 if ((status != BitmapSuccess) != 0)
5686 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5690 case DrawWidthCommand:
5693 width[MaxTextExtent] = "0";
5708 Select a command from the pop-up menu.
5710 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5716 line_width=(unsigned int) StringToUnsignedLong(WidthsMenu[entry]);
5719 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5723 line_width=(unsigned int) StringToUnsignedLong(width);
5726 case DrawUndoCommand:
5728 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5732 case DrawHelpCommand:
5734 XTextViewWidget(display,resource_info,windows,MagickFalse,
5735 "Help Viewer - Image Rotation",ImageDrawHelp);
5736 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5739 case DrawDismissCommand:
5751 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5758 if (event.xbutton.button != Button1)
5760 if (event.xbutton.window != windows->image.id)
5779 if (event.xkey.window != windows->image.id)
5782 Respond to a user key press.
5784 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5785 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5786 switch ((int) key_symbol)
5801 XTextViewWidget(display,resource_info,windows,MagickFalse,
5802 "Help Viewer - Image Rotation",ImageDrawHelp);
5807 (void) XBell(display,0);
5816 Map and unmap Info widget as text cursor crosses its boundaries.
5820 if (windows->info.mapped != MagickFalse)
5822 if ((x < (int) (windows->info.x+windows->info.width)) &&
5823 (y < (int) (windows->info.y+windows->info.height)))
5824 (void) XWithdrawWindow(display,windows->info.id,
5825 windows->info.screen);
5828 if ((x > (int) (windows->info.x+windows->info.width)) ||
5829 (y > (int) (windows->info.y+windows->info.height)))
5830 (void) XMapWindow(display,windows->info.id);
5834 } while ((state & ExitState) == 0);
5835 (void) XSelectInput(display,windows->image.id,
5836 windows->image.attributes.event_mask);
5837 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5838 if ((state & EscapeState) != 0)
5841 Draw element as pointer moves until the button is released.
5851 rectangle_info.width=0;
5852 rectangle_info.height=0;
5853 number_coordinates=1;
5854 coordinate_info->x=x;
5855 coordinate_info->y=y;
5856 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5865 if (number_coordinates > 1)
5867 (void) XDrawLines(display,windows->image.id,
5868 windows->image.highlight_context,coordinate_info,
5869 number_coordinates,CoordModeOrigin);
5870 (void) FormatMagickString(text,MaxTextExtent," %+d%+d",
5871 coordinate_info[number_coordinates-1].x,
5872 coordinate_info[number_coordinates-1].y);
5873 XInfoWidget(display,windows,text);
5882 Display angle of the line.
5884 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5885 line_info.y1),(double) (line_info.x2-line_info.x1)));
5886 (void) FormatMagickString(text,MaxTextExtent," %g",
5888 XInfoWidget(display,windows,text);
5889 XHighlightLine(display,windows->image.id,
5890 windows->image.highlight_context,&line_info);
5893 if (windows->info.mapped != MagickFalse)
5894 (void) XWithdrawWindow(display,windows->info.id,
5895 windows->info.screen);
5898 case RectangleElement:
5899 case FillRectangleElement:
5901 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5904 Display info and draw drawing rectangle.
5906 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
5907 rectangle_info.width,rectangle_info.height,rectangle_info.x,
5909 XInfoWidget(display,windows,text);
5910 XHighlightRectangle(display,windows->image.id,
5911 windows->image.highlight_context,&rectangle_info);
5914 if (windows->info.mapped != MagickFalse)
5915 (void) XWithdrawWindow(display,windows->info.id,
5916 windows->info.screen);
5920 case FillCircleElement:
5921 case EllipseElement:
5922 case FillEllipseElement:
5924 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5927 Display info and draw drawing rectangle.
5929 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
5930 rectangle_info.width,rectangle_info.height,rectangle_info.x,
5932 XInfoWidget(display,windows,text);
5933 XHighlightEllipse(display,windows->image.id,
5934 windows->image.highlight_context,&rectangle_info);
5937 if (windows->info.mapped != MagickFalse)
5938 (void) XWithdrawWindow(display,windows->info.id,
5939 windows->info.screen);
5942 case PolygonElement:
5943 case FillPolygonElement:
5945 if (number_coordinates > 1)
5946 (void) XDrawLines(display,windows->image.id,
5947 windows->image.highlight_context,coordinate_info,
5948 number_coordinates,CoordModeOrigin);
5952 Display angle of the line.
5954 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5955 line_info.y1),(double) (line_info.x2-line_info.x1)));
5956 (void) FormatMagickString(text,MaxTextExtent," %g",
5958 XInfoWidget(display,windows,text);
5959 XHighlightLine(display,windows->image.id,
5960 windows->image.highlight_context,&line_info);
5963 if (windows->info.mapped != MagickFalse)
5964 (void) XWithdrawWindow(display,windows->info.id,
5965 windows->info.screen);
5970 Wait for next event.
5972 XScreenEvent(display,windows,&event);
5978 if (number_coordinates > 1)
5979 (void) XDrawLines(display,windows->image.id,
5980 windows->image.highlight_context,coordinate_info,
5981 number_coordinates,CoordModeOrigin);
5987 XHighlightLine(display,windows->image.id,
5988 windows->image.highlight_context,&line_info);
5991 case RectangleElement:
5992 case FillRectangleElement:
5994 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5995 XHighlightRectangle(display,windows->image.id,
5996 windows->image.highlight_context,&rectangle_info);
6000 case FillCircleElement:
6001 case EllipseElement:
6002 case FillEllipseElement:
6004 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6005 XHighlightEllipse(display,windows->image.id,
6006 windows->image.highlight_context,&rectangle_info);
6009 case PolygonElement:
6010 case FillPolygonElement:
6012 if (number_coordinates > 1)
6013 (void) XDrawLines(display,windows->image.id,
6014 windows->image.highlight_context,coordinate_info,
6015 number_coordinates,CoordModeOrigin);
6017 XHighlightLine(display,windows->image.id,
6018 windows->image.highlight_context,&line_info);
6029 User has committed to element.
6031 line_info.x2=event.xbutton.x;
6032 line_info.y2=event.xbutton.y;
6033 rectangle_info.x=event.xbutton.x;
6034 rectangle_info.y=event.xbutton.y;
6035 coordinate_info[number_coordinates].x=event.xbutton.x;
6036 coordinate_info[number_coordinates].y=event.xbutton.y;
6037 if (((element != PolygonElement) &&
6038 (element != FillPolygonElement)) || (distance <= 9))
6043 number_coordinates++;
6044 if (number_coordinates < (int) max_coordinates)
6046 line_info.x1=event.xbutton.x;
6047 line_info.y1=event.xbutton.y;
6050 max_coordinates<<=1;
6051 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6052 max_coordinates,sizeof(*coordinate_info));
6053 if (coordinate_info == (XPoint *) NULL)
6054 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
6055 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6062 if (event.xmotion.window != windows->image.id)
6064 if (element != PointElement)
6066 line_info.x2=event.xmotion.x;
6067 line_info.y2=event.xmotion.y;
6068 rectangle_info.x=event.xmotion.x;
6069 rectangle_info.y=event.xmotion.y;
6072 coordinate_info[number_coordinates].x=event.xbutton.x;
6073 coordinate_info[number_coordinates].y=event.xbutton.y;
6074 number_coordinates++;
6075 if (number_coordinates < (int) max_coordinates)
6077 max_coordinates<<=1;
6078 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6079 max_coordinates,sizeof(*coordinate_info));
6080 if (coordinate_info == (XPoint *) NULL)
6081 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
6082 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6089 Check boundary conditions.
6091 if (line_info.x2 < 0)
6094 if (line_info.x2 > (int) windows->image.width)
6095 line_info.x2=(short) windows->image.width;
6096 if (line_info.y2 < 0)
6099 if (line_info.y2 > (int) windows->image.height)
6100 line_info.y2=(short) windows->image.height;
6101 distance=(unsigned int)
6102 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6103 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6104 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6105 ((state & ExitState) != 0))
6107 if (rectangle_info.x < 0)
6110 if (rectangle_info.x > (int) windows->image.width)
6111 rectangle_info.x=(long) windows->image.width;
6112 if ((int) rectangle_info.x < x)
6113 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6116 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6119 if (rectangle_info.y < 0)
6122 if (rectangle_info.y > (int) windows->image.height)
6123 rectangle_info.y=(long) windows->image.height;
6124 if ((int) rectangle_info.y < y)
6125 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6128 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6132 } while ((state & ExitState) == 0);
6133 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6134 if ((element == PointElement) || (element == PolygonElement) ||
6135 (element == FillPolygonElement))
6138 Determine polygon bounding box.
6140 rectangle_info.x=coordinate_info->x;
6141 rectangle_info.y=coordinate_info->y;
6142 x=coordinate_info->x;
6143 y=coordinate_info->y;
6144 for (i=1; i < number_coordinates; i++)
6146 if (coordinate_info[i].x > x)
6147 x=coordinate_info[i].x;
6148 if (coordinate_info[i].y > y)
6149 y=coordinate_info[i].y;
6150 if (coordinate_info[i].x < rectangle_info.x)
6151 rectangle_info.x=MagickMax(coordinate_info[i].x,0);
6152 if (coordinate_info[i].y < rectangle_info.y)
6153 rectangle_info.y=MagickMax(coordinate_info[i].y,0);
6155 rectangle_info.width=(unsigned long) (x-rectangle_info.x);
6156 rectangle_info.height=(unsigned long) (y-rectangle_info.y);
6157 for (i=0; i < number_coordinates; i++)
6159 coordinate_info[i].x-=rectangle_info.x;
6160 coordinate_info[i].y-=rectangle_info.y;
6167 if ((element == RectangleElement) ||
6168 (element == CircleElement) || (element == EllipseElement))
6170 rectangle_info.width--;
6171 rectangle_info.height--;
6174 Drawing is relative to image configuration.
6176 draw_info.x=(int) rectangle_info.x;
6177 draw_info.y=(int) rectangle_info.y;
6178 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6180 width=(unsigned int) (*image)->columns;
6181 height=(unsigned int) (*image)->rows;
6184 if (windows->image.crop_geometry != (char *) NULL)
6185 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6186 draw_info.x+=windows->image.x-(line_width/2);
6187 if (draw_info.x < 0)
6189 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6190 draw_info.y+=windows->image.y-(line_width/2);
6191 if (draw_info.y < 0)
6193 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6194 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6195 if (draw_info.width > (unsigned int) (*image)->columns)
6196 draw_info.width=(unsigned int) (*image)->columns;
6197 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6198 if (draw_info.height > (unsigned int) (*image)->rows)
6199 draw_info.height=(unsigned int) (*image)->rows;
6200 (void) FormatMagickString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6201 width*draw_info.width/windows->image.ximage->width,
6202 height*draw_info.height/windows->image.ximage->height,
6203 draw_info.x+x,draw_info.y+y);
6205 Initialize drawing attributes.
6207 draw_info.degrees=0.0;
6208 draw_info.element=element;
6209 draw_info.stipple=stipple;
6210 draw_info.line_width=line_width;
6211 draw_info.line_info=line_info;
6212 if (line_info.x1 > (int) (line_width/2))
6213 draw_info.line_info.x1=(short) line_width/2;
6214 if (line_info.y1 > (int) (line_width/2))
6215 draw_info.line_info.y1=(short) line_width/2;
6216 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6217 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6218 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6220 draw_info.line_info.x2=(-draw_info.line_info.x2);
6221 draw_info.line_info.y2=(-draw_info.line_info.y2);
6223 if (draw_info.line_info.x2 < 0)
6225 draw_info.line_info.x2=(-draw_info.line_info.x2);
6226 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6228 if (draw_info.line_info.y2 < 0)
6230 draw_info.line_info.y2=(-draw_info.line_info.y2);
6231 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6233 draw_info.rectangle_info=rectangle_info;
6234 if (draw_info.rectangle_info.x > (int) (line_width/2))
6235 draw_info.rectangle_info.x=(long) line_width/2;
6236 if (draw_info.rectangle_info.y > (int) (line_width/2))
6237 draw_info.rectangle_info.y=(long) line_width/2;
6238 draw_info.number_coordinates=(unsigned int) number_coordinates;
6239 draw_info.coordinate_info=coordinate_info;
6240 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6242 Draw element on image.
6244 XSetCursorState(display,windows,MagickTrue);
6245 XCheckRefreshWindows(display,windows);
6246 status=XDrawImage(display,windows->pixel_info,&draw_info,*image);
6247 XSetCursorState(display,windows,MagickFalse);
6249 Update image colormap and return to image drawing.
6251 XConfigureImageColormap(display,resource_info,windows,*image);
6252 (void) XConfigureImage(display,resource_info,windows,*image);
6254 XSetCursorState(display,windows,MagickFalse);
6255 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6256 return(status != 0 ? MagickTrue : MagickFalse);
6260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6264 + X D r a w P a n R e c t a n g l e %
6268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6270 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6271 % displays a zoom image and the rectangle shows which portion of the image is
6272 % displayed in the Image window.
6274 % The format of the XDrawPanRectangle method is:
6276 % XDrawPanRectangle(Display *display,XWindows *windows)
6278 % A description of each parameter follows:
6280 % o display: Specifies a connection to an X server; returned from
6283 % o windows: Specifies a pointer to a XWindows structure.
6286 static void XDrawPanRectangle(Display *display,XWindows *windows)
6295 Determine dimensions of the panning rectangle.
6297 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
6298 highlight_info.x=(int) (scale_factor*windows->image.x+0.5);
6299 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6300 scale_factor=(MagickRealType)
6301 windows->pan.height/windows->image.ximage->height;
6302 highlight_info.y=(int) (scale_factor*windows->image.y+0.5);
6303 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6305 Display the panning rectangle.
6307 (void) XClearWindow(display,windows->pan.id);
6308 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6317 + X I m a g e C a c h e %
6321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6323 % XImageCache() handles the creation, manipulation, and destruction of the
6324 % image cache (undo and redo buffers).
6326 % The format of the XImageCache method is:
6328 % void XImageCache(Display *display,XResourceInfo *resource_info,
6329 % XWindows *windows,const CommandType command,Image **image)
6331 % A description of each parameter follows:
6333 % o display: Specifies a connection to an X server; returned from
6336 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6338 % o windows: Specifies a pointer to a XWindows structure.
6340 % o command: Specifies a command to perform.
6342 % o image: the image; XImageCache
6343 % may transform the image and return a new image pointer.
6346 static void XImageCache(Display *display,XResourceInfo *resource_info,
6347 XWindows *windows,const CommandType command,Image **image)
6353 *redo_image = (Image *) NULL,
6354 *undo_image = (Image *) NULL;
6358 case FreeBuffersCommand:
6361 Free memory from the undo and redo cache.
6363 while (undo_image != (Image *) NULL)
6365 cache_image=undo_image;
6366 undo_image=GetPreviousImageInList(undo_image);
6367 cache_image->list=DestroyImage(cache_image->list);
6368 cache_image=DestroyImage(cache_image);
6370 undo_image=NewImageList();
6371 if (redo_image != (Image *) NULL)
6372 redo_image=DestroyImage(redo_image);
6373 redo_image=NewImageList();
6379 Undo the last image transformation.
6381 if (undo_image == (Image *) NULL)
6383 (void) XBell(display,0);
6386 cache_image=undo_image;
6387 undo_image=GetPreviousImageInList(undo_image);
6388 windows->image.window_changes.width=(int) cache_image->columns;
6389 windows->image.window_changes.height=(int) cache_image->rows;
6390 if (windows->image.crop_geometry != (char *) NULL)
6391 windows->image.crop_geometry=(char *)
6392 RelinquishMagickMemory(windows->image.crop_geometry);
6393 windows->image.crop_geometry=cache_image->geometry;
6394 if (redo_image != (Image *) NULL)
6395 redo_image=DestroyImage(redo_image);
6396 redo_image=(*image);
6397 *image=cache_image->list;
6398 cache_image=DestroyImage(cache_image);
6399 if (windows->image.orphan != MagickFalse)
6401 XConfigureImageColormap(display,resource_info,windows,*image);
6402 (void) XConfigureImage(display,resource_info,windows,*image);
6408 case HalfSizeCommand:
6409 case OriginalSizeCommand:
6410 case DoubleSizeCommand:
6417 case RotateRightCommand:
6418 case RotateLeftCommand:
6423 case ContrastStretchCommand:
6424 case SigmoidalContrastCommand:
6425 case NormalizeCommand:
6426 case EqualizeCommand:
6428 case SaturationCommand:
6429 case BrightnessCommand:
6433 case GrayscaleCommand:
6435 case QuantizeCommand:
6436 case DespeckleCommand:
6438 case ReduceNoiseCommand:
6439 case AddNoiseCommand:
6440 case SharpenCommand:
6442 case ThresholdCommand:
6443 case EdgeDetectCommand:
6447 case SegmentCommand:
6448 case SolarizeCommand:
6449 case SepiaToneCommand:
6451 case ImplodeCommand:
6452 case VignetteCommand:
6454 case OilPaintCommand:
6455 case CharcoalDrawCommand:
6456 case AnnotateCommand:
6457 case AddBorderCommand:
6458 case AddFrameCommand:
6459 case CompositeCommand:
6460 case CommentCommand:
6462 case RegionofInterestCommand:
6463 case SaveToUndoBufferCommand:
6472 bytes=(long) ((*image)->columns*(*image)->rows*sizeof(PixelPacket));
6473 if (undo_image != (Image *) NULL)
6476 Ensure the undo stash.has enough memory available.
6478 previous_image=undo_image;
6479 while (previous_image != (Image *) NULL)
6481 bytes+=previous_image->list->columns*previous_image->list->rows*
6482 sizeof(PixelPacket);
6483 if (bytes <= (long) (resource_info->undo_cache << 20))
6485 previous_image=GetPreviousImageInList(previous_image);
6488 bytes-=previous_image->list->columns*previous_image->list->rows*
6489 sizeof(PixelPacket);
6490 if (previous_image == undo_image)
6491 undo_image=NewImageList();
6493 previous_image->next->previous=NewImageList();
6496 while (previous_image != (Image *) NULL)
6499 Delete any excess memory from undo cache.
6501 cache_image=previous_image;
6502 previous_image=GetPreviousImageInList(previous_image);
6503 cache_image->list=DestroyImage(cache_image->list);
6504 cache_image=DestroyImage(cache_image);
6507 if (bytes > (long) (resource_info->undo_cache << 20))
6510 Save image before transformations are applied.
6512 cache_image=AcquireImage((ImageInfo *) NULL);
6513 if (cache_image == (Image *) NULL)
6515 XSetCursorState(display,windows,MagickTrue);
6516 XCheckRefreshWindows(display,windows);
6517 cache_image->list=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
6518 XSetCursorState(display,windows,MagickFalse);
6519 if (cache_image->list == (Image *) NULL)
6521 cache_image=DestroyImage(cache_image);
6524 cache_image->columns=(unsigned long) windows->image.ximage->width;
6525 cache_image->rows=(unsigned long) windows->image.ximage->height;
6526 cache_image->geometry=windows->image.crop_geometry;
6527 if (windows->image.crop_geometry != (char *) NULL)
6529 cache_image->geometry=AcquireString((char *) NULL);
6530 (void) CopyMagickString(cache_image->geometry,
6531 windows->image.crop_geometry,MaxTextExtent);
6533 if (undo_image == (Image *) NULL)
6535 undo_image=cache_image;
6538 undo_image->next=cache_image;
6539 undo_image->next->previous=undo_image;
6540 undo_image=undo_image->next;
6546 if (command == RedoCommand)
6549 Redo the last image transformation.
6551 if (redo_image == (Image *) NULL)
6553 (void) XBell(display,0);
6556 windows->image.window_changes.width=(int) redo_image->columns;
6557 windows->image.window_changes.height=(int) redo_image->rows;
6558 if (windows->image.crop_geometry != (char *) NULL)
6559 windows->image.crop_geometry=(char *)
6560 RelinquishMagickMemory(windows->image.crop_geometry);
6561 windows->image.crop_geometry=redo_image->geometry;
6562 *image=DestroyImage(*image);
6564 redo_image=NewImageList();
6565 if (windows->image.orphan != MagickFalse)
6567 XConfigureImageColormap(display,resource_info,windows,*image);
6568 (void) XConfigureImage(display,resource_info,windows,*image);
6571 if (command != InfoCommand)
6576 XSetCursorState(display,windows,MagickTrue);
6577 XCheckRefreshWindows(display,windows);
6578 XDisplayImageInfo(display,resource_info,windows,undo_image,*image);
6579 XSetCursorState(display,windows,MagickFalse);
6583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6587 + X I m a g e W i n d o w C o m m a n d %
6591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6593 % XImageWindowCommand() makes a transform to the image or Image window as
6594 % specified by a user menu button or keyboard command.
6596 % The format of the XMagickCommand method is:
6598 % CommandType XImageWindowCommand(Display *display,
6599 % XResourceInfo *resource_info,XWindows *windows,
6600 % const MagickStatusType state,KeySym key_symbol,Image **image)
6602 % A description of each parameter follows:
6604 % o nexus: Method XImageWindowCommand returns an image when the
6605 % user chooses 'Open Image' from the command menu. Otherwise a null
6606 % image is returned.
6608 % o display: Specifies a connection to an X server; returned from
6611 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6613 % o windows: Specifies a pointer to a XWindows structure.
6615 % o state: key mask.
6617 % o key_symbol: Specifies a command to perform.
6619 % o image: the image; XImageWIndowCommand
6620 % may transform the image and return a new image pointer.
6623 static CommandType XImageWindowCommand(Display *display,
6624 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6625 KeySym key_symbol,Image **image)
6628 delta[MaxTextExtent] = "";
6631 Digits[] = "01234567890";
6636 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6638 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6641 resource_info->quantum=1;
6643 last_symbol=key_symbol;
6644 delta[strlen(delta)+1]='\0';
6645 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6646 resource_info->quantum=StringToLong(delta);
6647 return(NullCommand);
6649 last_symbol=key_symbol;
6650 if (resource_info->immutable)
6653 Virtual image window has a restricted command set.
6658 return(InfoCommand);
6661 return(PrintCommand);
6663 return(NextCommand);
6666 return(QuitCommand);
6670 return(NullCommand);
6672 switch ((int) key_symbol)
6676 if ((state & ControlMask) == 0)
6678 return(OpenCommand);
6681 return(NextCommand);
6683 return(FormerCommand);
6686 if ((state & Mod1Mask) != 0)
6687 return(SwirlCommand);
6688 if ((state & ControlMask) == 0)
6689 return(ShearCommand);
6690 return(SaveCommand);
6695 if ((state & Mod1Mask) != 0)
6696 return(OilPaintCommand);
6697 if ((state & Mod4Mask) != 0)
6698 return(ColorCommand);
6699 if ((state & ControlMask) == 0)
6700 return(NullCommand);
6701 return(PrintCommand);
6705 if ((state & Mod4Mask) != 0)
6706 return(DrawCommand);
6707 if ((state & ControlMask) == 0)
6708 return(NullCommand);
6709 return(DeleteCommand);
6713 if ((state & ControlMask) == 0)
6714 return(NullCommand);
6715 return(SelectCommand);
6719 if ((state & ControlMask) == 0)
6720 return(NullCommand);
6725 return(QuitCommand);
6729 if ((state & ControlMask) == 0)
6730 return(NullCommand);
6731 return(UndoCommand);
6736 if ((state & ControlMask) == 0)
6737 return(RollCommand);
6738 return(RedoCommand);
6742 if ((state & ControlMask) == 0)
6743 return(NullCommand);
6748 if ((state & Mod1Mask) != 0)
6749 return(CharcoalDrawCommand);
6750 if ((state & ControlMask) == 0)
6751 return(CropCommand);
6752 return(CopyCommand);
6757 if ((state & Mod4Mask) != 0)
6758 return(CompositeCommand);
6759 if ((state & ControlMask) == 0)
6760 return(FlipCommand);
6761 return(PasteCommand);
6764 return(HalfSizeCommand);
6766 return(OriginalSizeCommand);
6768 return(DoubleSizeCommand);
6770 return(ResizeCommand);
6772 return(RefreshCommand);
6773 case XK_bracketleft:
6774 return(ChopCommand);
6776 return(FlopCommand);
6778 return(RotateRightCommand);
6780 return(RotateLeftCommand);
6782 return(RotateCommand);
6784 return(TrimCommand);
6788 return(SaturationCommand);
6790 return(BrightnessCommand);
6792 return(GammaCommand);
6794 return(SpiffCommand);
6796 return(DullCommand);
6798 return(NormalizeCommand);
6800 return(EqualizeCommand);
6802 return(NegateCommand);
6804 return(GrayscaleCommand);
6806 return(QuantizeCommand);
6808 return(DespeckleCommand);
6810 return(EmbossCommand);
6812 return(ReduceNoiseCommand);
6814 return(AddNoiseCommand);
6816 return(SharpenCommand);
6818 return(BlurCommand);
6820 return(ThresholdCommand);
6822 return(EdgeDetectCommand);
6824 return(SpreadCommand);
6826 return(ShadeCommand);
6828 return(RaiseCommand);
6830 return(SegmentCommand);
6833 if ((state & Mod1Mask) == 0)
6834 return(NullCommand);
6835 return(ImplodeCommand);
6839 if ((state & Mod1Mask) == 0)
6840 return(NullCommand);
6841 return(WaveCommand);
6845 if ((state & Mod4Mask) == 0)
6846 return(NullCommand);
6847 return(MatteCommand);
6851 if ((state & Mod4Mask) == 0)
6852 return(NullCommand);
6853 return(AddBorderCommand);
6857 if ((state & Mod4Mask) == 0)
6858 return(NullCommand);
6859 return(AddFrameCommand);
6863 if ((state & Mod4Mask) == 0)
6864 return(NullCommand);
6865 return(CommentCommand);
6869 if ((state & Mod1Mask) != 0)
6870 return(ApplyCommand);
6871 if ((state & Mod4Mask) != 0)
6872 return(AnnotateCommand);
6873 if ((state & ControlMask) == 0)
6874 return(NullCommand);
6875 return(RegionofInterestCommand);
6878 return(InfoCommand);
6880 return(ZoomCommand);
6883 if ((state & ShiftMask) == 0)
6884 return(NullCommand);
6885 return(ShowPreviewCommand);
6888 return(LaunchCommand);
6890 return(HelpCommand);
6892 return(BrowseDocumentationCommand);
6895 (void) XMapRaised(display,windows->command.id);
6896 return(NullCommand);
6903 XTranslateImage(display,windows,*image,key_symbol);
6904 return(NullCommand);
6915 if ((state & Mod1Mask) != 0)
6921 Trim one pixel from edge of image.
6925 crop_info.width=(unsigned long) windows->image.ximage->width;
6926 crop_info.height=(unsigned long) windows->image.ximage->height;
6927 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
6929 if (resource_info->quantum >= (int) crop_info.height)
6930 resource_info->quantum=(int) crop_info.height-1;
6931 crop_info.height-=resource_info->quantum;
6933 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
6935 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
6936 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
6937 crop_info.y+=resource_info->quantum;
6938 crop_info.height-=resource_info->quantum;
6940 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
6942 if (resource_info->quantum >= (int) crop_info.width)
6943 resource_info->quantum=(int) crop_info.width-1;
6944 crop_info.width-=resource_info->quantum;
6946 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
6948 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
6949 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
6950 crop_info.x+=resource_info->quantum;
6951 crop_info.width-=resource_info->quantum;
6953 if ((int) (windows->image.x+windows->image.width) >
6954 (int) crop_info.width)
6955 windows->image.x=(int) (crop_info.width-windows->image.width);
6956 if ((int) (windows->image.y+windows->image.height) >
6957 (int) crop_info.height)
6958 windows->image.y=(int) (crop_info.height-windows->image.height);
6959 XSetCropGeometry(display,windows,&crop_info,*image);
6960 windows->image.window_changes.width=(int) crop_info.width;
6961 windows->image.window_changes.height=(int) crop_info.height;
6962 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
6963 (void) XConfigureImage(display,resource_info,windows,*image);
6964 return(NullCommand);
6966 XTranslateImage(display,windows,*image,key_symbol);
6967 return(NullCommand);
6970 return(NullCommand);
6972 return(NullCommand);
6976 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6980 + X M a g i c k C o m m a n d %
6984 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6986 % XMagickCommand() makes a transform to the image or Image window as
6987 % specified by a user menu button or keyboard command.
6989 % The format of the XMagickCommand method is:
6991 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
6992 % XWindows *windows,const CommandType command,Image **image)
6994 % A description of each parameter follows:
6996 % o nexus: Method XMagickCommand returns an image when the
6997 % user chooses 'Load Image' from the command menu. Otherwise a null
6998 % image is returned.
7000 % o display: Specifies a connection to an X server; returned from
7003 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7005 % o windows: Specifies a pointer to a XWindows structure.
7007 % o command: Specifies a command to perform.
7009 % o image: the image; XMagickCommand
7010 % may transform the image and return a new image pointer.
7013 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7014 XWindows *windows,const CommandType command,Image **image)
7017 filename[MaxTextExtent],
7018 geometry[MaxTextExtent],
7019 modulate_factors[MaxTextExtent];
7048 color[MaxTextExtent] = "gray";
7055 Process user command.
7057 XCheckRefreshWindows(display,windows);
7058 XImageCache(display,resource_info,windows,command,image);
7059 nexus=NewImageList();
7060 windows->image.window_changes.width=windows->image.ximage->width;
7061 windows->image.window_changes.height=windows->image.ximage->height;
7062 image_info=CloneImageInfo(resource_info->image_info);
7063 SetGeometryInfo(&geometry_info);
7064 GetQuantizeInfo(&quantize_info);
7072 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7080 for (i=0; i < resource_info->quantum; i++)
7081 XClientMessage(display,windows->image.id,windows->im_protocols,
7082 windows->im_next_image,CurrentTime);
7088 Display former image.
7090 for (i=0; i < resource_info->quantum; i++)
7091 XClientMessage(display,windows->image.id,windows->im_protocols,
7092 windows->im_former_image,CurrentTime);
7103 status=chdir(resource_info->home_directory);
7105 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
7106 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
7107 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7115 status=XSaveImage(display,resource_info,windows,*image);
7116 if (status == MagickFalse)
7118 XNoticeWidget(display,windows,"Unable to write X image:",
7119 (*image)->filename);
7129 status=XPrintImage(display,resource_info,windows,*image);
7130 if (status == MagickFalse)
7132 XNoticeWidget(display,windows,"Unable to print X image:",
7133 (*image)->filename);
7141 filename[MaxTextExtent] = "\0";
7146 XFileBrowserWidget(display,windows,"Delete",filename);
7147 if (*filename == '\0')
7149 status=remove(filename) != 0 ? MagickTrue : MagickFalse;
7150 if (status != MagickFalse)
7151 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7160 color[MaxTextExtent] = "gray",
7161 geometry[MaxTextExtent] = "640x480";
7164 *format = "gradient";
7167 Query user for canvas geometry.
7169 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7171 if (*geometry == '\0')
7175 XColorBrowserWidget(display,windows,"Select",color);
7181 (void) FormatMagickString(image_info->filename,MaxTextExtent,
7182 "%s:%s",format,color);
7183 (void) CloneString(&image_info->size,geometry);
7184 nexus=ReadImage(image_info,&(*image)->exception);
7185 CatchException(&(*image)->exception);
7186 XClientMessage(display,windows->image.id,windows->im_protocols,
7187 windows->im_next_image,CurrentTime);
7190 case VisualDirectoryCommand:
7193 Visual Image directory.
7195 nexus=XVisualDirectoryImage(display,resource_info,windows);
7203 if (resource_info->confirm_exit == MagickFalse)
7204 XClientMessage(display,windows->image.id,windows->im_protocols,
7205 windows->im_exit,CurrentTime);
7212 Confirm program exit.
7214 status=XConfirmWidget(display,windows,"Do you really want to exit",
7215 resource_info->client_name);
7217 XClientMessage(display,windows->image.id,windows->im_protocols,
7218 windows->im_exit,CurrentTime);
7227 (void) XCropImage(display,resource_info,windows,*image,CutMode);
7235 (void) XCropImage(display,resource_info,windows,*image,CopyMode);
7243 status=XPasteImage(display,resource_info,windows,*image);
7244 if (status == MagickFalse)
7246 XNoticeWidget(display,windows,"Unable to paste X image",
7247 (*image)->filename);
7252 case HalfSizeCommand:
7257 windows->image.window_changes.width=windows->image.ximage->width/2;
7258 windows->image.window_changes.height=windows->image.ximage->height/2;
7259 (void) XConfigureImage(display,resource_info,windows,*image);
7262 case OriginalSizeCommand:
7265 Original image size.
7267 windows->image.window_changes.width=(int) (*image)->columns;
7268 windows->image.window_changes.height=(int) (*image)->rows;
7269 (void) XConfigureImage(display,resource_info,windows,*image);
7272 case DoubleSizeCommand:
7275 Double the image size.
7277 windows->image.window_changes.width=windows->image.ximage->width << 1;
7278 windows->image.window_changes.height=windows->image.ximage->height << 1;
7279 (void) XConfigureImage(display,resource_info,windows,*image);
7298 width=(unsigned long) windows->image.ximage->width;
7299 height=(unsigned long) windows->image.ximage->height;
7302 (void) FormatMagickString(geometry,MaxTextExtent,"%lux%lu+0+0",
7304 status=XDialogWidget(display,windows,"Resize",
7305 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7306 if (*geometry == '\0')
7309 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7310 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7311 windows->image.window_changes.width=(int) width;
7312 windows->image.window_changes.height=(int) height;
7313 (void) XConfigureImage(display,resource_info,windows,*image);
7319 image_geometry[MaxTextExtent];
7321 if ((windows->image.crop_geometry == (char *) NULL) &&
7322 ((int) (*image)->columns == windows->image.ximage->width) &&
7323 ((int) (*image)->rows == windows->image.ximage->height))
7326 Apply size transforms to image.
7328 XSetCursorState(display,windows,MagickTrue);
7329 XCheckRefreshWindows(display,windows);
7331 Crop and/or scale displayed image.
7333 (void) FormatMagickString(image_geometry,MaxTextExtent,"%dx%d!",
7334 windows->image.ximage->width,windows->image.ximage->height);
7335 (void) TransformImage(image,windows->image.crop_geometry,image_geometry);
7336 if (windows->image.crop_geometry != (char *) NULL)
7337 windows->image.crop_geometry=(char *)
7338 RelinquishMagickMemory(windows->image.crop_geometry);
7341 XConfigureImageColormap(display,resource_info,windows,*image);
7342 (void) XConfigureImage(display,resource_info,windows,*image);
7345 case RefreshCommand:
7347 (void) XConfigureImage(display,resource_info,windows,*image);
7350 case RestoreCommand:
7353 Restore Image window to its original size.
7355 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7356 (windows->image.height == (unsigned int) (*image)->rows) &&
7357 (windows->image.crop_geometry == (char *) NULL))
7359 (void) XBell(display,0);
7362 windows->image.window_changes.width=(int) (*image)->columns;
7363 windows->image.window_changes.height=(int) (*image)->rows;
7364 if (windows->image.crop_geometry != (char *) NULL)
7366 windows->image.crop_geometry=(char *)
7367 RelinquishMagickMemory(windows->image.crop_geometry);
7368 windows->image.crop_geometry=(char *) NULL;
7372 XConfigureImageColormap(display,resource_info,windows,*image);
7373 (void) XConfigureImage(display,resource_info,windows,*image);
7381 (void) XCropImage(display,resource_info,windows,*image,CropMode);
7389 status=XChopImage(display,resource_info,windows,image);
7390 if (status == MagickFalse)
7392 XNoticeWidget(display,windows,"Unable to cut X image",
7393 (*image)->filename);
7404 Flop image scanlines.
7406 XSetCursorState(display,windows,MagickTrue);
7407 XCheckRefreshWindows(display,windows);
7408 flop_image=FlopImage(*image,&(*image)->exception);
7409 if (flop_image != (Image *) NULL)
7411 *image=DestroyImage(*image);
7414 CatchException(&(*image)->exception);
7415 XSetCursorState(display,windows,MagickFalse);
7416 if (windows->image.crop_geometry != (char *) NULL)
7421 width=(unsigned int) (*image)->columns;
7422 height=(unsigned int) (*image)->rows;
7423 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7425 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
7426 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7428 if (windows->image.orphan != MagickFalse)
7430 (void) XConfigureImage(display,resource_info,windows,*image);
7439 Flip image scanlines.
7441 XSetCursorState(display,windows,MagickTrue);
7442 XCheckRefreshWindows(display,windows);
7443 flip_image=FlipImage(*image,&(*image)->exception);
7444 if (flip_image != (Image *) NULL)
7446 *image=DestroyImage(*image);
7449 CatchException(&(*image)->exception);
7450 XSetCursorState(display,windows,MagickFalse);
7451 if (windows->image.crop_geometry != (char *) NULL)
7456 width=(unsigned int) (*image)->columns;
7457 height=(unsigned int) (*image)->rows;
7458 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7460 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
7461 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7463 if (windows->image.orphan != MagickFalse)
7465 (void) XConfigureImage(display,resource_info,windows,*image);
7468 case RotateRightCommand:
7471 Rotate image 90 degrees clockwise.
7473 status=XRotateImage(display,resource_info,windows,90.0,image);
7474 if (status == MagickFalse)
7476 XNoticeWidget(display,windows,"Unable to rotate X image",
7477 (*image)->filename);
7482 case RotateLeftCommand:
7485 Rotate image 90 degrees counter-clockwise.
7487 status=XRotateImage(display,resource_info,windows,-90.0,image);
7488 if (status == MagickFalse)
7490 XNoticeWidget(display,windows,"Unable to rotate X image",
7491 (*image)->filename);
7501 status=XRotateImage(display,resource_info,windows,0.0,image);
7502 if (status == MagickFalse)
7504 XNoticeWidget(display,windows,"Unable to rotate X image",
7505 (*image)->filename);
7516 geometry[MaxTextExtent] = "45.0x45.0";
7519 Query user for shear color and geometry.
7521 XColorBrowserWidget(display,windows,"Select",color);
7524 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7526 if (*geometry == '\0')
7531 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
7532 XSetCursorState(display,windows,MagickTrue);
7533 XCheckRefreshWindows(display,windows);
7534 (void) QueryColorDatabase(color,&(*image)->background_color,
7535 &(*image)->exception);
7536 flags=ParseGeometry(geometry,&geometry_info);
7537 if ((flags & SigmaValue) == 0)
7538 geometry_info.sigma=geometry_info.rho;
7539 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7540 &(*image)->exception);
7541 if (shear_image != (Image *) NULL)
7543 *image=DestroyImage(*image);
7546 CatchException(&(*image)->exception);
7547 XSetCursorState(display,windows,MagickFalse);
7548 if (windows->image.orphan != MagickFalse)
7550 windows->image.window_changes.width=(int) (*image)->columns;
7551 windows->image.window_changes.height=(int) (*image)->rows;
7552 XConfigureImageColormap(display,resource_info,windows,*image);
7553 (void) XConfigureImage(display,resource_info,windows,*image);
7562 geometry[MaxTextExtent] = "+2+2";
7565 Query user for the roll geometry.
7567 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7569 if (*geometry == '\0')
7574 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
7575 XSetCursorState(display,windows,MagickTrue);
7576 XCheckRefreshWindows(display,windows);
7577 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7578 &(*image)->exception);
7579 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7580 &(*image)->exception);
7581 if (roll_image != (Image *) NULL)
7583 *image=DestroyImage(*image);
7586 CatchException(&(*image)->exception);
7587 XSetCursorState(display,windows,MagickFalse);
7588 if (windows->image.orphan != MagickFalse)
7590 windows->image.window_changes.width=(int) (*image)->columns;
7591 windows->image.window_changes.height=(int) (*image)->rows;
7592 XConfigureImageColormap(display,resource_info,windows,*image);
7593 (void) XConfigureImage(display,resource_info,windows,*image);
7599 fuzz[MaxTextExtent];
7602 Query user for the fuzz factor.
7604 (void) FormatMagickString(fuzz,MaxTextExtent,"%g%%",100.0*
7605 (*image)->fuzz/(QuantumRange+1.0));
7606 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7609 (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0);
7613 status=XTrimImage(display,resource_info,windows,*image);
7614 if (status == MagickFalse)
7616 XNoticeWidget(display,windows,"Unable to trim X image",
7617 (*image)->filename);
7625 hue_percent[MaxTextExtent] = "110";
7628 Query user for percent hue change.
7630 (void) XDialogWidget(display,windows,"Apply",
7631 "Enter percent change in image hue (0-200):",hue_percent);
7632 if (*hue_percent == '\0')
7637 XSetCursorState(display,windows,MagickTrue);
7638 XCheckRefreshWindows(display,windows);
7639 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7640 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7642 (void) ModulateImage(*image,modulate_factors);
7643 XSetCursorState(display,windows,MagickFalse);
7644 if (windows->image.orphan != MagickFalse)
7646 XConfigureImageColormap(display,resource_info,windows,*image);
7647 (void) XConfigureImage(display,resource_info,windows,*image);
7650 case SaturationCommand:
7653 saturation_percent[MaxTextExtent] = "110";
7656 Query user for percent saturation change.
7658 (void) XDialogWidget(display,windows,"Apply",
7659 "Enter percent change in color saturation (0-200):",saturation_percent);
7660 if (*saturation_percent == '\0')
7663 Vary color saturation.
7665 XSetCursorState(display,windows,MagickTrue);
7666 XCheckRefreshWindows(display,windows);
7667 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7668 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7670 (void) ModulateImage(*image,modulate_factors);
7671 XSetCursorState(display,windows,MagickFalse);
7672 if (windows->image.orphan != MagickFalse)
7674 XConfigureImageColormap(display,resource_info,windows,*image);
7675 (void) XConfigureImage(display,resource_info,windows,*image);
7678 case BrightnessCommand:
7681 brightness_percent[MaxTextExtent] = "110";
7684 Query user for percent brightness change.
7686 (void) XDialogWidget(display,windows,"Apply",
7687 "Enter percent change in color brightness (0-200):",brightness_percent);
7688 if (*brightness_percent == '\0')
7691 Vary the color brightness.
7693 XSetCursorState(display,windows,MagickTrue);
7694 XCheckRefreshWindows(display,windows);
7695 (void) CopyMagickString(modulate_factors,brightness_percent,
7697 (void) ModulateImage(*image,modulate_factors);
7698 XSetCursorState(display,windows,MagickFalse);
7699 if (windows->image.orphan != MagickFalse)
7701 XConfigureImageColormap(display,resource_info,windows,*image);
7702 (void) XConfigureImage(display,resource_info,windows,*image);
7708 factor[MaxTextExtent] = "1.6";
7711 Query user for gamma value.
7713 (void) XDialogWidget(display,windows,"Gamma",
7714 "Enter gamma value (e.g. 1.0,1.0,1.6):",factor);
7715 if (*factor == '\0')
7718 Gamma correct image.
7720 XSetCursorState(display,windows,MagickTrue);
7721 XCheckRefreshWindows(display,windows);
7722 (void) GammaImage(*image,factor);
7723 XSetCursorState(display,windows,MagickFalse);
7724 if (windows->image.orphan != MagickFalse)
7726 XConfigureImageColormap(display,resource_info,windows,*image);
7727 (void) XConfigureImage(display,resource_info,windows,*image);
7733 Sharpen the image contrast.
7735 XSetCursorState(display,windows,MagickTrue);
7736 XCheckRefreshWindows(display,windows);
7737 (void) ContrastImage(*image,MagickTrue);
7738 XSetCursorState(display,windows,MagickFalse);
7739 if (windows->image.orphan != MagickFalse)
7741 XConfigureImageColormap(display,resource_info,windows,*image);
7742 (void) XConfigureImage(display,resource_info,windows,*image);
7748 Dull the image contrast.
7750 XSetCursorState(display,windows,MagickTrue);
7751 XCheckRefreshWindows(display,windows);
7752 (void) ContrastImage(*image,MagickFalse);
7753 XSetCursorState(display,windows,MagickFalse);
7754 if (windows->image.orphan != MagickFalse)
7756 XConfigureImageColormap(display,resource_info,windows,*image);
7757 (void) XConfigureImage(display,resource_info,windows,*image);
7760 case ContrastStretchCommand:
7767 levels[MaxTextExtent] = "1%";
7770 Query user for gamma value.
7772 (void) XDialogWidget(display,windows,"Contrast Stretch",
7773 "Enter black and white points:",levels);
7774 if (*levels == '\0')
7777 Contrast stretch image.
7779 XSetCursorState(display,windows,MagickTrue);
7780 XCheckRefreshWindows(display,windows);
7781 flags=ParseGeometry(levels,&geometry_info);
7782 black_point=geometry_info.rho;
7783 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7784 if ((flags & PercentValue) != 0)
7786 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7787 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7789 white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point;
7790 (void) ContrastStretchImageChannel(*image,DefaultChannels,black_point,
7792 XSetCursorState(display,windows,MagickFalse);
7793 if (windows->image.orphan != MagickFalse)
7795 XConfigureImageColormap(display,resource_info,windows,*image);
7796 (void) XConfigureImage(display,resource_info,windows,*image);
7799 case SigmoidalContrastCommand:
7802 levels[MaxTextExtent] = "3x50%";
7805 Query user for gamma value.
7807 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7808 "Enter contrast and midpoint:",levels);
7809 if (*levels == '\0')
7812 Contrast stretch image.
7814 XSetCursorState(display,windows,MagickTrue);
7815 XCheckRefreshWindows(display,windows);
7816 (void) SigmoidalContrastImage(*image,MagickTrue,levels);
7817 XSetCursorState(display,windows,MagickFalse);
7818 if (windows->image.orphan != MagickFalse)
7820 XConfigureImageColormap(display,resource_info,windows,*image);
7821 (void) XConfigureImage(display,resource_info,windows,*image);
7824 case NormalizeCommand:
7827 Perform histogram normalization on the image.
7829 XSetCursorState(display,windows,MagickTrue);
7830 XCheckRefreshWindows(display,windows);
7831 (void) NormalizeImage(*image);
7832 XSetCursorState(display,windows,MagickFalse);
7833 if (windows->image.orphan != MagickFalse)
7835 XConfigureImageColormap(display,resource_info,windows,*image);
7836 (void) XConfigureImage(display,resource_info,windows,*image);
7839 case EqualizeCommand:
7842 Perform histogram equalization on the image.
7844 XSetCursorState(display,windows,MagickTrue);
7845 XCheckRefreshWindows(display,windows);
7846 (void) EqualizeImage(*image);
7847 XSetCursorState(display,windows,MagickFalse);
7848 if (windows->image.orphan != MagickFalse)
7850 XConfigureImageColormap(display,resource_info,windows,*image);
7851 (void) XConfigureImage(display,resource_info,windows,*image);
7857 Negate colors in image.
7859 XSetCursorState(display,windows,MagickTrue);
7860 XCheckRefreshWindows(display,windows);
7861 (void) NegateImage(*image,MagickFalse);
7862 XSetCursorState(display,windows,MagickFalse);
7863 if (windows->image.orphan != MagickFalse)
7865 XConfigureImageColormap(display,resource_info,windows,*image);
7866 (void) XConfigureImage(display,resource_info,windows,*image);
7869 case GrayscaleCommand:
7872 Convert image to grayscale.
7874 XSetCursorState(display,windows,MagickTrue);
7875 XCheckRefreshWindows(display,windows);
7876 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
7877 GrayscaleType : GrayscaleMatteType);
7878 XSetCursorState(display,windows,MagickFalse);
7879 if (windows->image.orphan != MagickFalse)
7881 XConfigureImageColormap(display,resource_info,windows,*image);
7882 (void) XConfigureImage(display,resource_info,windows,*image);
7891 filename[MaxTextExtent] = "\0";
7894 Request image file name from user.
7896 XFileBrowserWidget(display,windows,"Map",filename);
7897 if (*filename == '\0')
7902 XSetCursorState(display,windows,MagickTrue);
7903 XCheckRefreshWindows(display,windows);
7904 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
7905 affinity_image=ReadImage(image_info,&(*image)->exception);
7906 if (affinity_image != (Image *) NULL)
7908 (void) RemapImage(&quantize_info,*image,affinity_image);
7909 affinity_image=DestroyImage(affinity_image);
7911 CatchException(&(*image)->exception);
7912 XSetCursorState(display,windows,MagickFalse);
7913 if (windows->image.orphan != MagickFalse)
7915 XConfigureImageColormap(display,resource_info,windows,*image);
7916 (void) XConfigureImage(display,resource_info,windows,*image);
7919 case QuantizeCommand:
7925 colors[MaxTextExtent] = "256";
7928 Query user for maximum number of colors.
7930 status=XDialogWidget(display,windows,"Quantize",
7931 "Maximum number of colors:",colors);
7932 if (*colors == '\0')
7935 Color reduce the image.
7937 XSetCursorState(display,windows,MagickTrue);
7938 XCheckRefreshWindows(display,windows);
7939 quantize_info.number_colors=StringToUnsignedLong(colors);
7940 quantize_info.dither=status != 0 ? MagickTrue : MagickFalse;
7941 (void) QuantizeImage(&quantize_info,*image);
7942 XSetCursorState(display,windows,MagickFalse);
7943 if (windows->image.orphan != MagickFalse)
7945 XConfigureImageColormap(display,resource_info,windows,*image);
7946 (void) XConfigureImage(display,resource_info,windows,*image);
7949 case DespeckleCommand:
7957 XSetCursorState(display,windows,MagickTrue);
7958 XCheckRefreshWindows(display,windows);
7959 despeckle_image=DespeckleImage(*image,&(*image)->exception);
7960 if (despeckle_image != (Image *) NULL)
7962 *image=DestroyImage(*image);
7963 *image=despeckle_image;
7965 CatchException(&(*image)->exception);
7966 XSetCursorState(display,windows,MagickFalse);
7967 if (windows->image.orphan != MagickFalse)
7969 XConfigureImageColormap(display,resource_info,windows,*image);
7970 (void) XConfigureImage(display,resource_info,windows,*image);
7979 radius[MaxTextExtent] = "0.0x1.0";
7982 Query user for emboss radius.
7984 (void) XDialogWidget(display,windows,"Emboss",
7985 "Enter the emboss radius and standard deviation:",radius);
7986 if (*radius == '\0')
7989 Reduce noise in the image.
7991 XSetCursorState(display,windows,MagickTrue);
7992 XCheckRefreshWindows(display,windows);
7993 flags=ParseGeometry(radius,&geometry_info);
7994 if ((flags & SigmaValue) == 0)
7995 geometry_info.sigma=1.0;
7996 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
7997 &(*image)->exception);
7998 if (emboss_image != (Image *) NULL)
8000 *image=DestroyImage(*image);
8001 *image=emboss_image;
8003 CatchException(&(*image)->exception);
8004 XSetCursorState(display,windows,MagickFalse);
8005 if (windows->image.orphan != MagickFalse)
8007 XConfigureImageColormap(display,resource_info,windows,*image);
8008 (void) XConfigureImage(display,resource_info,windows,*image);
8011 case ReduceNoiseCommand:
8017 radius[MaxTextExtent] = "0";
8020 Query user for noise radius.
8022 (void) XDialogWidget(display,windows,"Reduce Noise",
8023 "Enter the noise radius:",radius);
8024 if (*radius == '\0')
8027 Reduce noise in the image.
8029 XSetCursorState(display,windows,MagickTrue);
8030 XCheckRefreshWindows(display,windows);
8031 flags=ParseGeometry(radius,&geometry_info);
8032 noise_image=ReduceNoiseImage(*image,geometry_info.rho,
8033 &(*image)->exception);
8034 if (noise_image != (Image *) NULL)
8036 *image=DestroyImage(*image);
8039 CatchException(&(*image)->exception);
8040 XSetCursorState(display,windows,MagickFalse);
8041 if (windows->image.orphan != MagickFalse)
8043 XConfigureImageColormap(display,resource_info,windows,*image);
8044 (void) XConfigureImage(display,resource_info,windows,*image);
8047 case AddNoiseCommand:
8056 noise_type[MaxTextExtent] = "Gaussian";
8059 Add noise to the image.
8061 noises=GetMagickOptions(MagickNoiseOptions);
8062 if (noises == (char **) NULL)
8064 XListBrowserWidget(display,windows,&windows->widget,
8065 (const char **) noises,"Add Noise",
8066 "Select a type of noise to add to your image:",noise_type);
8067 noises=DestroyStringList(noises);
8068 if (*noise_type == '\0')
8070 XSetCursorState(display,windows,MagickTrue);
8071 XCheckRefreshWindows(display,windows);
8072 noise_image=AddNoiseImage(*image,(NoiseType) ParseMagickOption(
8073 MagickNoiseOptions,MagickFalse,noise_type),&(*image)->exception);
8074 if (noise_image != (Image *) NULL)
8076 *image=DestroyImage(*image);
8079 CatchException(&(*image)->exception);
8080 XSetCursorState(display,windows,MagickFalse);
8081 if (windows->image.orphan != MagickFalse)
8083 XConfigureImageColormap(display,resource_info,windows,*image);
8084 (void) XConfigureImage(display,resource_info,windows,*image);
8087 case SharpenCommand:
8093 radius[MaxTextExtent] = "0.0x1.0";
8096 Query user for sharpen radius.
8098 (void) XDialogWidget(display,windows,"Sharpen",
8099 "Enter the sharpen radius and standard deviation:",radius);
8100 if (*radius == '\0')
8103 Sharpen image scanlines.
8105 XSetCursorState(display,windows,MagickTrue);
8106 XCheckRefreshWindows(display,windows);
8107 flags=ParseGeometry(radius,&geometry_info);
8108 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8109 &(*image)->exception);
8110 if (sharp_image != (Image *) NULL)
8112 *image=DestroyImage(*image);
8115 CatchException(&(*image)->exception);
8116 XSetCursorState(display,windows,MagickFalse);
8117 if (windows->image.orphan != MagickFalse)
8119 XConfigureImageColormap(display,resource_info,windows,*image);
8120 (void) XConfigureImage(display,resource_info,windows,*image);
8129 radius[MaxTextExtent] = "0.0x1.0";
8132 Query user for blur radius.
8134 (void) XDialogWidget(display,windows,"Blur",
8135 "Enter the blur radius and standard deviation:",radius);
8136 if (*radius == '\0')
8141 XSetCursorState(display,windows,MagickTrue);
8142 XCheckRefreshWindows(display,windows);
8143 flags=ParseGeometry(radius,&geometry_info);
8144 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8145 &(*image)->exception);
8146 if (blur_image != (Image *) NULL)
8148 *image=DestroyImage(*image);
8151 CatchException(&(*image)->exception);
8152 XSetCursorState(display,windows,MagickFalse);
8153 if (windows->image.orphan != MagickFalse)
8155 XConfigureImageColormap(display,resource_info,windows,*image);
8156 (void) XConfigureImage(display,resource_info,windows,*image);
8159 case ThresholdCommand:
8165 factor[MaxTextExtent] = "128";
8168 Query user for threshold value.
8170 (void) XDialogWidget(display,windows,"Threshold",
8171 "Enter threshold value:",factor);
8172 if (*factor == '\0')
8175 Gamma correct image.
8177 XSetCursorState(display,windows,MagickTrue);
8178 XCheckRefreshWindows(display,windows);
8179 threshold=SiPrefixToDouble(factor,QuantumRange);
8180 (void) BilevelImage(*image,threshold);
8181 XSetCursorState(display,windows,MagickFalse);
8182 if (windows->image.orphan != MagickFalse)
8184 XConfigureImageColormap(display,resource_info,windows,*image);
8185 (void) XConfigureImage(display,resource_info,windows,*image);
8188 case EdgeDetectCommand:
8194 radius[MaxTextExtent] = "0";
8197 Query user for edge factor.
8199 (void) XDialogWidget(display,windows,"Detect Edges",
8200 "Enter the edge detect radius:",radius);
8201 if (*radius == '\0')
8204 Detect edge in image.
8206 XSetCursorState(display,windows,MagickTrue);
8207 XCheckRefreshWindows(display,windows);
8208 flags=ParseGeometry(radius,&geometry_info);
8209 edge_image=EdgeImage(*image,geometry_info.rho,&(*image)->exception);
8210 if (edge_image != (Image *) NULL)
8212 *image=DestroyImage(*image);
8215 CatchException(&(*image)->exception);
8216 XSetCursorState(display,windows,MagickFalse);
8217 if (windows->image.orphan != MagickFalse)
8219 XConfigureImageColormap(display,resource_info,windows,*image);
8220 (void) XConfigureImage(display,resource_info,windows,*image);
8229 amount[MaxTextExtent] = "2";
8232 Query user for spread amount.
8234 (void) XDialogWidget(display,windows,"Spread",
8235 "Enter the displacement amount:",amount);
8236 if (*amount == '\0')
8239 Displace image pixels by a random amount.
8241 XSetCursorState(display,windows,MagickTrue);
8242 XCheckRefreshWindows(display,windows);
8243 flags=ParseGeometry(amount,&geometry_info);
8244 spread_image=EdgeImage(*image,geometry_info.rho,&(*image)->exception);
8245 if (spread_image != (Image *) NULL)
8247 *image=DestroyImage(*image);
8248 *image=spread_image;
8250 CatchException(&(*image)->exception);
8251 XSetCursorState(display,windows,MagickFalse);
8252 if (windows->image.orphan != MagickFalse)
8254 XConfigureImageColormap(display,resource_info,windows,*image);
8255 (void) XConfigureImage(display,resource_info,windows,*image);
8267 geometry[MaxTextExtent] = "30x30";
8270 Query user for the shade geometry.
8272 status=XDialogWidget(display,windows,"Shade",
8273 "Enter the azimuth and elevation of the light source:",geometry);
8274 if (*geometry == '\0')
8279 XSetCursorState(display,windows,MagickTrue);
8280 XCheckRefreshWindows(display,windows);
8281 flags=ParseGeometry(geometry,&geometry_info);
8282 if ((flags & SigmaValue) == 0)
8283 geometry_info.sigma=1.0;
8284 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
8285 geometry_info.rho,geometry_info.sigma,&(*image)->exception);
8286 if (shade_image != (Image *) NULL)
8288 *image=DestroyImage(*image);
8291 CatchException(&(*image)->exception);
8292 XSetCursorState(display,windows,MagickFalse);
8293 if (windows->image.orphan != MagickFalse)
8295 XConfigureImageColormap(display,resource_info,windows,*image);
8296 (void) XConfigureImage(display,resource_info,windows,*image);
8302 bevel_width[MaxTextExtent] = "10";
8305 Query user for bevel width.
8307 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8308 if (*bevel_width == '\0')
8313 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
8314 XSetCursorState(display,windows,MagickTrue);
8315 XCheckRefreshWindows(display,windows);
8316 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8317 &(*image)->exception);
8318 (void) RaiseImage(*image,&page_geometry,MagickTrue);
8319 XSetCursorState(display,windows,MagickFalse);
8320 if (windows->image.orphan != MagickFalse)
8322 XConfigureImageColormap(display,resource_info,windows,*image);
8323 (void) XConfigureImage(display,resource_info,windows,*image);
8326 case SegmentCommand:
8329 threshold[MaxTextExtent] = "1.0x1.5";
8332 Query user for smoothing threshold.
8334 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8336 if (*threshold == '\0')
8341 XSetCursorState(display,windows,MagickTrue);
8342 XCheckRefreshWindows(display,windows);
8343 flags=ParseGeometry(threshold,&geometry_info);
8344 if ((flags & SigmaValue) == 0)
8345 geometry_info.sigma=1.0;
8346 (void) SegmentImage(*image,RGBColorspace,MagickFalse,geometry_info.rho,
8347 geometry_info.sigma);
8348 XSetCursorState(display,windows,MagickFalse);
8349 if (windows->image.orphan != MagickFalse)
8351 XConfigureImageColormap(display,resource_info,windows,*image);
8352 (void) XConfigureImage(display,resource_info,windows,*image);
8355 case SepiaToneCommand:
8364 factor[MaxTextExtent] = "80%";
8367 Query user for sepia-tone factor.
8369 (void) XDialogWidget(display,windows,"Sepia Tone",
8370 "Enter the sepia tone factor (0 - 99.9%):",factor);
8371 if (*factor == '\0')
8374 Sepia tone image pixels.
8376 XSetCursorState(display,windows,MagickTrue);
8377 XCheckRefreshWindows(display,windows);
8378 threshold=SiPrefixToDouble(factor,QuantumRange);
8379 sepia_image=SepiaToneImage(*image,threshold,&(*image)->exception);
8380 if (sepia_image != (Image *) NULL)
8382 *image=DestroyImage(*image);
8385 CatchException(&(*image)->exception);
8386 XSetCursorState(display,windows,MagickFalse);
8387 if (windows->image.orphan != MagickFalse)
8389 XConfigureImageColormap(display,resource_info,windows,*image);
8390 (void) XConfigureImage(display,resource_info,windows,*image);
8393 case SolarizeCommand:
8399 factor[MaxTextExtent] = "60%";
8402 Query user for solarize factor.
8404 (void) XDialogWidget(display,windows,"Solarize",
8405 "Enter the solarize factor (0 - 99.9%):",factor);
8406 if (*factor == '\0')
8409 Solarize image pixels.
8411 XSetCursorState(display,windows,MagickTrue);
8412 XCheckRefreshWindows(display,windows);
8413 threshold=SiPrefixToDouble(factor,QuantumRange);
8414 (void) SolarizeImage(*image,threshold);
8415 XSetCursorState(display,windows,MagickFalse);
8416 if (windows->image.orphan != MagickFalse)
8418 XConfigureImageColormap(display,resource_info,windows,*image);
8419 (void) XConfigureImage(display,resource_info,windows,*image);
8428 degrees[MaxTextExtent] = "60";
8431 Query user for swirl angle.
8433 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8435 if (*degrees == '\0')
8438 Swirl image pixels about the center.
8440 XSetCursorState(display,windows,MagickTrue);
8441 XCheckRefreshWindows(display,windows);
8442 flags=ParseGeometry(degrees,&geometry_info);
8443 swirl_image=SwirlImage(*image,geometry_info.rho,&(*image)->exception);
8444 if (swirl_image != (Image *) NULL)
8446 *image=DestroyImage(*image);
8449 CatchException(&(*image)->exception);
8450 XSetCursorState(display,windows,MagickFalse);
8451 if (windows->image.orphan != MagickFalse)
8453 XConfigureImageColormap(display,resource_info,windows,*image);
8454 (void) XConfigureImage(display,resource_info,windows,*image);
8457 case ImplodeCommand:
8463 factor[MaxTextExtent] = "0.3";
8466 Query user for implode factor.
8468 (void) XDialogWidget(display,windows,"Implode",
8469 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8470 if (*factor == '\0')
8473 Implode image pixels about the center.
8475 XSetCursorState(display,windows,MagickTrue);
8476 XCheckRefreshWindows(display,windows);
8477 flags=ParseGeometry(factor,&geometry_info);
8478 implode_image=ImplodeImage(*image,geometry_info.rho,&(*image)->exception);
8479 if (implode_image != (Image *) NULL)
8481 *image=DestroyImage(*image);
8482 *image=implode_image;
8484 CatchException(&(*image)->exception);
8485 XSetCursorState(display,windows,MagickFalse);
8486 if (windows->image.orphan != MagickFalse)
8488 XConfigureImageColormap(display,resource_info,windows,*image);
8489 (void) XConfigureImage(display,resource_info,windows,*image);
8492 case VignetteCommand:
8498 geometry[MaxTextExtent] = "0x20";
8501 Query user for the vignette geometry.
8503 (void) XDialogWidget(display,windows,"Vignette",
8504 "Enter the radius, sigma, and x and y offsets:",geometry);
8505 if (*geometry == '\0')
8508 Soften the edges of the image in vignette style
8510 XSetCursorState(display,windows,MagickTrue);
8511 XCheckRefreshWindows(display,windows);
8512 flags=ParseGeometry(geometry,&geometry_info);
8513 if ((flags & SigmaValue) == 0)
8514 geometry_info.sigma=1.0;
8515 if ((flags & XiValue) == 0)
8516 geometry_info.xi=0.1*(*image)->columns;
8517 if ((flags & PsiValue) == 0)
8518 geometry_info.psi=0.1*(*image)->rows;
8519 vignette_image=VignetteImage(*image,geometry_info.rho,geometry_info.sigma,
8520 (long) floor(geometry_info.xi+0.5),(long) floor(geometry_info.psi+0.5),
8521 &(*image)->exception);
8522 if (vignette_image != (Image *) NULL)
8524 *image=DestroyImage(*image);
8525 *image=vignette_image;
8527 CatchException(&(*image)->exception);
8528 XSetCursorState(display,windows,MagickFalse);
8529 if (windows->image.orphan != MagickFalse)
8531 XConfigureImageColormap(display,resource_info,windows,*image);
8532 (void) XConfigureImage(display,resource_info,windows,*image);
8541 geometry[MaxTextExtent] = "25x150";
8544 Query user for the wave geometry.
8546 (void) XDialogWidget(display,windows,"Wave",
8547 "Enter the amplitude and length of the wave:",geometry);
8548 if (*geometry == '\0')
8551 Alter an image along a sine wave.
8553 XSetCursorState(display,windows,MagickTrue);
8554 XCheckRefreshWindows(display,windows);
8555 flags=ParseGeometry(geometry,&geometry_info);
8556 if ((flags & SigmaValue) == 0)
8557 geometry_info.sigma=1.0;
8558 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8559 &(*image)->exception);
8560 if (wave_image != (Image *) NULL)
8562 *image=DestroyImage(*image);
8565 CatchException(&(*image)->exception);
8566 XSetCursorState(display,windows,MagickFalse);
8567 if (windows->image.orphan != MagickFalse)
8569 XConfigureImageColormap(display,resource_info,windows,*image);
8570 (void) XConfigureImage(display,resource_info,windows,*image);
8573 case OilPaintCommand:
8579 radius[MaxTextExtent] = "0";
8582 Query user for circular neighborhood radius.
8584 (void) XDialogWidget(display,windows,"Oil Paint",
8585 "Enter the mask radius:",radius);
8586 if (*radius == '\0')
8589 OilPaint image scanlines.
8591 XSetCursorState(display,windows,MagickTrue);
8592 XCheckRefreshWindows(display,windows);
8593 flags=ParseGeometry(radius,&geometry_info);
8594 paint_image=OilPaintImage(*image,geometry_info.rho,&(*image)->exception);
8595 if (paint_image != (Image *) NULL)
8597 *image=DestroyImage(*image);
8600 CatchException(&(*image)->exception);
8601 XSetCursorState(display,windows,MagickFalse);
8602 if (windows->image.orphan != MagickFalse)
8604 XConfigureImageColormap(display,resource_info,windows,*image);
8605 (void) XConfigureImage(display,resource_info,windows,*image);
8608 case CharcoalDrawCommand:
8614 radius[MaxTextExtent] = "0x1";
8617 Query user for charcoal radius.
8619 (void) XDialogWidget(display,windows,"Charcoal Draw",
8620 "Enter the charcoal radius and sigma:",radius);
8621 if (*radius == '\0')
8626 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
8627 XSetCursorState(display,windows,MagickTrue);
8628 XCheckRefreshWindows(display,windows);
8629 flags=ParseGeometry(radius,&geometry_info);
8630 if ((flags & SigmaValue) == 0)
8631 geometry_info.sigma=geometry_info.rho;
8632 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8633 &(*image)->exception);
8634 if (charcoal_image != (Image *) NULL)
8636 *image=DestroyImage(*image);
8637 *image=charcoal_image;
8639 CatchException(&(*image)->exception);
8640 XSetCursorState(display,windows,MagickFalse);
8641 if (windows->image.orphan != MagickFalse)
8643 XConfigureImageColormap(display,resource_info,windows,*image);
8644 (void) XConfigureImage(display,resource_info,windows,*image);
8647 case AnnotateCommand:
8650 Annotate the image with text.
8652 status=XAnnotateEditImage(display,resource_info,windows,*image);
8653 if (status == MagickFalse)
8655 XNoticeWidget(display,windows,"Unable to annotate X image",
8656 (*image)->filename);
8666 status=XDrawEditImage(display,resource_info,windows,image);
8667 if (status == MagickFalse)
8669 XNoticeWidget(display,windows,"Unable to draw on the X image",
8670 (*image)->filename);
8680 status=XColorEditImage(display,resource_info,windows,image);
8681 if (status == MagickFalse)
8683 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8684 (*image)->filename);
8694 status=XMatteEditImage(display,resource_info,windows,image);
8695 if (status == MagickFalse)
8697 XNoticeWidget(display,windows,"Unable to matte edit X image",
8698 (*image)->filename);
8703 case CompositeCommand:
8708 status=XCompositeImage(display,resource_info,windows,*image);
8709 if (status == MagickFalse)
8711 XNoticeWidget(display,windows,"Unable to composite X image",
8712 (*image)->filename);
8717 case AddBorderCommand:
8723 geometry[MaxTextExtent] = "6x6";
8726 Query user for border color and geometry.
8728 XColorBrowserWidget(display,windows,"Select",color);
8731 (void) XDialogWidget(display,windows,"Add Border",
8732 "Enter border geometry:",geometry);
8733 if (*geometry == '\0')
8736 Add a border to the image.
8738 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
8739 XSetCursorState(display,windows,MagickTrue);
8740 XCheckRefreshWindows(display,windows);
8741 (void) QueryColorDatabase(color,&(*image)->border_color,
8742 &(*image)->exception);
8743 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8744 &(*image)->exception);
8745 border_image=BorderImage(*image,&page_geometry,&(*image)->exception);
8746 if (border_image != (Image *) NULL)
8748 *image=DestroyImage(*image);
8749 *image=border_image;
8751 CatchException(&(*image)->exception);
8752 XSetCursorState(display,windows,MagickFalse);
8753 if (windows->image.orphan != MagickFalse)
8755 windows->image.window_changes.width=(int) (*image)->columns;
8756 windows->image.window_changes.height=(int) (*image)->rows;
8757 XConfigureImageColormap(display,resource_info,windows,*image);
8758 (void) XConfigureImage(display,resource_info,windows,*image);
8761 case AddFrameCommand:
8770 geometry[MaxTextExtent] = "6x6";
8773 Query user for frame color and geometry.
8775 XColorBrowserWidget(display,windows,"Select",color);
8778 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8780 if (*geometry == '\0')
8783 Surround image with an ornamental border.
8785 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
8786 XSetCursorState(display,windows,MagickTrue);
8787 XCheckRefreshWindows(display,windows);
8788 (void) QueryColorDatabase(color,&(*image)->matte_color,
8789 &(*image)->exception);
8790 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8791 &(*image)->exception);
8792 frame_info.width=page_geometry.width;
8793 frame_info.height=page_geometry.height;
8794 frame_info.outer_bevel=page_geometry.x;
8795 frame_info.inner_bevel=page_geometry.y;
8796 frame_info.x=(long) frame_info.width;
8797 frame_info.y=(long) frame_info.height;
8798 frame_info.width=(*image)->columns+2*frame_info.width;
8799 frame_info.height=(*image)->rows+2*frame_info.height;
8800 frame_image=FrameImage(*image,&frame_info,&(*image)->exception);
8801 if (frame_image != (Image *) NULL)
8803 *image=DestroyImage(*image);
8806 CatchException(&(*image)->exception);
8807 XSetCursorState(display,windows,MagickFalse);
8808 if (windows->image.orphan != MagickFalse)
8810 windows->image.window_changes.width=(int) (*image)->columns;
8811 windows->image.window_changes.height=(int) (*image)->rows;
8812 XConfigureImageColormap(display,resource_info,windows,*image);
8813 (void) XConfigureImage(display,resource_info,windows,*image);
8816 case CommentCommand:
8830 unique_file=AcquireUniqueFileResource(image_info->filename);
8831 if (unique_file == -1)
8832 XNoticeWidget(display,windows,"Unable to edit image comment",
8833 image_info->filename);
8834 value=GetImageProperty(*image,"comment");
8835 if (value == (char *) NULL)
8836 unique_file=close(unique_file)-1;
8842 file=fdopen(unique_file,"w");
8843 if (file == (FILE *) NULL)
8845 XNoticeWidget(display,windows,"Unable to edit image comment",
8846 image_info->filename);
8849 for (p=value; *p != '\0'; p++)
8850 (void) fputc((int) *p,file);
8851 (void) fputc('\n',file);
8852 (void) fclose(file);
8854 XSetCursorState(display,windows,MagickTrue);
8855 XCheckRefreshWindows(display,windows);
8856 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
8857 &(*image)->exception);
8858 if (status == MagickFalse)
8859 XNoticeWidget(display,windows,"Unable to edit image comment",
8866 comment=FileToString(image_info->filename,~0UL,&(*image)->exception);
8867 if (comment != (char *) NULL)
8869 (void) SetImageProperty(*image,"comment",comment);
8870 (*image)->taint=MagickTrue;
8873 (void) RelinquishUniqueFileResource(image_info->filename);
8874 XSetCursorState(display,windows,MagickFalse);
8882 XSetCursorState(display,windows,MagickTrue);
8883 XCheckRefreshWindows(display,windows);
8884 (void) AcquireUniqueFilename(filename);
8885 (void) FormatMagickString((*image)->filename,MaxTextExtent,"launch:%s",
8887 status=WriteImage(image_info,*image);
8888 if (status == MagickFalse)
8889 XNoticeWidget(display,windows,"Unable to launch image editor",
8893 nexus=ReadImage(resource_info->image_info,&(*image)->exception);
8894 CatchException(&(*image)->exception);
8895 XClientMessage(display,windows->image.id,windows->im_protocols,
8896 windows->im_next_image,CurrentTime);
8898 (void) RelinquishUniqueFileResource(filename);
8899 XSetCursorState(display,windows,MagickFalse);
8902 case RegionofInterestCommand:
8905 Apply an image processing technique to a region of interest.
8907 (void) XROIImage(display,resource_info,windows,image);
8917 if (windows->magnify.mapped != MagickFalse)
8918 (void) XRaiseWindow(display,windows->magnify.id);
8924 XSetCursorState(display,windows,MagickTrue);
8925 (void) XMapRaised(display,windows->magnify.id);
8926 XSetCursorState(display,windows,MagickFalse);
8930 case ShowPreviewCommand:
8939 preview_type[MaxTextExtent] = "Gamma";
8942 Select preview type from menu.
8944 previews=GetMagickOptions(MagickPreviewOptions);
8945 if (previews == (char **) NULL)
8947 XListBrowserWidget(display,windows,&windows->widget,
8948 (const char **) previews,"Preview",
8949 "Select an enhancement, effect, or F/X:",preview_type);
8950 previews=DestroyStringList(previews);
8951 if (*preview_type == '\0')
8956 XSetCursorState(display,windows,MagickTrue);
8957 XCheckRefreshWindows(display,windows);
8958 image_info->preview_type=(PreviewType)
8959 ParseMagickOption(MagickPreviewOptions,MagickFalse,preview_type);
8960 image_info->group=(long) windows->image.id;
8961 (void) DeleteImageProperty(*image,"label");
8962 (void) SetImageProperty(*image,"label","Preview");
8963 (void) AcquireUniqueFilename(filename);
8964 (void) FormatMagickString((*image)->filename,MaxTextExtent,"preview:%s",
8966 status=WriteImage(image_info,*image);
8967 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8968 preview_image=ReadImage(image_info,&(*image)->exception);
8969 (void) RelinquishUniqueFileResource(filename);
8970 if (preview_image == (Image *) NULL)
8972 (void) FormatMagickString(preview_image->filename,MaxTextExtent,"show:%s",
8974 status=WriteImage(image_info,preview_image);
8975 preview_image=DestroyImage(preview_image);
8976 if (status == MagickFalse)
8977 XNoticeWidget(display,windows,"Unable to show image preview",
8978 (*image)->filename);
8979 XDelay(display,1500);
8980 XSetCursorState(display,windows,MagickFalse);
8983 case ShowHistogramCommand:
8989 Show image histogram.
8991 XSetCursorState(display,windows,MagickTrue);
8992 XCheckRefreshWindows(display,windows);
8993 image_info->group=(long) windows->image.id;
8994 (void) DeleteImageProperty(*image,"label");
8995 (void) SetImageProperty(*image,"label","Histogram");
8996 (void) AcquireUniqueFilename(filename);
8997 (void) FormatMagickString((*image)->filename,MaxTextExtent,"histogram:%s",
8999 status=WriteImage(image_info,*image);
9000 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9001 histogram_image=ReadImage(image_info,&(*image)->exception);
9002 (void) RelinquishUniqueFileResource(filename);
9003 if (histogram_image == (Image *) NULL)
9005 (void) FormatMagickString(histogram_image->filename,MaxTextExtent,
9006 "show:%s",filename);
9007 status=WriteImage(image_info,histogram_image);
9008 histogram_image=DestroyImage(histogram_image);
9009 if (status == MagickFalse)
9010 XNoticeWidget(display,windows,"Unable to show histogram",
9011 (*image)->filename);
9012 XDelay(display,1500);
9013 XSetCursorState(display,windows,MagickFalse);
9016 case ShowMatteCommand:
9021 if ((*image)->matte == MagickFalse)
9023 XNoticeWidget(display,windows,
9024 "Image does not have any matte information",(*image)->filename);
9030 XSetCursorState(display,windows,MagickTrue);
9031 XCheckRefreshWindows(display,windows);
9032 image_info->group=(long) windows->image.id;
9033 (void) DeleteImageProperty(*image,"label");
9034 (void) SetImageProperty(*image,"label","Matte");
9035 (void) AcquireUniqueFilename(filename);
9036 (void) FormatMagickString((*image)->filename,MaxTextExtent,"matte:%s",
9038 status=WriteImage(image_info,*image);
9039 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9040 matte_image=ReadImage(image_info,&(*image)->exception);
9041 (void) RelinquishUniqueFileResource(filename);
9042 if (matte_image == (Image *) NULL)
9044 (void) FormatMagickString(matte_image->filename,MaxTextExtent,"show:%s",
9046 status=WriteImage(image_info,matte_image);
9047 matte_image=DestroyImage(matte_image);
9048 if (status == MagickFalse)
9049 XNoticeWidget(display,windows,"Unable to show matte",
9050 (*image)->filename);
9051 XDelay(display,1500);
9052 XSetCursorState(display,windows,MagickFalse);
9055 case BackgroundCommand:
9060 status=XBackgroundImage(display,resource_info,windows,image);
9061 if (status == MagickFalse)
9063 nexus=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
9064 if (nexus != (Image *) NULL)
9065 XClientMessage(display,windows->image.id,windows->im_protocols,
9066 windows->im_next_image,CurrentTime);
9069 case SlideShowCommand:
9072 delay[MaxTextExtent] = "5";
9075 Display next image after pausing.
9077 (void) XDialogWidget(display,windows,"Slide Show",
9078 "Pause how many 1/100ths of a second between images:",delay);
9081 resource_info->delay=StringToUnsignedLong(delay);
9082 XClientMessage(display,windows->image.id,windows->im_protocols,
9083 windows->im_next_image,CurrentTime);
9086 case PreferencesCommand:
9089 Set user preferences.
9091 status=XPreferencesWidget(display,resource_info,windows);
9092 if (status == MagickFalse)
9094 nexus=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
9095 if (nexus != (Image *) NULL)
9096 XClientMessage(display,windows->image.id,windows->im_protocols,
9097 windows->im_next_image,CurrentTime);
9103 User requested help.
9105 XTextViewWidget(display,resource_info,windows,MagickFalse,
9106 "Help Viewer - Display",DisplayHelp);
9109 case BrowseDocumentationCommand:
9119 Browse the ImageMagick documentation.
9121 root_window=XRootWindow(display,XDefaultScreen(display));
9122 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9123 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9124 if (mozilla_window != (Window) NULL)
9127 command[MaxTextExtent],
9131 Display documentation using Netscape remote control.
9133 url=GetMagickHomeURL();
9134 (void) FormatMagickString(command,MaxTextExtent,
9135 "openurl(%s,new-tab)",url);
9136 url=DestroyString(url);
9137 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9138 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9139 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9140 XSetCursorState(display,windows,MagickFalse);
9143 XSetCursorState(display,windows,MagickTrue);
9144 XCheckRefreshWindows(display,windows);
9145 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9146 &(*image)->exception);
9147 if (status == MagickFalse)
9148 XNoticeWidget(display,windows,"Unable to browse documentation",
9150 XDelay(display,1500);
9151 XSetCursorState(display,windows,MagickFalse);
9154 case VersionCommand:
9156 XNoticeWidget(display,windows,GetMagickVersion((unsigned long *) NULL),
9157 GetMagickCopyright());
9160 case SaveToUndoBufferCommand:
9164 (void) XBell(display,0);
9168 image_info=DestroyImageInfo(image_info);
9173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9177 + X M a g n i f y I m a g e %
9181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9183 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9184 % The magnified portion is displayed in a separate window.
9186 % The format of the XMagnifyImage method is:
9188 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
9190 % A description of each parameter follows:
9192 % o display: Specifies a connection to an X server; returned from
9195 % o windows: Specifies a pointer to a XWindows structure.
9197 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9198 % the entire image is refreshed.
9201 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
9204 text[MaxTextExtent];
9214 Update magnified image until the mouse button is released.
9216 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9220 windows->magnify.x=windows->image.x+x;
9221 windows->magnify.y=windows->image.y+y;
9225 Map and unmap Info widget as text cursor crosses its boundaries.
9227 if (windows->info.mapped != MagickFalse)
9229 if ((x < (int) (windows->info.x+windows->info.width)) &&
9230 (y < (int) (windows->info.y+windows->info.height)))
9231 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9234 if ((x > (int) (windows->info.x+windows->info.width)) ||
9235 (y > (int) (windows->info.y+windows->info.height)))
9236 (void) XMapWindow(display,windows->info.id);
9237 if (windows->info.mapped != MagickFalse)
9240 Display pointer position.
9242 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
9243 windows->magnify.x,windows->magnify.y);
9244 XInfoWidget(display,windows,text);
9247 Wait for next event.
9249 XScreenEvent(display,windows,event);
9250 switch (event->type)
9257 User has finished magnifying image.
9276 Check boundary conditions.
9281 if (x >= (int) windows->image.width)
9282 x=(int) windows->image.width-1;
9286 if (y >= (int) windows->image.height)
9287 y=(int) windows->image.height-1;
9288 } while ((state & ExitState) == 0);
9290 Display magnified image.
9292 XSetCursorState(display,windows,MagickFalse);
9296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9300 + X M a g n i f y W i n d o w C o m m a n d %
9304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9306 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9307 % pixel as specified by the key symbol.
9309 % The format of the XMagnifyWindowCommand method is:
9311 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9312 % const MagickStatusType state,const KeySym key_symbol)
9314 % A description of each parameter follows:
9316 % o display: Specifies a connection to an X server; returned from
9319 % o windows: Specifies a pointer to a XWindows structure.
9321 % o state: key mask.
9323 % o key_symbol: Specifies a KeySym which indicates which side of the image
9327 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9328 const MagickStatusType state,const KeySym key_symbol)
9334 User specified a magnify factor or position.
9337 if ((state & Mod1Mask) != 0)
9339 switch ((int) key_symbol)
9343 (void) XWithdrawWindow(display,windows->magnify.id,
9344 windows->magnify.screen);
9350 windows->magnify.x=(int) windows->image.width/2;
9351 windows->magnify.y=(int) windows->image.height/2;
9357 if (windows->magnify.x > 0)
9358 windows->magnify.x-=quantum;
9364 if (windows->magnify.y > 0)
9365 windows->magnify.y-=quantum;
9371 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9372 windows->magnify.x+=quantum;
9378 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9379 windows->magnify.y+=quantum;
9393 windows->magnify.data=(key_symbol-XK_0);
9407 windows->magnify.data=(key_symbol-XK_KP_0);
9413 XMakeMagnifyImage(display,windows);
9417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9421 + X M a k e P a n I m a g e %
9425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9427 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9430 % The format of the XMakePanImage method is:
9432 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9433 % XWindows *windows,Image *image)
9435 % A description of each parameter follows:
9437 % o display: Specifies a connection to an X server; returned from
9440 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9442 % o windows: Specifies a pointer to a XWindows structure.
9444 % o image: the image.
9447 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9448 XWindows *windows,Image *image)
9454 Create and display image for panning icon.
9456 XSetCursorState(display,windows,MagickTrue);
9457 XCheckRefreshWindows(display,windows);
9458 windows->pan.x=windows->image.x;
9459 windows->pan.y=windows->image.y;
9460 status=XMakeImage(display,resource_info,&windows->pan,image,
9461 windows->pan.width,windows->pan.height);
9462 if (status == MagickFalse)
9463 ThrowXWindowFatalException(XServerError,image->exception.reason,
9464 image->exception.description);
9465 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9466 windows->pan.pixmap);
9467 (void) XClearWindow(display,windows->pan.id);
9468 XDrawPanRectangle(display,windows);
9469 XSetCursorState(display,windows,MagickFalse);
9473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9477 + X M a t t a E d i t I m a g e %
9481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9483 % XMatteEditImage() allows the user to interactively change the Matte channel
9484 % of an image. If the image is PseudoClass it is promoted to DirectClass
9485 % before the matte information is stored.
9487 % The format of the XMatteEditImage method is:
9489 % MagickBooleanType XMatteEditImage(Display *display,
9490 % XResourceInfo *resource_info,XWindows *windows,Image **image)
9492 % A description of each parameter follows:
9494 % o display: Specifies a connection to an X server; returned from
9497 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9499 % o windows: Specifies a pointer to a XWindows structure.
9501 % o image: the image; returned from ReadImage.
9504 static MagickBooleanType XMatteEditImage(Display *display,
9505 XResourceInfo *resource_info,XWindows *windows,Image **image)
9508 matte[MaxTextExtent] = "0";
9523 static const ModeType
9524 MatteEditCommands[] =
9527 MatteEditBorderCommand,
9528 MatteEditFuzzCommand,
9529 MatteEditValueCommand,
9530 MatteEditUndoCommand,
9531 MatteEditHelpCommand,
9532 MatteEditDismissCommand
9536 method = PointMethod;
9539 border_color = { 0, 0, 0, 0, 0, 0 };
9542 command[MaxTextExtent],
9543 text[MaxTextExtent];
9559 register PixelPacket
9575 (void) CloneString(&windows->command.name,"Matte Edit");
9576 windows->command.data=4;
9577 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9578 (void) XMapRaised(display,windows->command.id);
9579 XClientMessage(display,windows->image.id,windows->im_protocols,
9580 windows->im_update_widget,CurrentTime);
9584 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9585 resource_info->background_color,resource_info->foreground_color);
9586 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9588 Track pointer until button 1 is pressed.
9590 XQueryPosition(display,windows->image.id,&x,&y);
9591 (void) XSelectInput(display,windows->image.id,
9592 windows->image.attributes.event_mask | PointerMotionMask);
9596 if (windows->info.mapped != MagickFalse)
9599 Display pointer position.
9601 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
9602 x+windows->image.x,y+windows->image.y);
9603 XInfoWidget(display,windows,text);
9606 Wait for next event.
9608 XScreenEvent(display,windows,&event);
9609 if (event.xany.window == windows->command.id)
9612 Select a command from the Command widget.
9614 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9617 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9620 switch (MatteEditCommands[id])
9622 case MatteEditMethod:
9628 Select a method from the pop-up menu.
9630 methods=GetMagickOptions(MagickMethodOptions);
9631 if (methods == (char **) NULL)
9633 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9634 (const char **) methods,command);
9636 method=(PaintMethod) ParseMagickOption(MagickMethodOptions,
9637 MagickFalse,methods[entry]);
9638 methods=DestroyStringList(methods);
9641 case MatteEditBorderCommand:
9644 *ColorMenu[MaxNumberPens];
9650 Initialize menu selections.
9652 for (i=0; i < (int) (MaxNumberPens-2); i++)
9653 ColorMenu[i]=resource_info->pen_colors[i];
9654 ColorMenu[MaxNumberPens-2]="Browser...";
9655 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9657 Select a pen color from the pop-up menu.
9659 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9660 (const char **) ColorMenu,command);
9663 if (pen_number == (MaxNumberPens-2))
9666 color_name[MaxTextExtent] = "gray";
9669 Select a pen color from a dialog.
9671 resource_info->pen_colors[pen_number]=color_name;
9672 XColorBrowserWidget(display,windows,"Select",color_name);
9673 if (*color_name == '\0')
9679 (void) XParseColor(display,windows->map_info->colormap,
9680 resource_info->pen_colors[pen_number],&border_color);
9683 case MatteEditFuzzCommand:
9686 fuzz[MaxTextExtent];
9701 Select a command from the pop-up menu.
9703 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9709 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*QuantumRange+
9713 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9714 (void) XDialogWidget(display,windows,"Ok",
9715 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9718 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9719 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
9722 case MatteEditValueCommand:
9725 message[MaxTextExtent];
9737 Select a command from the pop-up menu.
9739 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9745 (void) FormatMagickString(matte,MaxTextExtent,QuantumFormat,
9747 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9748 (void) FormatMagickString(matte,MaxTextExtent,QuantumFormat,
9749 (Quantum) TransparentOpacity);
9752 (void) FormatMagickString(message,MaxTextExtent,
9753 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9755 (void) XDialogWidget(display,windows,"Matte",message,matte);
9760 case MatteEditUndoCommand:
9762 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9766 case MatteEditHelpCommand:
9768 XTextViewWidget(display,resource_info,windows,MagickFalse,
9769 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9772 case MatteEditDismissCommand:
9784 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9791 if (event.xbutton.button != Button1)
9793 if ((event.xbutton.window != windows->image.id) &&
9794 (event.xbutton.window != windows->magnify.id))
9801 (void) XMagickCommand(display,resource_info,windows,
9802 SaveToUndoBufferCommand,image);
9803 state|=UpdateConfigurationState;
9808 if (event.xbutton.button != Button1)
9810 if ((event.xbutton.window != windows->image.id) &&
9811 (event.xbutton.window != windows->magnify.id))
9814 Update colormap information.
9818 XConfigureImageColormap(display,resource_info,windows,*image);
9819 (void) XConfigureImage(display,resource_info,windows,*image);
9820 XInfoWidget(display,windows,text);
9821 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9822 state&=(~UpdateConfigurationState);
9830 command[MaxTextExtent];
9835 if (event.xkey.window == windows->magnify.id)
9840 window=windows->magnify.id;
9841 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
9843 if (event.xkey.window != windows->image.id)
9846 Respond to a user key press.
9848 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
9849 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9850 switch ((int) key_symbol)
9864 XTextViewWidget(display,resource_info,windows,MagickFalse,
9865 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9870 (void) XBell(display,0);
9879 Map and unmap Info widget as cursor crosses its boundaries.
9883 if (windows->info.mapped != MagickFalse)
9885 if ((x < (int) (windows->info.x+windows->info.width)) &&
9886 (y < (int) (windows->info.y+windows->info.height)))
9887 (void) XWithdrawWindow(display,windows->info.id,
9888 windows->info.screen);
9891 if ((x > (int) (windows->info.x+windows->info.width)) ||
9892 (y > (int) (windows->info.y+windows->info.height)))
9893 (void) XMapWindow(display,windows->info.id);
9899 if (event.xany.window == windows->magnify.id)
9901 x=windows->magnify.x-windows->image.x;
9902 y=windows->magnify.y-windows->image.y;
9906 if ((state & UpdateConfigurationState) != 0)
9916 Matte edit is relative to image configuration.
9918 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
9920 XPutPixel(windows->image.ximage,x_offset,y_offset,
9921 windows->pixel_info->background_color.pixel);
9922 width=(unsigned int) (*image)->columns;
9923 height=(unsigned int) (*image)->rows;
9926 if (windows->image.crop_geometry != (char *) NULL)
9927 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
9930 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
9932 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
9933 if ((x_offset < 0) || (y_offset < 0))
9935 if ((x_offset >= (int) (*image)->columns) ||
9936 (y_offset >= (int) (*image)->rows))
9938 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
9939 return(MagickFalse);
9940 (*image)->matte=MagickTrue;
9941 exception=(&(*image)->exception);
9948 Update matte information using point algorithm.
9950 q=GetAuthenticPixels(*image,x_offset,y_offset,1,1,exception);
9951 if (q == (PixelPacket *) NULL)
9953 q->opacity=(Quantum) StringToLong(matte);
9954 (void) SyncAuthenticPixels(*image,exception);
9963 Update matte information using replace algorithm.
9965 (void) GetOneVirtualPixel(*image,x_offset,y_offset,&target,
9967 for (y=0; y < (long) (*image)->rows; y++)
9969 q=GetAuthenticPixels(*image,0,y,(*image)->columns,1,
9970 &(*image)->exception);
9971 if (q == (PixelPacket *) NULL)
9973 for (x=0; x < (int) (*image)->columns; x++)
9975 if (IsColorSimilar(*image,q,&target))
9976 q->opacity=(Quantum) StringToLong(matte);
9979 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
9984 case FloodfillMethod:
9985 case FillToBorderMethod:
9994 Update matte information using floodfill algorithm.
9996 (void) GetOneVirtualMagickPixel(*image,x_offset,y_offset,&target,
9998 if (method == FillToBorderMethod)
10000 target.red=(MagickRealType)
10001 ScaleShortToQuantum(border_color.red);
10002 target.green=(MagickRealType)
10003 ScaleShortToQuantum(border_color.green);
10004 target.blue=(MagickRealType)
10005 ScaleShortToQuantum(border_color.blue);
10007 draw_info=CloneDrawInfo(resource_info->image_info,
10008 (DrawInfo *) NULL);
10009 draw_info->fill.opacity=ClampToQuantum(StringToDouble(matte));
10010 (void) FloodfillPaintImage(*image,OpacityChannel,draw_info,&target,
10011 x_offset,y_offset,method == FloodfillMethod ? MagickFalse :
10013 draw_info=DestroyDrawInfo(draw_info);
10019 Update matte information using reset algorithm.
10021 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
10022 return(MagickFalse);
10023 for (y=0; y < (long) (*image)->rows; y++)
10025 q=QueueAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
10026 if (q == (PixelPacket *) NULL)
10028 for (x=0; x < (int) (*image)->columns; x++)
10030 q->opacity=(Quantum) StringToLong(matte);
10033 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
10036 if (StringToLong(matte) == OpaqueOpacity)
10037 (*image)->matte=MagickFalse;
10041 state&=(~UpdateConfigurationState);
10043 } while ((state & ExitState) == 0);
10044 (void) XSelectInput(display,windows->image.id,
10045 windows->image.attributes.event_mask);
10046 XSetCursorState(display,windows,MagickFalse);
10047 (void) XFreeCursor(display,cursor);
10048 return(MagickTrue);
10052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10056 + X O p e n I m a g e %
10060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10062 % XOpenImage() loads an image from a file.
10064 % The format of the XOpenImage method is:
10066 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10067 % XWindows *windows,const unsigned int command)
10069 % A description of each parameter follows:
10071 % o display: Specifies a connection to an X server; returned from
10074 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10076 % o windows: Specifies a pointer to a XWindows structure.
10078 % o command: A value other than zero indicates that the file is selected
10079 % from the command line argument list.
10082 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10083 XWindows *windows,const MagickBooleanType command)
10098 filename[MaxTextExtent] = "\0";
10101 Request file name from user.
10103 if (command == MagickFalse)
10104 XFileBrowserWidget(display,windows,"Open",filename);
10120 Select next image from the command line.
10122 status=XGetCommand(display,windows->image.id,&files,&count);
10125 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10126 return((Image *) NULL);
10128 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10129 if (filelist == (char **) NULL)
10131 ThrowXWindowFatalException(ResourceLimitError,
10132 "MemoryAllocationFailed","...");
10133 (void) XFreeStringList(files);
10134 return((Image *) NULL);
10137 for (i=1; i < count; i++)
10138 if (*files[i] != '-')
10139 filelist[j++]=files[i];
10140 filelist[j]=(char *) NULL;
10141 XListBrowserWidget(display,windows,&windows->widget,
10142 (const char **) filelist,"Load","Select Image to Load:",filename);
10143 filelist=(char **) RelinquishMagickMemory(filelist);
10144 (void) XFreeStringList(files);
10146 if (*filename == '\0')
10147 return((Image *) NULL);
10148 image_info=CloneImageInfo(resource_info->image_info);
10149 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10151 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10152 exception=AcquireExceptionInfo();
10153 (void) SetImageInfo(image_info,0,exception);
10154 if (LocaleCompare(image_info->magick,"X") == 0)
10157 seconds[MaxTextExtent];
10160 User may want to delay the X server screen grab.
10162 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10163 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10165 if (*seconds == '\0')
10166 return((Image *) NULL);
10167 XDelay(display,(unsigned long) (1000*StringToLong(seconds)));
10169 magick_info=GetMagickInfo(image_info->magick,exception);
10170 if ((magick_info != (const MagickInfo *) NULL) &&
10171 (magick_info->raw != MagickFalse))
10174 geometry[MaxTextExtent];
10177 Request image size from the user.
10179 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10180 if (image_info->size != (char *) NULL)
10181 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10182 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10184 (void) CloneString(&image_info->size,geometry);
10189 XSetCursorState(display,windows,MagickTrue);
10190 XCheckRefreshWindows(display,windows);
10191 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10192 nexus=ReadImage(image_info,exception);
10193 CatchException(exception);
10194 XSetCursorState(display,windows,MagickFalse);
10195 if (nexus != (Image *) NULL)
10196 XClientMessage(display,windows->image.id,windows->im_protocols,
10197 windows->im_next_image,CurrentTime);
10205 Unknown image format.
10207 text=FileToString(filename,~0,exception);
10208 if (text == (char *) NULL)
10209 return((Image *) NULL);
10210 textlist=StringToList(text);
10211 if (textlist != (char **) NULL)
10214 title[MaxTextExtent];
10219 (void) FormatMagickString(title,MaxTextExtent,
10220 "Unknown format: %s",filename);
10221 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10222 (const char **) textlist);
10223 for (i=0; textlist[i] != (char *) NULL; i++)
10224 textlist[i]=DestroyString(textlist[i]);
10225 textlist=(char **) RelinquishMagickMemory(textlist);
10227 text=DestroyString(text);
10229 exception=DestroyExceptionInfo(exception);
10230 image_info=DestroyImageInfo(image_info);
10235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10239 + X P a n I m a g e %
10243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10245 % XPanImage() pans the image until the mouse button is released.
10247 % The format of the XPanImage method is:
10249 % void XPanImage(Display *display,XWindows *windows,XEvent *event)
10251 % A description of each parameter follows:
10253 % o display: Specifies a connection to an X server; returned from
10256 % o windows: Specifies a pointer to a XWindows structure.
10258 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10259 % the entire image is refreshed.
10262 static void XPanImage(Display *display,XWindows *windows,XEvent *event)
10265 text[MaxTextExtent];
10283 if ((windows->image.ximage->width > (int) windows->image.width) &&
10284 (windows->image.ximage->height > (int) windows->image.height))
10285 cursor=XCreateFontCursor(display,XC_fleur);
10287 if (windows->image.ximage->width > (int) windows->image.width)
10288 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10290 if (windows->image.ximage->height > (int) windows->image.height)
10291 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10293 cursor=XCreateFontCursor(display,XC_arrow);
10294 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10296 Pan image as pointer moves until the mouse button is released.
10298 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10299 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10300 pan_info.width=windows->pan.width*windows->image.width/
10301 windows->image.ximage->width;
10302 pan_info.height=windows->pan.height*windows->image.height/
10303 windows->image.ximage->height;
10306 state=UpdateConfigurationState;
10309 switch (event->type)
10314 User choose an initial pan location.
10316 pan_info.x=event->xbutton.x;
10317 pan_info.y=event->xbutton.y;
10318 state|=UpdateConfigurationState;
10321 case ButtonRelease:
10324 User has finished panning the image.
10326 pan_info.x=event->xbutton.x;
10327 pan_info.y=event->xbutton.y;
10328 state|=UpdateConfigurationState | ExitState;
10333 pan_info.x=event->xmotion.x;
10334 pan_info.y=event->xmotion.y;
10335 state|=UpdateConfigurationState;
10340 if ((state & UpdateConfigurationState) != 0)
10343 Check boundary conditions.
10345 if (pan_info.x < (int) (pan_info.width/2))
10348 pan_info.x=(int) (x_factor*(pan_info.x-(pan_info.width/2)));
10349 if (pan_info.x < 0)
10352 if ((int) (pan_info.x+windows->image.width) >
10353 windows->image.ximage->width)
10355 (windows->image.ximage->width-windows->image.width);
10356 if (pan_info.y < (long) (pan_info.height/2))
10359 pan_info.y=(long) (y_factor*(pan_info.y-(pan_info.height/2)));
10360 if (pan_info.y < 0)
10363 if ((int) (pan_info.y+windows->image.height) >
10364 windows->image.ximage->height)
10366 (windows->image.ximage->height-windows->image.height);
10367 if ((windows->image.x != (int) pan_info.x) ||
10368 (windows->image.y != (int) pan_info.y))
10371 Display image pan offset.
10373 windows->image.x=(int) pan_info.x;
10374 windows->image.y=(int) pan_info.y;
10375 (void) FormatMagickString(text,MaxTextExtent," %ux%u%+d%+d ",
10376 windows->image.width,windows->image.height,windows->image.x,
10378 XInfoWidget(display,windows,text);
10380 Refresh Image window.
10382 XDrawPanRectangle(display,windows);
10383 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10385 state&=(~UpdateConfigurationState);
10388 Wait for next event.
10390 if ((state & ExitState) == 0)
10391 XScreenEvent(display,windows,event);
10392 } while ((state & ExitState) == 0);
10396 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10397 (void) XFreeCursor(display,cursor);
10398 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10406 + X P a s t e I m a g e %
10410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10412 % XPasteImage() pastes an image previously saved with XCropImage in the X
10413 % window image at a location the user chooses with the pointer.
10415 % The format of the XPasteImage method is:
10417 % MagickBooleanType XPasteImage(Display *display,
10418 % XResourceInfo *resource_info,XWindows *windows,Image *image)
10420 % A description of each parameter follows:
10422 % o display: Specifies a connection to an X server; returned from
10425 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10427 % o windows: Specifies a pointer to a XWindows structure.
10429 % o image: the image; returned from ReadImage.
10432 static MagickBooleanType XPasteImage(Display *display,
10433 XResourceInfo *resource_info,XWindows *windows,Image *image)
10444 static const ModeType
10447 PasteOperatorsCommand,
10449 PasteDismissCommand
10452 static CompositeOperator
10453 compose = CopyCompositeOp;
10456 text[MaxTextExtent];
10490 if (resource_info->copy_image == (Image *) NULL)
10491 return(MagickFalse);
10492 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,
10493 &image->exception);
10495 Map Command widget.
10497 (void) CloneString(&windows->command.name,"Paste");
10498 windows->command.data=1;
10499 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10500 (void) XMapRaised(display,windows->command.id);
10501 XClientMessage(display,windows->image.id,windows->im_protocols,
10502 windows->im_update_widget,CurrentTime);
10504 Track pointer until button 1 is pressed.
10506 XSetCursorState(display,windows,MagickFalse);
10507 XQueryPosition(display,windows->image.id,&x,&y);
10508 (void) XSelectInput(display,windows->image.id,
10509 windows->image.attributes.event_mask | PointerMotionMask);
10510 paste_info.x=windows->image.x+x;
10511 paste_info.y=windows->image.y+y;
10512 paste_info.width=0;
10513 paste_info.height=0;
10514 cursor=XCreateFontCursor(display,XC_ul_angle);
10515 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10516 state=DefaultState;
10519 if (windows->info.mapped != MagickFalse)
10522 Display pointer position.
10524 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
10525 paste_info.x,paste_info.y);
10526 XInfoWidget(display,windows,text);
10528 highlight_info=paste_info;
10529 highlight_info.x=paste_info.x-windows->image.x;
10530 highlight_info.y=paste_info.y-windows->image.y;
10531 XHighlightRectangle(display,windows->image.id,
10532 windows->image.highlight_context,&highlight_info);
10534 Wait for next event.
10536 XScreenEvent(display,windows,&event);
10537 XHighlightRectangle(display,windows->image.id,
10538 windows->image.highlight_context,&highlight_info);
10539 if (event.xany.window == windows->command.id)
10542 Select a command from the Command widget.
10544 id=XCommandWidget(display,windows,PasteMenu,&event);
10547 switch (PasteCommands[id])
10549 case PasteOperatorsCommand:
10552 command[MaxTextExtent],
10556 Select a command from the pop-up menu.
10558 operators=GetMagickOptions(MagickComposeOptions);
10559 if (operators == (char **) NULL)
10561 entry=XMenuWidget(display,windows,PasteMenu[id],
10562 (const char **) operators,command);
10564 compose=(CompositeOperator) ParseMagickOption(
10565 MagickComposeOptions,MagickFalse,operators[entry]);
10566 operators=DestroyStringList(operators);
10569 case PasteHelpCommand:
10571 XTextViewWidget(display,resource_info,windows,MagickFalse,
10572 "Help Viewer - Image Composite",ImagePasteHelp);
10575 case PasteDismissCommand:
10580 state|=EscapeState;
10589 switch (event.type)
10593 if (image->debug != MagickFalse)
10594 (void) LogMagickEvent(X11Event,GetMagickModule(),
10595 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10596 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10597 if (event.xbutton.button != Button1)
10599 if (event.xbutton.window != windows->image.id)
10602 Paste rectangle is relative to image configuration.
10604 width=(unsigned int) image->columns;
10605 height=(unsigned int) image->rows;
10608 if (windows->image.crop_geometry != (char *) NULL)
10609 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10611 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10612 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10613 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10614 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10615 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10616 paste_info.x=windows->image.x+event.xbutton.x;
10617 paste_info.y=windows->image.y+event.xbutton.y;
10620 case ButtonRelease:
10622 if (image->debug != MagickFalse)
10623 (void) LogMagickEvent(X11Event,GetMagickModule(),
10624 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10625 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10626 if (event.xbutton.button != Button1)
10628 if (event.xbutton.window != windows->image.id)
10630 if ((paste_info.width != 0) && (paste_info.height != 0))
10633 User has selected the location of the paste image.
10635 paste_info.x=windows->image.x+event.xbutton.x;
10636 paste_info.y=windows->image.y+event.xbutton.y;
10646 command[MaxTextExtent];
10654 if (event.xkey.window != windows->image.id)
10657 Respond to a user key press.
10659 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10660 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10661 *(command+length)='\0';
10662 if (image->debug != MagickFalse)
10663 (void) LogMagickEvent(X11Event,GetMagickModule(),
10664 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10665 switch ((int) key_symbol)
10673 paste_image=DestroyImage(paste_image);
10674 state|=EscapeState;
10681 (void) XSetFunction(display,windows->image.highlight_context,
10683 XTextViewWidget(display,resource_info,windows,MagickFalse,
10684 "Help Viewer - Image Composite",ImagePasteHelp);
10685 (void) XSetFunction(display,windows->image.highlight_context,
10691 (void) XBell(display,0);
10700 Map and unmap Info widget as text cursor crosses its boundaries.
10704 if (windows->info.mapped != MagickFalse)
10706 if ((x < (int) (windows->info.x+windows->info.width)) &&
10707 (y < (int) (windows->info.y+windows->info.height)))
10708 (void) XWithdrawWindow(display,windows->info.id,
10709 windows->info.screen);
10712 if ((x > (int) (windows->info.x+windows->info.width)) ||
10713 (y > (int) (windows->info.y+windows->info.height)))
10714 (void) XMapWindow(display,windows->info.id);
10715 paste_info.x=windows->image.x+x;
10716 paste_info.y=windows->image.y+y;
10721 if (image->debug != MagickFalse)
10722 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10727 } while ((state & ExitState) == 0);
10728 (void) XSelectInput(display,windows->image.id,
10729 windows->image.attributes.event_mask);
10730 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10731 XSetCursorState(display,windows,MagickFalse);
10732 (void) XFreeCursor(display,cursor);
10733 if ((state & EscapeState) != 0)
10734 return(MagickTrue);
10736 Image pasting is relative to image configuration.
10738 XSetCursorState(display,windows,MagickTrue);
10739 XCheckRefreshWindows(display,windows);
10740 width=(unsigned int) image->columns;
10741 height=(unsigned int) image->rows;
10744 if (windows->image.crop_geometry != (char *) NULL)
10745 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10746 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10748 paste_info.x=(int) (scale_factor*paste_info.x+0.5);
10749 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10750 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10752 paste_info.y=(int) (scale_factor*paste_info.y*scale_factor+0.5);
10753 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10755 Paste image with X Image window.
10757 (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y);
10758 paste_image=DestroyImage(paste_image);
10759 XSetCursorState(display,windows,MagickFalse);
10761 Update image colormap.
10763 XConfigureImageColormap(display,resource_info,windows,image);
10764 (void) XConfigureImage(display,resource_info,windows,image);
10765 return(MagickTrue);
10769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10773 + X P r i n t I m a g e %
10777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10779 % XPrintImage() prints an image to a Postscript printer.
10781 % The format of the XPrintImage method is:
10783 % MagickBooleanType XPrintImage(Display *display,
10784 % XResourceInfo *resource_info,XWindows *windows,Image *image)
10786 % A description of each parameter follows:
10788 % o display: Specifies a connection to an X server; returned from
10791 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10793 % o windows: Specifies a pointer to a XWindows structure.
10795 % o image: the image.
10798 static MagickBooleanType XPrintImage(Display *display,
10799 XResourceInfo *resource_info,XWindows *windows,Image *image)
10802 filename[MaxTextExtent],
10803 geometry[MaxTextExtent];
10815 Request Postscript page geometry from user.
10817 image_info=CloneImageInfo(resource_info->image_info);
10818 (void) FormatMagickString(geometry,MaxTextExtent,"Letter");
10819 if (image_info->page != (char *) NULL)
10820 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
10821 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
10822 "Select Postscript Page Geometry:",geometry);
10823 if (*geometry == '\0')
10824 return(MagickTrue);
10825 image_info->page=GetPageGeometry(geometry);
10827 Apply image transforms.
10829 XSetCursorState(display,windows,MagickTrue);
10830 XCheckRefreshWindows(display,windows);
10831 print_image=CloneImage(image,0,0,MagickTrue,&image->exception);
10832 if (print_image == (Image *) NULL)
10833 return(MagickFalse);
10834 (void) FormatMagickString(geometry,MaxTextExtent,"%dx%d!",
10835 windows->image.ximage->width,windows->image.ximage->height);
10836 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry);
10840 (void) AcquireUniqueFilename(filename);
10841 (void) FormatMagickString(print_image->filename,MaxTextExtent,"print:%s",
10843 status=WriteImage(image_info,print_image);
10844 (void) RelinquishUniqueFileResource(filename);
10845 print_image=DestroyImage(print_image);
10846 image_info=DestroyImageInfo(image_info);
10847 XSetCursorState(display,windows,MagickFalse);
10848 return(status != 0 ? MagickTrue : MagickFalse);
10852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10856 + X R O I I m a g e %
10860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10862 % XROIImage() applies an image processing technique to a region of interest.
10864 % The format of the XROIImage method is:
10866 % MagickBooleanType XROIImage(Display *display,
10867 % XResourceInfo *resource_info,XWindows *windows,Image **image)
10869 % A description of each parameter follows:
10871 % o display: Specifies a connection to an X server; returned from
10874 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10876 % o windows: Specifies a pointer to a XWindows structure.
10878 % o image: the image; returned from ReadImage.
10881 static MagickBooleanType XROIImage(Display *display,
10882 XResourceInfo *resource_info,XWindows *windows,Image **image)
10884 #define ApplyMenus 7
10934 "Contrast Stretch...",
10935 "Sigmoidal Contrast...",
10969 "Charcoal Draw...",
10972 *MiscellanyMenu[] =
10983 **Menus[ApplyMenus] =
10994 static const CommandType
11017 TransformCommands[] =
11021 RotateRightCommand,
11024 EnhanceCommands[] =
11032 ContrastStretchCommand,
11033 SigmoidalContrastCommand,
11041 EffectsCommands[] =
11045 ReduceNoiseCommand,
11064 CharcoalDrawCommand
11066 MiscellanyCommands[] =
11070 ShowPreviewCommand,
11071 ShowHistogramCommand,
11080 static const CommandType
11081 *Commands[ApplyMenus] =
11093 command[MaxTextExtent],
11094 text[MaxTextExtent];
11114 MagickProgressMonitor
11133 Map Command widget.
11135 (void) CloneString(&windows->command.name,"ROI");
11136 windows->command.data=0;
11137 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11138 (void) XMapRaised(display,windows->command.id);
11139 XClientMessage(display,windows->image.id,windows->im_protocols,
11140 windows->im_update_widget,CurrentTime);
11142 Track pointer until button 1 is pressed.
11144 XQueryPosition(display,windows->image.id,&x,&y);
11145 (void) XSelectInput(display,windows->image.id,
11146 windows->image.attributes.event_mask | PointerMotionMask);
11147 roi_info.x=windows->image.x+x;
11148 roi_info.y=windows->image.y+y;
11151 cursor=XCreateFontCursor(display,XC_fleur);
11152 state=DefaultState;
11155 if (windows->info.mapped != MagickFalse)
11158 Display pointer position.
11160 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
11161 roi_info.x,roi_info.y);
11162 XInfoWidget(display,windows,text);
11165 Wait for next event.
11167 XScreenEvent(display,windows,&event);
11168 if (event.xany.window == windows->command.id)
11171 Select a command from the Command widget.
11173 id=XCommandWidget(display,windows,ROIMenu,&event);
11176 switch (ROICommands[id])
11178 case ROIHelpCommand:
11180 XTextViewWidget(display,resource_info,windows,MagickFalse,
11181 "Help Viewer - Region of Interest",ImageROIHelp);
11184 case ROIDismissCommand:
11189 state|=EscapeState;
11198 switch (event.type)
11202 if (event.xbutton.button != Button1)
11204 if (event.xbutton.window != windows->image.id)
11207 Note first corner of region of interest rectangle-- exit loop.
11209 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11210 roi_info.x=windows->image.x+event.xbutton.x;
11211 roi_info.y=windows->image.y+event.xbutton.y;
11215 case ButtonRelease:
11224 if (event.xkey.window != windows->image.id)
11227 Respond to a user key press.
11229 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11230 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11231 switch ((int) key_symbol)
11239 state|=EscapeState;
11246 XTextViewWidget(display,resource_info,windows,MagickFalse,
11247 "Help Viewer - Region of Interest",ImageROIHelp);
11252 (void) XBell(display,0);
11261 Map and unmap Info widget as text cursor crosses its boundaries.
11265 if (windows->info.mapped != MagickFalse)
11267 if ((x < (int) (windows->info.x+windows->info.width)) &&
11268 (y < (int) (windows->info.y+windows->info.height)))
11269 (void) XWithdrawWindow(display,windows->info.id,
11270 windows->info.screen);
11273 if ((x > (int) (windows->info.x+windows->info.width)) ||
11274 (y > (int) (windows->info.y+windows->info.height)))
11275 (void) XMapWindow(display,windows->info.id);
11276 roi_info.x=windows->image.x+x;
11277 roi_info.y=windows->image.y+y;
11283 } while ((state & ExitState) == 0);
11284 (void) XSelectInput(display,windows->image.id,
11285 windows->image.attributes.event_mask);
11286 if ((state & EscapeState) != 0)
11289 User want to exit without region of interest.
11291 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11292 (void) XFreeCursor(display,cursor);
11293 return(MagickTrue);
11295 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11299 Size rectangle as pointer moves until the mouse button is released.
11301 x=(int) roi_info.x;
11302 y=(int) roi_info.y;
11305 state=DefaultState;
11308 highlight_info=roi_info;
11309 highlight_info.x=roi_info.x-windows->image.x;
11310 highlight_info.y=roi_info.y-windows->image.y;
11311 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11314 Display info and draw region of interest rectangle.
11316 if (windows->info.mapped == MagickFalse)
11317 (void) XMapWindow(display,windows->info.id);
11318 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
11319 roi_info.width,roi_info.height,roi_info.x,roi_info.y);
11320 XInfoWidget(display,windows,text);
11321 XHighlightRectangle(display,windows->image.id,
11322 windows->image.highlight_context,&highlight_info);
11325 if (windows->info.mapped != MagickFalse)
11326 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11328 Wait for next event.
11330 XScreenEvent(display,windows,&event);
11331 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11332 XHighlightRectangle(display,windows->image.id,
11333 windows->image.highlight_context,&highlight_info);
11334 switch (event.type)
11338 roi_info.x=windows->image.x+event.xbutton.x;
11339 roi_info.y=windows->image.y+event.xbutton.y;
11342 case ButtonRelease:
11345 User has committed to region of interest rectangle.
11347 roi_info.x=windows->image.x+event.xbutton.x;
11348 roi_info.y=windows->image.y+event.xbutton.y;
11349 XSetCursorState(display,windows,MagickFalse);
11351 if (LocaleCompare(windows->command.name,"Apply") == 0)
11353 (void) CloneString(&windows->command.name,"Apply");
11354 windows->command.data=ApplyMenus;
11355 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11362 roi_info.x=windows->image.x+event.xmotion.x;
11363 roi_info.y=windows->image.y+event.xmotion.y;
11368 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11369 ((state & ExitState) != 0))
11372 Check boundary conditions.
11374 if (roi_info.x < 0)
11377 if (roi_info.x > (int) windows->image.ximage->width)
11378 roi_info.x=windows->image.ximage->width;
11379 if ((int) roi_info.x < x)
11380 roi_info.width=(unsigned int) (x-roi_info.x);
11383 roi_info.width=(unsigned int) (roi_info.x-x);
11386 if (roi_info.y < 0)
11389 if (roi_info.y > (int) windows->image.ximage->height)
11390 roi_info.y=windows->image.ximage->height;
11391 if ((int) roi_info.y < y)
11392 roi_info.height=(unsigned int) (y-roi_info.y);
11395 roi_info.height=(unsigned int) (roi_info.y-y);
11399 } while ((state & ExitState) == 0);
11401 Wait for user to grab a corner of the rectangle or press return.
11403 state=DefaultState;
11404 command_type=NullCommand;
11405 (void) XMapWindow(display,windows->info.id);
11408 if (windows->info.mapped != MagickFalse)
11411 Display pointer position.
11413 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
11414 roi_info.width,roi_info.height,roi_info.x,roi_info.y);
11415 XInfoWidget(display,windows,text);
11417 highlight_info=roi_info;
11418 highlight_info.x=roi_info.x-windows->image.x;
11419 highlight_info.y=roi_info.y-windows->image.y;
11420 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11422 state|=EscapeState;
11426 if ((state & UpdateRegionState) != 0)
11428 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11429 switch (command_type)
11434 (void) XMagickCommand(display,resource_info,windows,command_type,
11441 Region of interest is relative to image configuration.
11443 progress_monitor=SetImageProgressMonitor(*image,
11444 (MagickProgressMonitor) NULL,(*image)->client_data);
11445 crop_info=roi_info;
11446 width=(unsigned int) (*image)->columns;
11447 height=(unsigned int) (*image)->rows;
11450 if (windows->image.crop_geometry != (char *) NULL)
11451 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11453 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11455 crop_info.x=(int) (scale_factor*crop_info.x+0.5);
11456 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11457 scale_factor=(MagickRealType)
11458 height/windows->image.ximage->height;
11460 crop_info.y=(int) (scale_factor*crop_info.y+0.5);
11461 crop_info.height=(unsigned int)
11462 (scale_factor*crop_info.height+0.5);
11463 roi_image=CropImage(*image,&crop_info,&(*image)->exception);
11464 (void) SetImageProgressMonitor(*image,progress_monitor,
11465 (*image)->client_data);
11466 if (roi_image == (Image *) NULL)
11469 Apply image processing technique to the region of interest.
11471 windows->image.orphan=MagickTrue;
11472 (void) XMagickCommand(display,resource_info,windows,command_type,
11474 progress_monitor=SetImageProgressMonitor(*image,
11475 (MagickProgressMonitor) NULL,(*image)->client_data);
11476 (void) XMagickCommand(display,resource_info,windows,
11477 SaveToUndoBufferCommand,image);
11478 windows->image.orphan=MagickFalse;
11479 (void) CompositeImage(*image,CopyCompositeOp,roi_image,
11480 crop_info.x,crop_info.y);
11481 roi_image=DestroyImage(roi_image);
11482 (void) SetImageProgressMonitor(*image,progress_monitor,
11483 (*image)->client_data);
11487 if (command_type != InfoCommand)
11489 XConfigureImageColormap(display,resource_info,windows,*image);
11490 (void) XConfigureImage(display,resource_info,windows,*image);
11492 XCheckRefreshWindows(display,windows);
11493 XInfoWidget(display,windows,text);
11494 (void) XSetFunction(display,windows->image.highlight_context,
11496 state&=(~UpdateRegionState);
11498 XHighlightRectangle(display,windows->image.id,
11499 windows->image.highlight_context,&highlight_info);
11500 XScreenEvent(display,windows,&event);
11501 if (event.xany.window == windows->command.id)
11504 Select a command from the Command widget.
11506 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11507 command_type=NullCommand;
11508 id=XCommandWidget(display,windows,ApplyMenu,&event);
11511 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11512 command_type=ApplyCommands[id];
11513 if (id < ApplyMenus)
11516 Select a command from a pop-up menu.
11518 entry=XMenuWidget(display,windows,ApplyMenu[id],
11519 (const char **) Menus[id],command);
11522 (void) CopyMagickString(command,Menus[id][entry],
11524 command_type=Commands[id][entry];
11528 (void) XSetFunction(display,windows->image.highlight_context,
11530 XHighlightRectangle(display,windows->image.id,
11531 windows->image.highlight_context,&highlight_info);
11532 if (command_type == HelpCommand)
11534 (void) XSetFunction(display,windows->image.highlight_context,
11536 XTextViewWidget(display,resource_info,windows,MagickFalse,
11537 "Help Viewer - Region of Interest",ImageROIHelp);
11538 (void) XSetFunction(display,windows->image.highlight_context,
11542 if (command_type == QuitCommand)
11547 state|=EscapeState;
11551 if (command_type != NullCommand)
11552 state|=UpdateRegionState;
11555 XHighlightRectangle(display,windows->image.id,
11556 windows->image.highlight_context,&highlight_info);
11557 switch (event.type)
11561 x=windows->image.x;
11562 y=windows->image.y;
11563 if (event.xbutton.button != Button1)
11565 if (event.xbutton.window != windows->image.id)
11567 x=windows->image.x+event.xbutton.x;
11568 y=windows->image.y+event.xbutton.y;
11569 if ((x < (int) (roi_info.x+RoiDelta)) &&
11570 (x > (int) (roi_info.x-RoiDelta)) &&
11571 (y < (int) (roi_info.y+RoiDelta)) &&
11572 (y > (int) (roi_info.y-RoiDelta)))
11574 roi_info.x=(long) (roi_info.x+roi_info.width);
11575 roi_info.y=(long) (roi_info.y+roi_info.height);
11576 state|=UpdateConfigurationState;
11579 if ((x < (int) (roi_info.x+RoiDelta)) &&
11580 (x > (int) (roi_info.x-RoiDelta)) &&
11581 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11582 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11584 roi_info.x=(long) (roi_info.x+roi_info.width);
11585 state|=UpdateConfigurationState;
11588 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11589 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11590 (y < (int) (roi_info.y+RoiDelta)) &&
11591 (y > (int) (roi_info.y-RoiDelta)))
11593 roi_info.y=(long) (roi_info.y+roi_info.height);
11594 state|=UpdateConfigurationState;
11597 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11598 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11599 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11600 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11602 state|=UpdateConfigurationState;
11606 case ButtonRelease:
11608 if (event.xbutton.window == windows->pan.id)
11609 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11610 (highlight_info.y != crop_info.y-windows->image.y))
11611 XHighlightRectangle(display,windows->image.id,
11612 windows->image.highlight_context,&highlight_info);
11613 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11614 event.xbutton.time);
11619 if (event.xexpose.window == windows->image.id)
11620 if (event.xexpose.count == 0)
11622 event.xexpose.x=(int) highlight_info.x;
11623 event.xexpose.y=(int) highlight_info.y;
11624 event.xexpose.width=(int) highlight_info.width;
11625 event.xexpose.height=(int) highlight_info.height;
11626 XRefreshWindow(display,&windows->image,&event);
11628 if (event.xexpose.window == windows->info.id)
11629 if (event.xexpose.count == 0)
11630 XInfoWidget(display,windows,text);
11638 if (event.xkey.window != windows->image.id)
11641 Respond to a user key press.
11643 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11644 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11645 switch ((int) key_symbol)
11652 state|=EscapeState;
11661 roi_info.x=(long) (windows->image.width/2L-roi_info.width/2L);
11662 roi_info.y=(long) (windows->image.height/2L-roi_info.height/2L);
11694 (void) XSetFunction(display,windows->image.highlight_context,
11696 XTextViewWidget(display,resource_info,windows,MagickFalse,
11697 "Help Viewer - Region of Interest",ImageROIHelp);
11698 (void) XSetFunction(display,windows->image.highlight_context,
11704 command_type=XImageWindowCommand(display,resource_info,windows,
11705 event.xkey.state,key_symbol,image);
11706 if (command_type != NullCommand)
11707 state|=UpdateRegionState;
11711 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11719 if (event.xbutton.window != windows->image.id)
11722 Map and unmap Info widget as text cursor crosses its boundaries.
11726 if (windows->info.mapped != MagickFalse)
11728 if ((x < (int) (windows->info.x+windows->info.width)) &&
11729 (y < (int) (windows->info.y+windows->info.height)))
11730 (void) XWithdrawWindow(display,windows->info.id,
11731 windows->info.screen);
11734 if ((x > (int) (windows->info.x+windows->info.width)) ||
11735 (y > (int) (windows->info.y+windows->info.height)))
11736 (void) XMapWindow(display,windows->info.id);
11737 roi_info.x=windows->image.x+event.xmotion.x;
11738 roi_info.y=windows->image.y+event.xmotion.y;
11741 case SelectionRequest:
11746 XSelectionRequestEvent
11750 Set primary selection.
11752 (void) FormatMagickString(text,MaxTextExtent,"%lux%lu%+ld%+ld",
11753 roi_info.width,roi_info.height,roi_info.x,roi_info.y);
11754 request=(&(event.xselectionrequest));
11755 (void) XChangeProperty(request->display,request->requestor,
11756 request->property,request->target,8,PropModeReplace,
11757 (unsigned char *) text,(int) strlen(text));
11758 notify.type=SelectionNotify;
11759 notify.display=request->display;
11760 notify.requestor=request->requestor;
11761 notify.selection=request->selection;
11762 notify.target=request->target;
11763 notify.time=request->time;
11764 if (request->property == None)
11765 notify.property=request->target;
11767 notify.property=request->property;
11768 (void) XSendEvent(request->display,request->requestor,False,0,
11769 (XEvent *) ¬ify);
11774 if ((state & UpdateConfigurationState) != 0)
11776 (void) XPutBackEvent(display,&event);
11777 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11780 } while ((state & ExitState) == 0);
11781 } while ((state & ExitState) == 0);
11782 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11783 XSetCursorState(display,windows,MagickFalse);
11784 if ((state & EscapeState) != 0)
11785 return(MagickTrue);
11786 return(MagickTrue);
11790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11794 + X R o t a t e I m a g e %
11798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11800 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11801 % rotation angle is computed from the slope of a line drawn by the user.
11803 % The format of the XRotateImage method is:
11805 % MagickBooleanType XRotateImage(Display *display,
11806 % XResourceInfo *resource_info,XWindows *windows,double degrees,
11809 % A description of each parameter follows:
11811 % o display: Specifies a connection to an X server; returned from
11814 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11816 % o windows: Specifies a pointer to a XWindows structure.
11818 % o degrees: Specifies the number of degrees to rotate the image.
11820 % o image: the image.
11823 static MagickBooleanType XRotateImage(Display *display,
11824 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image)
11837 direction = HorizontalRotateCommand;
11839 static const ModeType
11840 DirectionCommands[] =
11842 HorizontalRotateCommand,
11843 VerticalRotateCommand
11847 RotateColorCommand,
11848 RotateDirectionCommand,
11850 RotateDismissCommand
11853 static unsigned int
11857 command[MaxTextExtent],
11858 text[MaxTextExtent];
11869 normalized_degrees;
11879 if (degrees == 0.0)
11894 Map Command widget.
11896 (void) CloneString(&windows->command.name,"Rotate");
11897 windows->command.data=2;
11898 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
11899 (void) XMapRaised(display,windows->command.id);
11900 XClientMessage(display,windows->image.id,windows->im_protocols,
11901 windows->im_update_widget,CurrentTime);
11903 Wait for first button press.
11905 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11906 XQueryPosition(display,windows->image.id,&x,&y);
11911 state=DefaultState;
11914 XHighlightLine(display,windows->image.id,
11915 windows->image.highlight_context,&rotate_info);
11917 Wait for next event.
11919 XScreenEvent(display,windows,&event);
11920 XHighlightLine(display,windows->image.id,
11921 windows->image.highlight_context,&rotate_info);
11922 if (event.xany.window == windows->command.id)
11925 Select a command from the Command widget.
11927 id=XCommandWidget(display,windows,RotateMenu,&event);
11930 (void) XSetFunction(display,windows->image.highlight_context,
11932 switch (RotateCommands[id])
11934 case RotateColorCommand:
11937 *ColorMenu[MaxNumberPens];
11946 Initialize menu selections.
11948 for (i=0; i < (int) (MaxNumberPens-2); i++)
11949 ColorMenu[i]=resource_info->pen_colors[i];
11950 ColorMenu[MaxNumberPens-2]="Browser...";
11951 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
11953 Select a pen color from the pop-up menu.
11955 pen_number=XMenuWidget(display,windows,RotateMenu[id],
11956 (const char **) ColorMenu,command);
11957 if (pen_number < 0)
11959 if (pen_number == (MaxNumberPens-2))
11962 color_name[MaxTextExtent] = "gray";
11965 Select a pen color from a dialog.
11967 resource_info->pen_colors[pen_number]=color_name;
11968 XColorBrowserWidget(display,windows,"Select",color_name);
11969 if (*color_name == '\0')
11975 (void) XParseColor(display,windows->map_info->colormap,
11976 resource_info->pen_colors[pen_number],&color);
11977 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
11978 (unsigned int) MaxColors,&color);
11979 windows->pixel_info->pen_colors[pen_number]=color;
11980 pen_id=(unsigned int) pen_number;
11983 case RotateDirectionCommand:
11994 Select a command from the pop-up menu.
11996 id=XMenuWidget(display,windows,RotateMenu[id],
11997 Directions,command);
11999 direction=DirectionCommands[id];
12002 case RotateHelpCommand:
12004 XTextViewWidget(display,resource_info,windows,MagickFalse,
12005 "Help Viewer - Image Rotation",ImageRotateHelp);
12008 case RotateDismissCommand:
12013 state|=EscapeState;
12020 (void) XSetFunction(display,windows->image.highlight_context,
12024 switch (event.type)
12028 if (event.xbutton.button != Button1)
12030 if (event.xbutton.window != windows->image.id)
12035 (void) XSetFunction(display,windows->image.highlight_context,
12037 rotate_info.x1=event.xbutton.x;
12038 rotate_info.y1=event.xbutton.y;
12042 case ButtonRelease:
12049 command[MaxTextExtent];
12054 if (event.xkey.window != windows->image.id)
12057 Respond to a user key press.
12059 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12060 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12061 switch ((int) key_symbol)
12069 state|=EscapeState;
12076 (void) XSetFunction(display,windows->image.highlight_context,
12078 XTextViewWidget(display,resource_info,windows,MagickFalse,
12079 "Help Viewer - Image Rotation",ImageRotateHelp);
12080 (void) XSetFunction(display,windows->image.highlight_context,
12086 (void) XBell(display,0);
12094 rotate_info.x1=event.xmotion.x;
12095 rotate_info.y1=event.xmotion.y;
12098 rotate_info.x2=rotate_info.x1;
12099 rotate_info.y2=rotate_info.y1;
12100 if (direction == HorizontalRotateCommand)
12101 rotate_info.x2+=32;
12103 rotate_info.y2-=32;
12104 } while ((state & ExitState) == 0);
12105 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12106 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12107 if ((state & EscapeState) != 0)
12108 return(MagickTrue);
12110 Draw line as pointer moves until the mouse button is released.
12113 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12114 state=DefaultState;
12120 Display info and draw rotation line.
12122 if (windows->info.mapped == MagickFalse)
12123 (void) XMapWindow(display,windows->info.id);
12124 (void) FormatMagickString(text,MaxTextExtent," %g",
12125 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12126 XInfoWidget(display,windows,text);
12127 XHighlightLine(display,windows->image.id,
12128 windows->image.highlight_context,&rotate_info);
12131 if (windows->info.mapped != MagickFalse)
12132 (void) XWithdrawWindow(display,windows->info.id,
12133 windows->info.screen);
12135 Wait for next event.
12137 XScreenEvent(display,windows,&event);
12139 XHighlightLine(display,windows->image.id,
12140 windows->image.highlight_context,&rotate_info);
12141 switch (event.type)
12145 case ButtonRelease:
12148 User has committed to rotation line.
12150 rotate_info.x2=event.xbutton.x;
12151 rotate_info.y2=event.xbutton.y;
12159 rotate_info.x2=event.xmotion.x;
12160 rotate_info.y2=event.xmotion.y;
12166 Check boundary conditions.
12168 if (rotate_info.x2 < 0)
12171 if (rotate_info.x2 > (int) windows->image.width)
12172 rotate_info.x2=(short) windows->image.width;
12173 if (rotate_info.y2 < 0)
12176 if (rotate_info.y2 > (int) windows->image.height)
12177 rotate_info.y2=(short) windows->image.height;
12179 Compute rotation angle from the slope of the line.
12182 distance=(unsigned int)
12183 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12184 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12186 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12187 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12188 } while ((state & ExitState) == 0);
12189 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12190 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12192 return(MagickTrue);
12194 if (direction == VerticalRotateCommand)
12196 if (degrees == 0.0)
12197 return(MagickTrue);
12201 normalized_degrees=degrees;
12202 while (normalized_degrees < -45.0)
12203 normalized_degrees+=360.0;
12204 for (rotations=0; normalized_degrees > 45.0; rotations++)
12205 normalized_degrees-=90.0;
12206 if (normalized_degrees != 0.0)
12207 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
12208 XSetCursorState(display,windows,MagickTrue);
12209 XCheckRefreshWindows(display,windows);
12210 (*image)->background_color.red=ScaleShortToQuantum(
12211 windows->pixel_info->pen_colors[pen_id].red);
12212 (*image)->background_color.green=ScaleShortToQuantum(
12213 windows->pixel_info->pen_colors[pen_id].green);
12214 (*image)->background_color.blue=ScaleShortToQuantum(
12215 windows->pixel_info->pen_colors[pen_id].blue);
12216 rotate_image=RotateImage(*image,degrees,&(*image)->exception);
12217 XSetCursorState(display,windows,MagickFalse);
12218 if (rotate_image == (Image *) NULL)
12219 return(MagickFalse);
12220 *image=DestroyImage(*image);
12221 *image=rotate_image;
12222 if (windows->image.crop_geometry != (char *) NULL)
12225 Rotate crop geometry.
12227 width=(unsigned int) (*image)->columns;
12228 height=(unsigned int) (*image)->rows;
12229 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12230 switch (rotations % 4)
12240 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12241 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12248 Rotate 180 degrees.
12250 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12251 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12257 Rotate 270 degrees.
12259 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12260 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12265 if (windows->image.orphan != MagickFalse)
12266 return(MagickTrue);
12267 if (normalized_degrees != 0.0)
12270 Update image colormap.
12272 windows->image.window_changes.width=(int) (*image)->columns;
12273 windows->image.window_changes.height=(int) (*image)->rows;
12274 if (windows->image.crop_geometry != (char *) NULL)
12277 Obtain dimensions of image from crop geometry.
12279 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12281 windows->image.window_changes.width=(int) width;
12282 windows->image.window_changes.height=(int) height;
12284 XConfigureImageColormap(display,resource_info,windows,*image);
12287 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12289 windows->image.window_changes.width=windows->image.ximage->height;
12290 windows->image.window_changes.height=windows->image.ximage->width;
12293 Update image configuration.
12295 (void) XConfigureImage(display,resource_info,windows,*image);
12296 return(MagickTrue);
12300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12304 + X S a v e I m a g e %
12308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12310 % XSaveImage() saves an image to a file.
12312 % The format of the XSaveImage method is:
12314 % MagickBooleanType XSaveImage(Display *display,
12315 % XResourceInfo *resource_info,XWindows *windows,Image *image)
12317 % A description of each parameter follows:
12319 % o display: Specifies a connection to an X server; returned from
12322 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12324 % o windows: Specifies a pointer to a XWindows structure.
12326 % o image: the image.
12329 static MagickBooleanType XSaveImage(Display *display,
12330 XResourceInfo *resource_info,XWindows *windows,Image *image)
12333 filename[MaxTextExtent],
12334 geometry[MaxTextExtent];
12346 Request file name from user.
12348 if (resource_info->write_filename != (char *) NULL)
12349 (void) CopyMagickString(filename,resource_info->write_filename,
12354 path[MaxTextExtent];
12359 GetPathComponent(image->filename,HeadPath,path);
12360 GetPathComponent(image->filename,TailPath,filename);
12361 status=chdir(path);
12363 (void) ThrowMagickException(&image->exception,GetMagickModule(),
12364 FileOpenError,"UnableToOpenFile","%s",path);
12366 XFileBrowserWidget(display,windows,"Save",filename);
12367 if (*filename == '\0')
12368 return(MagickTrue);
12369 if (IsPathAccessible(filename) != MagickFalse)
12375 File exists-- seek user's permission before overwriting.
12377 status=XConfirmWidget(display,windows,"Overwrite",filename);
12379 return(MagickTrue);
12381 image_info=CloneImageInfo(resource_info->image_info);
12382 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12383 (void) SetImageInfo(image_info,1,&image->exception);
12384 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12385 (LocaleCompare(image_info->magick,"JPG") == 0))
12388 quality[MaxTextExtent];
12394 Request JPEG quality from user.
12396 (void) FormatMagickString(quality,MaxTextExtent,"%lu",image->quality);
12397 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12399 if (*quality == '\0')
12400 return(MagickTrue);
12401 image->quality=StringToUnsignedLong(quality);
12402 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12404 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12405 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12406 (LocaleCompare(image_info->magick,"PS") == 0) ||
12407 (LocaleCompare(image_info->magick,"PS2") == 0))
12410 geometry[MaxTextExtent];
12413 Request page geometry from user.
12415 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12416 if (LocaleCompare(image_info->magick,"PDF") == 0)
12417 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12418 if (image_info->page != (char *) NULL)
12419 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12420 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12421 "Select page geometry:",geometry);
12422 if (*geometry != '\0')
12423 image_info->page=GetPageGeometry(geometry);
12426 Apply image transforms.
12428 XSetCursorState(display,windows,MagickTrue);
12429 XCheckRefreshWindows(display,windows);
12430 save_image=CloneImage(image,0,0,MagickTrue,&image->exception);
12431 if (save_image == (Image *) NULL)
12432 return(MagickFalse);
12433 (void) FormatMagickString(geometry,MaxTextExtent,"%dx%d!",
12434 windows->image.ximage->width,windows->image.ximage->height);
12435 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry);
12439 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12440 status=WriteImage(image_info,save_image);
12441 if (status != MagickFalse)
12442 image->taint=MagickFalse;
12443 save_image=DestroyImage(save_image);
12444 image_info=DestroyImageInfo(image_info);
12445 XSetCursorState(display,windows,MagickFalse);
12446 return(status != 0 ? MagickTrue : MagickFalse);
12450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12454 + X S c r e e n E v e n t %
12458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12460 % XScreenEvent() handles global events associated with the Pan and Magnify
12463 % The format of the XScreenEvent function is:
12465 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12467 % A description of each parameter follows:
12469 % o display: Specifies a pointer to the Display structure; returned from
12472 % o windows: Specifies a pointer to a XWindows structure.
12474 % o event: Specifies a pointer to a X11 XEvent structure.
12479 #if defined(__cplusplus) || defined(c_plusplus)
12483 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12488 windows=(XWindows *) data;
12489 if ((event->type == ClientMessage) &&
12490 (event->xclient.window == windows->image.id))
12491 return(MagickFalse);
12492 return(MagickTrue);
12495 #if defined(__cplusplus) || defined(c_plusplus)
12499 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12505 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12506 if (event->xany.window == windows->command.id)
12508 switch (event->type)
12511 case ButtonRelease:
12513 if ((event->xbutton.button == Button3) &&
12514 (event->xbutton.state & Mod1Mask))
12517 Convert Alt-Button3 to Button2.
12519 event->xbutton.button=Button2;
12520 event->xbutton.state&=(~Mod1Mask);
12522 if (event->xbutton.window == windows->backdrop.id)
12524 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12525 event->xbutton.time);
12528 if (event->xbutton.window == windows->pan.id)
12530 XPanImage(display,windows,event);
12533 if (event->xbutton.window == windows->image.id)
12534 if (event->xbutton.button == Button2)
12537 Update magnified image.
12539 x=event->xbutton.x;
12540 y=event->xbutton.y;
12544 if (x >= (int) windows->image.width)
12545 x=(int) (windows->image.width-1);
12546 windows->magnify.x=windows->image.x+x;
12550 if (y >= (int) windows->image.height)
12551 y=(int) (windows->image.height-1);
12552 windows->magnify.y=windows->image.y+y;
12553 if (windows->magnify.mapped == MagickFalse)
12554 (void) XMapRaised(display,windows->magnify.id);
12555 XMakeMagnifyImage(display,windows);
12556 if (event->type == ButtonRelease)
12557 (void) XWithdrawWindow(display,windows->info.id,
12558 windows->info.screen);
12563 case ClientMessage:
12566 If client window delete message, exit.
12568 if (event->xclient.message_type != windows->wm_protocols)
12570 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12572 if (event->xclient.window == windows->magnify.id)
12574 (void) XWithdrawWindow(display,windows->magnify.id,
12575 windows->magnify.screen);
12580 case ConfigureNotify:
12582 if (event->xconfigure.window == windows->magnify.id)
12588 Magnify window has a new configuration.
12590 windows->magnify.width=(unsigned int) event->xconfigure.width;
12591 windows->magnify.height=(unsigned int) event->xconfigure.height;
12592 if (windows->magnify.mapped == MagickFalse)
12595 while ((int) magnify <= event->xconfigure.width)
12597 while ((int) magnify <= event->xconfigure.height)
12600 if (((int) magnify != event->xconfigure.width) ||
12601 ((int) magnify != event->xconfigure.height))
12606 window_changes.width=(int) magnify;
12607 window_changes.height=(int) magnify;
12608 (void) XReconfigureWMWindow(display,windows->magnify.id,
12609 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12613 XMakeMagnifyImage(display,windows);
12620 if (event->xexpose.window == windows->image.id)
12622 XRefreshWindow(display,&windows->image,event);
12625 if (event->xexpose.window == windows->pan.id)
12626 if (event->xexpose.count == 0)
12628 XDrawPanRectangle(display,windows);
12631 if (event->xexpose.window == windows->magnify.id)
12632 if (event->xexpose.count == 0)
12634 XMakeMagnifyImage(display,windows);
12642 command[MaxTextExtent];
12647 if (event->xkey.window != windows->magnify.id)
12650 Respond to a user key press.
12652 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12653 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12654 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol);
12659 if (event->xmap.window == windows->magnify.id)
12661 windows->magnify.mapped=MagickTrue;
12662 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12665 if (event->xmap.window == windows->info.id)
12667 windows->info.mapped=MagickTrue;
12674 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12675 if (event->xmotion.window == windows->image.id)
12676 if (windows->magnify.mapped != MagickFalse)
12679 Update magnified image.
12681 x=event->xmotion.x;
12682 y=event->xmotion.y;
12686 if (x >= (int) windows->image.width)
12687 x=(int) (windows->image.width-1);
12688 windows->magnify.x=windows->image.x+x;
12692 if (y >= (int) windows->image.height)
12693 y=(int) (windows->image.height-1);
12694 windows->magnify.y=windows->image.y+y;
12695 XMakeMagnifyImage(display,windows);
12701 if (event->xunmap.window == windows->magnify.id)
12703 windows->magnify.mapped=MagickFalse;
12706 if (event->xunmap.window == windows->info.id)
12708 windows->info.mapped=MagickFalse;
12719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12723 + X S e t C r o p G e o m e t r y %
12727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12729 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12730 % and translates it to a cropping geometry relative to the image.
12732 % The format of the XSetCropGeometry method is:
12734 % void XSetCropGeometry(Display *display,XWindows *windows,
12735 % RectangleInfo *crop_info,Image *image)
12737 % A description of each parameter follows:
12739 % o display: Specifies a connection to an X server; returned from
12742 % o windows: Specifies a pointer to a XWindows structure.
12744 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12745 % Image window to crop.
12747 % o image: the image.
12750 static void XSetCropGeometry(Display *display,XWindows *windows,
12751 RectangleInfo *crop_info,Image *image)
12754 text[MaxTextExtent];
12767 if (windows->info.mapped != MagickFalse)
12770 Display info on cropping rectangle.
12772 (void) FormatMagickString(text,MaxTextExtent," %lux%lu%+ld%+ld",
12773 crop_info->width,crop_info->height,crop_info->x,crop_info->y);
12774 XInfoWidget(display,windows,text);
12777 Cropping geometry is relative to any previous crop geometry.
12781 width=(unsigned int) image->columns;
12782 height=(unsigned int) image->rows;
12783 if (windows->image.crop_geometry != (char *) NULL)
12784 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12786 windows->image.crop_geometry=AcquireString((char *) NULL);
12788 Define the crop geometry string from the cropping rectangle.
12790 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12791 if (crop_info->x > 0)
12792 x+=(int) (scale_factor*crop_info->x+0.5);
12793 width=(unsigned int) (scale_factor*crop_info->width+0.5);
12796 scale_factor=(MagickRealType) height/windows->image.ximage->height;
12797 if (crop_info->y > 0)
12798 y+=(int) (scale_factor*crop_info->y+0.5);
12799 height=(unsigned int) (scale_factor*crop_info->height+0.5);
12802 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12803 "%ux%u%+d%+d",width,height,x,y);
12807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12811 + X T i l e I m a g e %
12815 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12817 % XTileImage() loads or deletes a selected tile from a visual image directory.
12818 % The load or delete command is chosen from a menu.
12820 % The format of the XTileImage method is:
12822 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
12823 % XWindows *windows,Image *image,XEvent *event)
12825 % A description of each parameter follows:
12827 % o tile_image: XTileImage reads or deletes the tile image
12828 % and returns it. A null image is returned if an error occurs.
12830 % o display: Specifies a connection to an X server; returned from
12833 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12835 % o windows: Specifies a pointer to a XWindows structure.
12837 % o image: the image; returned from ReadImage.
12839 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
12840 % the entire image is refreshed.
12843 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
12844 XWindows *windows,Image *image,XEvent *event)
12857 static const ModeType
12868 command[MaxTextExtent],
12869 filename[MaxTextExtent];
12896 Tile image is relative to montage image configuration.
12900 width=(unsigned int) image->columns;
12901 height=(unsigned int) image->rows;
12902 if (windows->image.crop_geometry != (char *) NULL)
12903 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12904 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12905 event->xbutton.x+=windows->image.x;
12906 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
12907 scale_factor=(MagickRealType) height/windows->image.ximage->height;
12908 event->xbutton.y+=windows->image.y;
12909 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
12911 Determine size and location of each tile in the visual image directory.
12913 width=(unsigned int) image->columns;
12914 height=(unsigned int) image->rows;
12917 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
12918 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
12919 (event->xbutton.x-x)/width;
12923 Button press is outside any tile.
12925 (void) XBell(display,0);
12926 return((Image *) NULL);
12929 Determine file name from the tile directory.
12931 p=image->directory;
12932 for (i=tile; (i != 0) && (*p != '\0'); )
12941 Button press is outside any tile.
12943 (void) XBell(display,0);
12944 return((Image *) NULL);
12947 Select a command from the pop-up menu.
12949 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
12951 return((Image *) NULL);
12953 while ((*q != '\n') && (*q != '\0'))
12955 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
12957 Perform command for the selected tile.
12959 XSetCursorState(display,windows,MagickTrue);
12960 XCheckRefreshWindows(display,windows);
12961 tile_image=NewImageList();
12962 switch (TileCommands[id])
12964 case TileLoadCommand:
12969 XCheckRefreshWindows(display,windows);
12970 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
12972 (void) CopyMagickString(resource_info->image_info->filename,filename,
12974 tile_image=ReadImage(resource_info->image_info,&image->exception);
12975 CatchException(&image->exception);
12976 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12979 case TileNextCommand:
12982 Display next image.
12984 XClientMessage(display,windows->image.id,windows->im_protocols,
12985 windows->im_next_image,CurrentTime);
12988 case TileFormerCommand:
12991 Display former image.
12993 XClientMessage(display,windows->image.id,windows->im_protocols,
12994 windows->im_former_image,CurrentTime);
12997 case TileDeleteCommand:
13002 if (IsPathAccessible(filename) == MagickFalse)
13004 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13007 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13010 status=remove(filename) != 0 ? MagickTrue : MagickFalse;
13011 if (status != MagickFalse)
13013 XNoticeWidget(display,windows,"Unable to delete image file:",
13018 case TileUpdateCommand:
13033 register PixelPacket
13037 Ensure all the images exist.
13040 for (p=image->directory; *p != '\0'; p++)
13043 while ((*q != '\n') && (*q != '\0'))
13045 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13047 if (IsPathAccessible(filename) != MagickFalse)
13053 Overwrite tile with background color.
13055 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13056 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13057 exception=(&image->exception);
13058 (void) GetOneVirtualPixel(image,0,0,&pixel,exception);
13059 for (i=0; i < (int) height; i++)
13061 s=GetAuthenticPixels(image,x_offset,y_offset+i,width,1,exception);
13062 if (s == (PixelPacket *) NULL)
13064 for (j=0; j < (int) width; j++)
13066 if (SyncAuthenticPixels(image,exception) == MagickFalse)
13071 windows->image.window_changes.width=(int) image->columns;
13072 windows->image.window_changes.height=(int) image->rows;
13073 XConfigureImageColormap(display,resource_info,windows,image);
13074 (void) XConfigureImage(display,resource_info,windows,image);
13080 XSetCursorState(display,windows,MagickFalse);
13081 return(tile_image);
13085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13089 + X T r a n s l a t e I m a g e %
13093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13095 % XTranslateImage() translates the image within an Image window by one pixel
13096 % as specified by the key symbol. If the image has a `montage string the
13097 % translation is respect to the width and height contained within the string.
13099 % The format of the XTranslateImage method is:
13101 % void XTranslateImage(Display *display,XWindows *windows,
13102 % Image *image,const KeySym key_symbol)
13104 % A description of each parameter follows:
13106 % o display: Specifies a connection to an X server; returned from
13109 % o windows: Specifies a pointer to a XWindows structure.
13111 % o image: the image.
13113 % o key_symbol: Specifies a KeySym which indicates which side of the image
13117 static void XTranslateImage(Display *display,XWindows *windows,
13118 Image *image,const KeySym key_symbol)
13121 text[MaxTextExtent];
13132 User specified a pan position offset.
13134 x_offset=windows->image.width;
13135 y_offset=windows->image.height;
13136 if (image->montage != (char *) NULL)
13137 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13138 switch ((int) key_symbol)
13143 windows->image.x=(int) windows->image.width/2;
13144 windows->image.y=(int) windows->image.height/2;
13150 windows->image.x-=x_offset;
13157 windows->image.y-=y_offset;
13163 windows->image.x+=x_offset;
13170 windows->image.y+=y_offset;
13177 Check boundary conditions.
13179 if (windows->image.x < 0)
13180 windows->image.x=0;
13182 if ((int) (windows->image.x+windows->image.width) >
13183 windows->image.ximage->width)
13184 windows->image.x=windows->image.ximage->width-windows->image.width;
13185 if (windows->image.y < 0)
13186 windows->image.y=0;
13188 if ((int) (windows->image.y+windows->image.height) >
13189 windows->image.ximage->height)
13190 windows->image.y=windows->image.ximage->height-windows->image.height;
13192 Refresh Image window.
13194 (void) FormatMagickString(text,MaxTextExtent," %ux%u%+d%+d ",
13195 windows->image.width,windows->image.height,windows->image.x,
13197 XInfoWidget(display,windows,text);
13198 XCheckRefreshWindows(display,windows);
13199 XDrawPanRectangle(display,windows);
13200 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13201 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13209 + X T r i m I m a g e %
13213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13215 % XTrimImage() trims the edges from the Image window.
13217 % The format of the XTrimImage method is:
13219 % MagickBooleanType XTrimImage(Display *display,
13220 % XResourceInfo *resource_info,XWindows *windows,Image *image)
13222 % A description of each parameter follows:
13224 % o display: Specifies a connection to an X server; returned from
13227 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13229 % o windows: Specifies a pointer to a XWindows structure.
13231 % o image: the image.
13234 static MagickBooleanType XTrimImage(Display *display,
13235 XResourceInfo *resource_info,XWindows *windows,Image *image)
13249 Trim edges from image.
13251 XSetCursorState(display,windows,MagickTrue);
13252 XCheckRefreshWindows(display,windows);
13254 Crop the left edge.
13256 background=XGetPixel(windows->image.ximage,0,0);
13257 trim_info.width=(unsigned long) windows->image.ximage->width;
13258 for (x=0; x < windows->image.ximage->width; x++)
13260 for (y=0; y < windows->image.ximage->height; y++)
13262 pixel=XGetPixel(windows->image.ximage,x,y);
13263 if (pixel != background)
13266 if (y < windows->image.ximage->height)
13270 if (trim_info.x == (int) windows->image.ximage->width)
13272 XSetCursorState(display,windows,MagickFalse);
13273 return(MagickFalse);
13276 Crop the right edge.
13278 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13279 for (x=windows->image.ximage->width-1; x != 0; x--)
13281 for (y=0; y < windows->image.ximage->height; y++)
13283 pixel=XGetPixel(windows->image.ximage,x,y);
13284 if (pixel != background)
13287 if (y < windows->image.ximage->height)
13290 trim_info.width=(unsigned long) (x-trim_info.x+1);
13294 background=XGetPixel(windows->image.ximage,0,0);
13295 trim_info.height=(unsigned long) windows->image.ximage->height;
13296 for (y=0; y < windows->image.ximage->height; y++)
13298 for (x=0; x < windows->image.ximage->width; x++)
13300 pixel=XGetPixel(windows->image.ximage,x,y);
13301 if (pixel != background)
13304 if (x < windows->image.ximage->width)
13309 Crop the bottom edge.
13311 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13312 for (y=windows->image.ximage->height-1; y != 0; y--)
13314 for (x=0; x < windows->image.ximage->width; x++)
13316 pixel=XGetPixel(windows->image.ximage,x,y);
13317 if (pixel != background)
13320 if (x < windows->image.ximage->width)
13323 trim_info.height=(unsigned long) y-trim_info.y+1;
13324 if (((unsigned int) trim_info.width != windows->image.width) ||
13325 ((unsigned int) trim_info.height != windows->image.height))
13328 Reconfigure Image window as defined by the trimming rectangle.
13330 XSetCropGeometry(display,windows,&trim_info,image);
13331 windows->image.window_changes.width=(int) trim_info.width;
13332 windows->image.window_changes.height=(int) trim_info.height;
13333 (void) XConfigureImage(display,resource_info,windows,image);
13335 XSetCursorState(display,windows,MagickFalse);
13336 return(MagickTrue);
13340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13344 + X V i s u a l D i r e c t o r y I m a g e %
13348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13350 % XVisualDirectoryImage() creates a Visual Image Directory.
13352 % The format of the XVisualDirectoryImage method is:
13354 % Image *XVisualDirectoryImage(Display *display,
13355 % XResourceInfo *resource_info,XWindows *windows)
13357 % A description of each parameter follows:
13359 % o nexus: Method XVisualDirectoryImage returns a visual image
13360 % directory if it can be created successfully. Otherwise a null image
13363 % o display: Specifies a connection to an X server; returned from
13366 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13368 % o windows: Specifies a pointer to a XWindows structure.
13371 static Image *XVisualDirectoryImage(Display *display,
13372 XResourceInfo *resource_info,XWindows *windows)
13374 #define TileImageTag "Scale/Image"
13375 #define XClientName "montage"
13411 filename[MaxTextExtent] = "\0",
13412 filenames[MaxTextExtent] = "*";
13415 background_resources;
13418 Request file name from user.
13420 XFileBrowserWidget(display,windows,"Directory",filenames);
13421 if (*filenames == '\0')
13422 return((Image *) NULL);
13424 Expand the filenames.
13426 filelist=(char **) AcquireAlignedMemory(1,sizeof(*filelist));
13427 if (filelist == (char **) NULL)
13429 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13431 return((Image *) NULL);
13434 filelist[0]=filenames;
13435 status=ExpandFilenames(&number_files,&filelist);
13436 if ((status == MagickFalse) || (number_files == 0))
13438 if (number_files == 0)
13439 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13441 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13443 return((Image *) NULL);
13446 Set image background resources.
13448 background_resources=(*resource_info);
13449 background_resources.window_id=AcquireString("");
13450 (void) FormatMagickString(background_resources.window_id,MaxTextExtent,
13451 "0x%lx",windows->image.id);
13452 background_resources.backdrop=MagickTrue;
13454 Read each image and convert them to a tile.
13456 backdrop=(windows->visual_info->klass == TrueColor) ||
13457 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13458 read_info=CloneImageInfo(resource_info->image_info);
13459 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13461 images=NewImageList();
13462 exception=AcquireExceptionInfo();
13463 XSetCursorState(display,windows,MagickTrue);
13464 XCheckRefreshWindows(display,windows);
13465 for (i=0; i < (long) number_files; i++)
13467 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13468 filelist[i]=DestroyString(filelist[i]);
13469 *read_info->magick='\0';
13470 (void) CloneString(&read_info->size,DefaultTileGeometry);
13471 next_image=ReadImage(read_info,exception);
13472 CatchException(exception);
13473 if (next_image != (Image *) NULL)
13475 (void) DeleteImageProperty(next_image,"label");
13476 (void) SetImageProperty(next_image,"label",DefaultTileLabel);
13477 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13479 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13480 geometry.height,exception);
13481 if (thumbnail_image != (Image *) NULL)
13483 next_image=DestroyImage(next_image);
13484 next_image=thumbnail_image;
13488 (void) XDisplayBackgroundImage(display,&background_resources,
13490 XSetCursorState(display,windows,MagickTrue);
13492 AppendImageToList(&images,next_image);
13493 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13498 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13499 (MagickSizeType) number_files);
13500 if (proceed == MagickFalse)
13505 exception=DestroyExceptionInfo(exception);
13506 filelist=(char **) RelinquishMagickMemory(filelist);
13507 read_info=DestroyImageInfo(read_info);
13508 if (images == (Image *) NULL)
13510 XSetCursorState(display,windows,MagickFalse);
13511 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13512 return((Image *) NULL);
13515 Create the Visual Image Directory.
13517 montage_info=CloneMontageInfo(resource_info->image_info,(MontageInfo *) NULL);
13518 if (resource_info->font != (char *) NULL)
13519 (void) CloneString(&montage_info->font,resource_info->font);
13520 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13521 montage_image=MontageImageList(resource_info->image_info,montage_info,
13522 GetFirstImageInList(images),&images->exception);
13523 montage_info=DestroyMontageInfo(montage_info);
13524 images=DestroyImageList(images);
13525 XSetCursorState(display,windows,MagickFalse);
13526 if (montage_image == (Image *) NULL)
13527 return(montage_image);
13528 XClientMessage(display,windows->image.id,windows->im_protocols,
13529 windows->im_next_image,CurrentTime);
13530 return(montage_image);
13534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13538 % X D i s p l a y B a c k g r o u n d I m a g e %
13542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13544 % XDisplayBackgroundImage() displays an image in the background of a window.
13546 % The format of the XDisplayBackgroundImage method is:
13548 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13549 % XResourceInfo *resource_info,Image *image)
13551 % A description of each parameter follows:
13553 % o display: Specifies a connection to an X server; returned from
13556 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13558 % o image: the image.
13561 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13562 XResourceInfo *resource_info,Image *image)
13565 geometry[MaxTextExtent],
13566 visual_type[MaxTextExtent];
13579 static XStandardColormap
13583 *visual_info = (XVisualInfo *) NULL;
13604 Determine target window.
13606 assert(image != (Image *) NULL);
13607 assert(image->signature == MagickSignature);
13608 if (image->debug != MagickFalse)
13609 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13610 resources=(*resource_info);
13611 window_info.id=(Window) NULL;
13612 root_window=XRootWindow(display,XDefaultScreen(display));
13613 if (LocaleCompare(resources.window_id,"root") == 0)
13614 window_info.id=root_window;
13617 if (isdigit((unsigned char) *resources.window_id) != 0)
13618 window_info.id=XWindowByID(display,root_window,
13619 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13620 if (window_info.id == (Window) NULL)
13621 window_info.id=XWindowByName(display,root_window,resources.window_id);
13623 if (window_info.id == (Window) NULL)
13625 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13626 resources.window_id);
13627 return(MagickFalse);
13630 Determine window visual id.
13632 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13633 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13634 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13635 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13637 (void) FormatMagickString(visual_type,MaxTextExtent,"0x%lx",
13638 XVisualIDFromVisual(window_attributes.visual));
13639 if (visual_info == (XVisualInfo *) NULL)
13642 Allocate standard colormap.
13644 map_info=XAllocStandardColormap();
13645 if (map_info == (XStandardColormap *) NULL)
13646 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13648 map_info->colormap=(Colormap) NULL;
13649 pixel.pixels=(unsigned long *) NULL;
13651 Initialize visual info.
13653 resources.map_type=(char *) NULL;
13654 resources.visual_type=visual_type;
13655 visual_info=XBestVisualInfo(display,map_info,&resources);
13656 if (visual_info == (XVisualInfo *) NULL)
13657 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13658 resources.visual_type);
13660 Initialize window info.
13662 window_info.ximage=(XImage *) NULL;
13663 window_info.matte_image=(XImage *) NULL;
13664 window_info.pixmap=(Pixmap) NULL;
13665 window_info.matte_pixmap=(Pixmap) NULL;
13668 Free previous root colors.
13670 if (window_info.id == root_window)
13671 (void) XDestroyWindowColors(display,root_window);
13673 Initialize Standard Colormap.
13675 resources.colormap=SharedColormap;
13676 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel);
13678 Graphic context superclass.
13680 context_values.background=pixel.background_color.pixel;
13681 context_values.foreground=pixel.foreground_color.pixel;
13682 pixel.annotate_context=XCreateGC(display,window_info.id,
13683 (unsigned long) (GCBackground | GCForeground),&context_values);
13684 if (pixel.annotate_context == (GC) NULL)
13685 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13688 Initialize Image window attributes.
13690 window_info.name=AcquireString("\0");
13691 window_info.icon_name=AcquireString("\0");
13692 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13693 &resources,&window_info);
13695 Create the X image.
13697 window_info.width=(unsigned int) image->columns;
13698 window_info.height=(unsigned int) image->rows;
13699 if ((image->columns != window_info.width) ||
13700 (image->rows != window_info.height))
13701 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13703 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>",
13704 window_attributes.width,window_attributes.height);
13705 geometry_info.width=window_info.width;
13706 geometry_info.height=window_info.height;
13707 geometry_info.x=window_info.x;
13708 geometry_info.y=window_info.y;
13709 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13710 &geometry_info.width,&geometry_info.height);
13711 window_info.width=(unsigned int) geometry_info.width;
13712 window_info.height=(unsigned int) geometry_info.height;
13713 window_info.x=(int) geometry_info.x;
13714 window_info.y=(int) geometry_info.y;
13715 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13716 window_info.height);
13717 if (status == MagickFalse)
13718 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13722 if (image->debug != MagickFalse)
13724 (void) LogMagickEvent(X11Event,GetMagickModule(),
13725 "Image: %s[%lu] %lux%lu ",image->filename,image->scene,
13726 image->columns,image->rows);
13727 if (image->colors != 0)
13728 (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",image->colors);
13729 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13732 Adjust image dimensions as specified by backdrop or geometry options.
13734 width=(int) window_info.width;
13735 height=(int) window_info.height;
13736 if (resources.backdrop != MagickFalse)
13739 Center image on window.
13741 window_info.x=(window_attributes.width/2)-
13742 (window_info.ximage->width/2);
13743 window_info.y=(window_attributes.height/2)-
13744 (window_info.ximage->height/2);
13745 width=window_attributes.width;
13746 height=window_attributes.height;
13748 if ((resources.image_geometry != (char *) NULL) &&
13749 (*resources.image_geometry != '\0'))
13752 default_geometry[MaxTextExtent];
13762 User specified geometry.
13764 size_hints=XAllocSizeHints();
13765 if (size_hints == (XSizeHints *) NULL)
13766 ThrowXWindowFatalException(ResourceLimitFatalError,
13767 "MemoryAllocationFailed",image->filename);
13768 size_hints->flags=0L;
13769 (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
13771 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13772 default_geometry,window_info.border_width,size_hints,&window_info.x,
13773 &window_info.y,&width,&height,&gravity);
13774 if (flags & (XValue | YValue))
13776 width=window_attributes.width;
13777 height=window_attributes.height;
13779 (void) XFree((void *) size_hints);
13782 Create the X pixmap.
13784 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
13785 (unsigned int) height,window_info.depth);
13786 if (window_info.pixmap == (Pixmap) NULL)
13787 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
13790 Display pixmap on the window.
13792 if (((unsigned int) width > window_info.width) ||
13793 ((unsigned int) height > window_info.height))
13794 (void) XFillRectangle(display,window_info.pixmap,
13795 window_info.annotate_context,0,0,(unsigned int) width,
13796 (unsigned int) height);
13797 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
13798 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
13799 window_info.width,(unsigned int) window_info.height);
13800 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
13801 (void) XClearWindow(display,window_info.id);
13802 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
13803 XDelay(display,delay == 0UL ? 10UL : delay);
13804 (void) XSync(display,MagickFalse);
13805 return(window_info.id == root_window ? MagickTrue : MagickFalse);
13809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13813 + X D i s p l a y I m a g e %
13817 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13819 % XDisplayImage() displays an image via X11. A new image is created and
13820 % returned if the user interactively transforms the displayed image.
13822 % The format of the XDisplayImage method is:
13824 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
13825 % char **argv,int argc,Image **image,unsigned long *state)
13827 % A description of each parameter follows:
13829 % o nexus: Method XDisplayImage returns an image when the
13830 % user chooses 'Open Image' from the command menu or picks a tile
13831 % from the image directory. Otherwise a null image is returned.
13833 % o display: Specifies a connection to an X server; returned from
13836 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13838 % o argv: Specifies the application's argument list.
13840 % o argc: Specifies the number of arguments.
13842 % o image: Specifies an address to an address of an Image structure;
13845 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
13846 char **argv,int argc,Image **image,unsigned long *state)
13848 #define MagnifySize 256 /* must be a power of 2 */
13849 #define MagickMenus 10
13850 #define MagickTitle "Commands"
13877 "Visual Directory...",
13923 "Contrast Stretch...",
13924 "Sigmoidal Contrast...",
13958 "Charcoal Draw...",
13972 "Region of Interest...",
13975 *MiscellanyMenu[] =
13990 "Browse Documentation",
14017 **Menus[MagickMenus] =
14055 VisualDirectoryCommand,
14069 OriginalSizeCommand,
14076 TransformCommands[] =
14082 RotateRightCommand,
14089 EnhanceCommands[] =
14097 ContrastStretchCommand,
14098 SigmoidalContrastCommand,
14106 EffectsCommands[] =
14110 ReduceNoiseCommand,
14130 CharcoalDrawCommand
14132 ImageEditCommands[] =
14143 RegionofInterestCommand
14145 MiscellanyCommands[] =
14149 ShowPreviewCommand,
14150 ShowHistogramCommand,
14159 BrowseDocumentationCommand,
14162 ShortCutsCommands[] =
14174 VirtualCommands[] =
14183 *Commands[MagickMenus] =
14193 MiscellanyCommands,
14198 command[MaxTextExtent],
14200 geometry[MaxTextExtent],
14201 resource_name[MaxTextExtent];
14228 working_directory[MaxTextExtent];
14234 *magick_windows[MaxXWindows];
14236 static unsigned int
14296 assert(image != (Image **) NULL);
14297 assert((*image)->signature == MagickSignature);
14298 if ((*image)->debug != MagickFalse)
14299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14300 display_image=(*image);
14301 warning_handler=(WarningHandler) NULL;
14302 windows=XSetWindows((XWindows *) ~0);
14303 if (windows != (XWindows *) NULL)
14308 status=chdir(working_directory);
14310 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
14311 FileOpenError,"UnableToOpenFile","%s",working_directory);
14312 warning_handler=resource_info->display_warnings ?
14313 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14314 warning_handler=resource_info->display_warnings ?
14315 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14320 Allocate windows structure.
14322 resource_info->colors=display_image->colors;
14323 windows=XSetWindows(XInitializeWindows(display,resource_info));
14324 if (windows == (XWindows *) NULL)
14325 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14326 (*image)->filename);
14328 Initialize window id's.
14331 magick_windows[number_windows++]=(&windows->icon);
14332 magick_windows[number_windows++]=(&windows->backdrop);
14333 magick_windows[number_windows++]=(&windows->image);
14334 magick_windows[number_windows++]=(&windows->info);
14335 magick_windows[number_windows++]=(&windows->command);
14336 magick_windows[number_windows++]=(&windows->widget);
14337 magick_windows[number_windows++]=(&windows->popup);
14338 magick_windows[number_windows++]=(&windows->magnify);
14339 magick_windows[number_windows++]=(&windows->pan);
14340 for (i=0; i < (int) number_windows; i++)
14341 magick_windows[i]->id=(Window) NULL;
14346 Initialize font info.
14348 if (windows->font_info != (XFontStruct *) NULL)
14349 (void) XFreeFont(display,windows->font_info);
14350 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14351 if (windows->font_info == (XFontStruct *) NULL)
14352 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14353 resource_info->font);
14355 Initialize Standard Colormap.
14357 map_info=windows->map_info;
14358 icon_map=windows->icon_map;
14359 visual_info=windows->visual_info;
14360 icon_visual=windows->icon_visual;
14361 pixel=windows->pixel_info;
14362 icon_pixel=windows->icon_pixel;
14363 font_info=windows->font_info;
14364 icon_resources=windows->icon_resources;
14365 class_hints=windows->class_hints;
14366 manager_hints=windows->manager_hints;
14367 root_window=XRootWindow(display,visual_info->screen);
14368 nexus=NewImageList();
14369 if (display_image->debug != MagickFalse)
14371 (void) LogMagickEvent(X11Event,GetMagickModule(),
14372 "Image: %s[%lu] %lux%lu ",display_image->filename,
14373 display_image->scene,display_image->columns,display_image->rows);
14374 if (display_image->colors != 0)
14375 (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
14376 display_image->colors);
14377 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14378 display_image->magick);
14380 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14382 display_image->taint=MagickFalse;
14384 Initialize graphic context.
14386 windows->context.id=(Window) NULL;
14387 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14388 resource_info,&windows->context);
14389 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14390 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14391 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14392 manager_hints->flags=InputHint | StateHint;
14393 manager_hints->input=MagickFalse;
14394 manager_hints->initial_state=WithdrawnState;
14395 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14396 &windows->context);
14397 if (display_image->debug != MagickFalse)
14398 (void) LogMagickEvent(X11Event,GetMagickModule(),
14399 "Window id: 0x%lx (context)",windows->context.id);
14400 context_values.background=pixel->background_color.pixel;
14401 context_values.font=font_info->fid;
14402 context_values.foreground=pixel->foreground_color.pixel;
14403 context_values.graphics_exposures=MagickFalse;
14404 context_mask=(MagickStatusType)
14405 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14406 if (pixel->annotate_context != (GC) NULL)
14407 (void) XFreeGC(display,pixel->annotate_context);
14408 pixel->annotate_context=XCreateGC(display,windows->context.id,
14409 context_mask,&context_values);
14410 if (pixel->annotate_context == (GC) NULL)
14411 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14412 display_image->filename);
14413 context_values.background=pixel->depth_color.pixel;
14414 if (pixel->widget_context != (GC) NULL)
14415 (void) XFreeGC(display,pixel->widget_context);
14416 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14418 if (pixel->widget_context == (GC) NULL)
14419 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14420 display_image->filename);
14421 context_values.background=pixel->foreground_color.pixel;
14422 context_values.foreground=pixel->background_color.pixel;
14423 context_values.plane_mask=context_values.background ^
14424 context_values.foreground;
14425 if (pixel->highlight_context != (GC) NULL)
14426 (void) XFreeGC(display,pixel->highlight_context);
14427 pixel->highlight_context=XCreateGC(display,windows->context.id,
14428 (unsigned long) (context_mask | GCPlaneMask),&context_values);
14429 if (pixel->highlight_context == (GC) NULL)
14430 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14431 display_image->filename);
14432 (void) XDestroyWindow(display,windows->context.id);
14434 Initialize icon window.
14436 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14437 icon_resources,&windows->icon);
14438 windows->icon.geometry=resource_info->icon_geometry;
14439 XBestIconSize(display,&windows->icon,display_image);
14440 windows->icon.attributes.colormap=XDefaultColormap(display,
14441 icon_visual->screen);
14442 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14443 manager_hints->flags=InputHint | StateHint;
14444 manager_hints->input=MagickFalse;
14445 manager_hints->initial_state=IconicState;
14446 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14448 if (display_image->debug != MagickFalse)
14449 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14452 Initialize graphic context for icon window.
14454 if (icon_pixel->annotate_context != (GC) NULL)
14455 (void) XFreeGC(display,icon_pixel->annotate_context);
14456 context_values.background=icon_pixel->background_color.pixel;
14457 context_values.foreground=icon_pixel->foreground_color.pixel;
14458 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14459 (unsigned long) (GCBackground | GCForeground),&context_values);
14460 if (icon_pixel->annotate_context == (GC) NULL)
14461 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14462 display_image->filename);
14463 windows->icon.annotate_context=icon_pixel->annotate_context;
14465 Initialize Image window.
14467 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14469 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14470 if (resource_info->use_shared_memory == MagickFalse)
14471 windows->image.shared_memory=MagickFalse;
14472 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14477 title=InterpretImageProperties(resource_info->image_info,display_image,
14478 resource_info->title);
14479 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14480 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14481 title=DestroyString(title);
14486 filename[MaxTextExtent];
14489 Window name is the base of the filename.
14491 GetPathComponent(display_image->magick_filename,TailPath,filename);
14492 if (GetImageListLength(display_image) == 1)
14493 (void) FormatMagickString(windows->image.name,MaxTextExtent,
14494 "%s: %s",MagickPackageName,filename);
14496 (void) FormatMagickString(windows->image.name,MaxTextExtent,
14497 "%s: %s[%lu of %lu]",MagickPackageName,filename,display_image->scene,
14498 GetImageListLength(display_image));
14499 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14501 if (resource_info->immutable)
14502 windows->image.immutable=MagickTrue;
14503 windows->image.use_pixmap=resource_info->use_pixmap;
14504 windows->image.geometry=resource_info->image_geometry;
14505 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14506 XDisplayWidth(display,visual_info->screen),
14507 XDisplayHeight(display,visual_info->screen));
14508 geometry_info.width=display_image->columns;
14509 geometry_info.height=display_image->rows;
14512 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14513 &geometry_info.width,&geometry_info.height);
14514 windows->image.width=(unsigned int) geometry_info.width;
14515 windows->image.height=(unsigned int) geometry_info.height;
14516 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14517 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14518 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14519 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14520 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14521 resource_info,&windows->backdrop);
14522 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14525 Initialize backdrop window.
14527 windows->backdrop.x=0;
14528 windows->backdrop.y=0;
14529 (void) CloneString(&windows->backdrop.name,"Backdrop");
14530 windows->backdrop.flags=(unsigned long) (USSize | USPosition);
14531 windows->backdrop.width=(unsigned int)
14532 XDisplayWidth(display,visual_info->screen);
14533 windows->backdrop.height=(unsigned int)
14534 XDisplayHeight(display,visual_info->screen);
14535 windows->backdrop.border_width=0;
14536 windows->backdrop.immutable=MagickTrue;
14537 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14539 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14540 StructureNotifyMask;
14541 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14542 manager_hints->icon_window=windows->icon.id;
14543 manager_hints->input=MagickTrue;
14544 manager_hints->initial_state=resource_info->iconic ? IconicState :
14546 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14547 &windows->backdrop);
14548 if (display_image->debug != MagickFalse)
14549 (void) LogMagickEvent(X11Event,GetMagickModule(),
14550 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14551 (void) XMapWindow(display,windows->backdrop.id);
14552 (void) XClearWindow(display,windows->backdrop.id);
14553 if (windows->image.id != (Window) NULL)
14555 (void) XDestroyWindow(display,windows->image.id);
14556 windows->image.id=(Window) NULL;
14559 Position image in the center the backdrop.
14561 windows->image.flags|=USPosition;
14562 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14563 (windows->image.width/2);
14564 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14565 (windows->image.height/2);
14567 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14568 manager_hints->icon_window=windows->icon.id;
14569 manager_hints->input=MagickTrue;
14570 manager_hints->initial_state=resource_info->iconic ? IconicState :
14572 if (windows->group_leader.id != (Window) NULL)
14577 manager_hints->flags|=WindowGroupHint;
14578 manager_hints->window_group=windows->group_leader.id;
14579 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14580 if (display_image->debug != MagickFalse)
14581 (void) LogMagickEvent(X11Event,GetMagickModule(),
14582 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14584 XMakeWindow(display,
14585 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14586 argv,argc,class_hints,manager_hints,&windows->image);
14587 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14588 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14589 if (windows->group_leader.id != (Window) NULL)
14590 (void) XSetTransientForHint(display,windows->image.id,
14591 windows->group_leader.id);
14592 if (display_image->debug != MagickFalse)
14593 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14594 windows->image.id);
14596 Initialize Info widget.
14598 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14600 (void) CloneString(&windows->info.name,"Info");
14601 (void) CloneString(&windows->info.icon_name,"Info");
14602 windows->info.border_width=1;
14605 windows->info.flags|=PPosition;
14606 windows->info.attributes.win_gravity=UnmapGravity;
14607 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14608 StructureNotifyMask;
14609 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14610 manager_hints->input=MagickFalse;
14611 manager_hints->initial_state=NormalState;
14612 manager_hints->window_group=windows->image.id;
14613 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14615 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14616 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14617 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14618 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14619 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14620 if (windows->image.mapped != MagickFalse)
14621 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14622 if (display_image->debug != MagickFalse)
14623 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14626 Initialize Command widget.
14628 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14629 resource_info,&windows->command);
14630 windows->command.data=MagickMenus;
14631 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14632 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.command",
14633 resource_info->client_name);
14634 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14635 resource_name,"geometry",(char *) NULL);
14636 (void) CloneString(&windows->command.name,MagickTitle);
14637 windows->command.border_width=0;
14638 windows->command.flags|=PPosition;
14639 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14640 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14641 OwnerGrabButtonMask | StructureNotifyMask;
14642 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14643 manager_hints->input=MagickTrue;
14644 manager_hints->initial_state=NormalState;
14645 manager_hints->window_group=windows->image.id;
14646 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14647 &windows->command);
14648 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14649 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14651 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14652 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14653 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14654 if (windows->command.mapped != MagickFalse)
14655 (void) XMapRaised(display,windows->command.id);
14656 if (display_image->debug != MagickFalse)
14657 (void) LogMagickEvent(X11Event,GetMagickModule(),
14658 "Window id: 0x%lx (command)",windows->command.id);
14660 Initialize Widget window.
14662 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14663 resource_info,&windows->widget);
14664 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.widget",
14665 resource_info->client_name);
14666 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14667 resource_name,"geometry",(char *) NULL);
14668 windows->widget.border_width=0;
14669 windows->widget.flags|=PPosition;
14670 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14671 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14672 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14673 StructureNotifyMask;
14674 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14675 manager_hints->input=MagickTrue;
14676 manager_hints->initial_state=NormalState;
14677 manager_hints->window_group=windows->image.id;
14678 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14680 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14681 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14682 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14683 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14684 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14685 if (display_image->debug != MagickFalse)
14686 (void) LogMagickEvent(X11Event,GetMagickModule(),
14687 "Window id: 0x%lx (widget)",windows->widget.id);
14689 Initialize popup window.
14691 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14692 resource_info,&windows->popup);
14693 windows->popup.border_width=0;
14694 windows->popup.flags|=PPosition;
14695 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14696 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14697 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14698 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14699 manager_hints->input=MagickTrue;
14700 manager_hints->initial_state=NormalState;
14701 manager_hints->window_group=windows->image.id;
14702 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14704 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14705 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14706 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14707 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14708 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14709 if (display_image->debug != MagickFalse)
14710 (void) LogMagickEvent(X11Event,GetMagickModule(),
14711 "Window id: 0x%lx (pop up)",windows->popup.id);
14713 Initialize Magnify window and cursor.
14715 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14716 resource_info,&windows->magnify);
14717 if (resource_info->use_shared_memory == MagickFalse)
14718 windows->magnify.shared_memory=MagickFalse;
14719 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.magnify",
14720 resource_info->client_name);
14721 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14722 resource_name,"geometry",(char *) NULL);
14723 (void) FormatMagickString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14724 resource_info->magnify);
14725 if (windows->magnify.cursor != (Cursor) NULL)
14726 (void) XFreeCursor(display,windows->magnify.cursor);
14727 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14728 map_info->colormap,resource_info->background_color,
14729 resource_info->foreground_color);
14730 if (windows->magnify.cursor == (Cursor) NULL)
14731 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14732 display_image->filename);
14733 windows->magnify.width=MagnifySize;
14734 windows->magnify.height=MagnifySize;
14735 windows->magnify.flags|=PPosition;
14736 windows->magnify.min_width=MagnifySize;
14737 windows->magnify.min_height=MagnifySize;
14738 windows->magnify.width_inc=MagnifySize;
14739 windows->magnify.height_inc=MagnifySize;
14740 windows->magnify.data=resource_info->magnify;
14741 windows->magnify.attributes.cursor=windows->magnify.cursor;
14742 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14743 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14744 StructureNotifyMask;
14745 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14746 manager_hints->input=MagickTrue;
14747 manager_hints->initial_state=NormalState;
14748 manager_hints->window_group=windows->image.id;
14749 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14750 &windows->magnify);
14751 if (display_image->debug != MagickFalse)
14752 (void) LogMagickEvent(X11Event,GetMagickModule(),
14753 "Window id: 0x%lx (magnify)",windows->magnify.id);
14754 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14756 Initialize panning window.
14758 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14759 resource_info,&windows->pan);
14760 (void) CloneString(&windows->pan.name,"Pan Icon");
14761 windows->pan.width=windows->icon.width;
14762 windows->pan.height=windows->icon.height;
14763 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.pan",
14764 resource_info->client_name);
14765 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14766 resource_name,"geometry",(char *) NULL);
14767 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14768 &windows->pan.width,&windows->pan.height);
14769 windows->pan.flags|=PPosition;
14770 windows->pan.immutable=MagickTrue;
14771 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14772 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
14773 StructureNotifyMask;
14774 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14775 manager_hints->input=MagickFalse;
14776 manager_hints->initial_state=NormalState;
14777 manager_hints->window_group=windows->image.id;
14778 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14780 if (display_image->debug != MagickFalse)
14781 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
14783 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
14784 if (windows->info.mapped != MagickFalse)
14785 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14786 if ((windows->image.mapped == MagickFalse) ||
14787 (windows->backdrop.id != (Window) NULL))
14788 (void) XMapWindow(display,windows->image.id);
14790 Set our progress monitor and warning handlers.
14792 if (warning_handler == (WarningHandler) NULL)
14794 warning_handler=resource_info->display_warnings ?
14795 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14796 warning_handler=resource_info->display_warnings ?
14797 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14800 Initialize Image and Magnify X images.
14802 windows->image.x=0;
14803 windows->image.y=0;
14804 windows->magnify.shape=MagickFalse;
14805 width=(unsigned int) display_image->columns;
14806 height=(unsigned int) display_image->rows;
14807 if ((display_image->columns != width) || (display_image->rows != height))
14808 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14809 display_image->filename);
14810 status=XMakeImage(display,resource_info,&windows->image,display_image,
14812 if (status == MagickFalse)
14813 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14814 display_image->filename);
14815 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
14816 windows->magnify.width,windows->magnify.height);
14817 if (status == MagickFalse)
14818 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14819 display_image->filename);
14820 if (windows->magnify.mapped != MagickFalse)
14821 (void) XMapRaised(display,windows->magnify.id);
14822 if (windows->pan.mapped != MagickFalse)
14823 (void) XMapRaised(display,windows->pan.id);
14824 windows->image.window_changes.width=(int) display_image->columns;
14825 windows->image.window_changes.height=(int) display_image->rows;
14826 (void) XConfigureImage(display,resource_info,windows,display_image);
14827 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14828 (void) XSync(display,MagickFalse);
14832 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
14833 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
14835 if (resource_info->update != MagickFalse)
14841 Determine when file data was last modified.
14843 status=GetPathAttributes(display_image->filename,&attributes);
14844 if (status != MagickFalse)
14845 update_time=attributes.st_mtime;
14847 *state&=(~FormerImageState);
14848 *state&=(~MontageImageState);
14849 *state&=(~NextImageState);
14853 Handle a window event.
14855 if (windows->image.mapped != MagickFalse)
14856 if ((display_image->delay != 0) || (resource_info->update != 0))
14858 if (timer < time((time_t *) NULL))
14860 if (resource_info->update == MagickFalse)
14861 *state|=NextImageState | ExitState;
14868 Determine if image file was modified.
14870 status=GetPathAttributes(display_image->filename,&attributes);
14871 if (status != MagickFalse)
14872 if (update_time != attributes.st_mtime)
14877 (void) FormatMagickString(
14878 resource_info->image_info->filename,MaxTextExtent,
14879 "%s:%s",display_image->magick,
14880 display_image->filename);
14881 nexus=ReadImage(resource_info->image_info,
14882 &display_image->exception);
14883 if (nexus != (Image *) NULL)
14885 nexus=DestroyImage(nexus);
14886 *state|=NextImageState | ExitState;
14889 delay=display_image->delay/MagickMax(
14890 display_image->ticks_per_second,1L);
14891 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
14894 if (XEventsQueued(display,QueuedAfterFlush) == 0)
14897 Do not block if delay > 0.
14899 XDelay(display,SuspendTime << 2);
14903 timestamp=time((time_t *) NULL);
14904 (void) XNextEvent(display,&event);
14905 if (windows->image.stasis == MagickFalse)
14906 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
14907 MagickTrue : MagickFalse;
14908 if (windows->magnify.stasis == MagickFalse)
14909 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
14910 MagickTrue : MagickFalse;
14911 if (event.xany.window == windows->command.id)
14914 Select a command from the Command widget.
14916 id=XCommandWidget(display,windows,CommandMenu,&event);
14919 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
14920 command_type=CommandMenus[id];
14921 if (id < MagickMenus)
14924 Select a command from a pop-up menu.
14926 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
14930 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
14931 command_type=Commands[id][entry];
14933 if (command_type != NullCommand)
14934 nexus=XMagickCommand(display,resource_info,windows,command_type,
14938 switch (event.type)
14942 if (display_image->debug != MagickFalse)
14943 (void) LogMagickEvent(X11Event,GetMagickModule(),
14944 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
14945 event.xbutton.button,event.xbutton.x,event.xbutton.y);
14946 if ((event.xbutton.button == Button3) &&
14947 (event.xbutton.state & Mod1Mask))
14950 Convert Alt-Button3 to Button2.
14952 event.xbutton.button=Button2;
14953 event.xbutton.state&=(~Mod1Mask);
14955 if (event.xbutton.window == windows->backdrop.id)
14957 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
14958 event.xbutton.time);
14961 if (event.xbutton.window == windows->image.id)
14963 switch (event.xbutton.button)
14967 if (resource_info->immutable)
14970 Select a command from the Virtual menu.
14972 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
14975 nexus=XMagickCommand(display,resource_info,windows,
14976 VirtualCommands[entry],&display_image);
14980 Map/unmap Command widget.
14982 if (windows->command.mapped != MagickFalse)
14983 (void) XWithdrawWindow(display,windows->command.id,
14984 windows->command.screen);
14987 (void) XCommandWidget(display,windows,CommandMenu,
14989 (void) XMapRaised(display,windows->command.id);
14996 User pressed the image magnify button.
14998 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15000 XMagnifyImage(display,windows,&event);
15005 if (resource_info->immutable)
15008 Select a command from the Virtual menu.
15010 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15013 nexus=XMagickCommand(display,resource_info,windows,
15014 VirtualCommands[entry],&display_image);
15017 if (display_image->montage != (char *) NULL)
15020 Open or delete a tile from a visual image directory.
15022 nexus=XTileImage(display,resource_info,windows,
15023 display_image,&event);
15024 if (nexus != (Image *) NULL)
15025 *state|=MontageImageState | NextImageState | ExitState;
15026 vid_info.x=windows->image.x;
15027 vid_info.y=windows->image.y;
15031 Select a command from the Short Cuts menu.
15033 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15036 nexus=XMagickCommand(display,resource_info,windows,
15037 ShortCutsCommands[entry],&display_image);
15045 XTranslateImage(display,windows,*image,XK_Up);
15053 XTranslateImage(display,windows,*image,XK_Down);
15061 if (event.xbutton.window == windows->magnify.id)
15081 MagnifyCommands[] =
15094 Select a magnify factor from the pop-up menu.
15096 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15098 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor]);
15101 if (event.xbutton.window == windows->pan.id)
15103 switch (event.xbutton.button)
15110 XTranslateImage(display,windows,*image,XK_Up);
15118 XTranslateImage(display,windows,*image,XK_Down);
15123 XPanImage(display,windows,&event);
15129 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15131 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15134 case ButtonRelease:
15136 if (display_image->debug != MagickFalse)
15137 (void) LogMagickEvent(X11Event,GetMagickModule(),
15138 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15139 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15142 case ClientMessage:
15144 if (display_image->debug != MagickFalse)
15145 (void) LogMagickEvent(X11Event,GetMagickModule(),
15146 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15147 event.xclient.message_type,event.xclient.format,(unsigned long)
15148 event.xclient.data.l[0]);
15149 if (event.xclient.message_type == windows->im_protocols)
15151 if (*event.xclient.data.l == (long) windows->im_update_widget)
15153 (void) CloneString(&windows->command.name,MagickTitle);
15154 windows->command.data=MagickMenus;
15155 (void) XCommandWidget(display,windows,CommandMenu,
15159 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15162 Update graphic context and window colormap.
15164 for (i=0; i < (int) number_windows; i++)
15166 if (magick_windows[i]->id == windows->icon.id)
15168 context_values.background=pixel->background_color.pixel;
15169 context_values.foreground=pixel->foreground_color.pixel;
15170 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15171 context_mask,&context_values);
15172 (void) XChangeGC(display,magick_windows[i]->widget_context,
15173 context_mask,&context_values);
15174 context_values.background=pixel->foreground_color.pixel;
15175 context_values.foreground=pixel->background_color.pixel;
15176 context_values.plane_mask=context_values.background ^
15177 context_values.foreground;
15178 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15179 (unsigned long) (context_mask | GCPlaneMask),
15181 magick_windows[i]->attributes.background_pixel=
15182 pixel->background_color.pixel;
15183 magick_windows[i]->attributes.border_pixel=
15184 pixel->border_color.pixel;
15185 magick_windows[i]->attributes.colormap=map_info->colormap;
15186 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15187 magick_windows[i]->mask,&magick_windows[i]->attributes);
15189 if (windows->pan.mapped != MagickFalse)
15191 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15192 windows->pan.pixmap);
15193 (void) XClearWindow(display,windows->pan.id);
15194 XDrawPanRectangle(display,windows);
15196 if (windows->backdrop.id != (Window) NULL)
15197 (void) XInstallColormap(display,map_info->colormap);
15200 if (*event.xclient.data.l == (long) windows->im_former_image)
15202 *state|=FormerImageState | ExitState;
15205 if (*event.xclient.data.l == (long) windows->im_next_image)
15207 *state|=NextImageState | ExitState;
15210 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15212 *state|=RetainColorsState;
15215 if (*event.xclient.data.l == (long) windows->im_exit)
15222 if (event.xclient.message_type == windows->dnd_protocols)
15240 Display image named by the Drag-and-Drop selection.
15242 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15244 selection=XInternAtom(display,"DndSelection",MagickFalse);
15245 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15246 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15247 &length,&after,&data);
15248 if ((status != Success) || (length == 0))
15250 if (*event.xclient.data.l == 2)
15255 (void) CopyMagickString(resource_info->image_info->filename,
15256 (char *) data,MaxTextExtent);
15263 if (strncmp((char *) data, "file:", 5) != 0)
15265 (void) XFree((void *) data);
15268 (void) CopyMagickString(resource_info->image_info->filename,
15269 ((char *) data)+5,MaxTextExtent);
15271 nexus=ReadImage(resource_info->image_info,
15272 &display_image->exception);
15273 CatchException(&display_image->exception);
15274 if (nexus != (Image *) NULL)
15275 *state|=NextImageState | ExitState;
15276 (void) XFree((void *) data);
15280 If client window delete message, exit.
15282 if (event.xclient.message_type != windows->wm_protocols)
15284 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15286 (void) XWithdrawWindow(display,event.xclient.window,
15287 visual_info->screen);
15288 if (event.xclient.window == windows->image.id)
15293 if (event.xclient.window == windows->pan.id)
15296 Restore original image size when pan window is deleted.
15298 windows->image.window_changes.width=windows->image.ximage->width;
15299 windows->image.window_changes.height=windows->image.ximage->height;
15300 (void) XConfigureImage(display,resource_info,windows,
15305 case ConfigureNotify:
15307 if (display_image->debug != MagickFalse)
15308 (void) LogMagickEvent(X11Event,GetMagickModule(),
15309 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15310 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15311 event.xconfigure.y,event.xconfigure.send_event);
15312 if (event.xconfigure.window == windows->image.id)
15315 Image window has a new configuration.
15317 if (event.xconfigure.send_event != 0)
15323 Position the transient windows relative of the Image window.
15325 if (windows->command.geometry == (char *) NULL)
15326 if (windows->command.mapped == MagickFalse)
15328 windows->command.x=event.xconfigure.x-
15329 windows->command.width-25;
15330 windows->command.y=event.xconfigure.y;
15331 XConstrainWindowPosition(display,&windows->command);
15332 window_changes.x=windows->command.x;
15333 window_changes.y=windows->command.y;
15334 (void) XReconfigureWMWindow(display,windows->command.id,
15335 windows->command.screen,(unsigned int) (CWX | CWY),
15338 if (windows->widget.geometry == (char *) NULL)
15339 if (windows->widget.mapped == MagickFalse)
15341 windows->widget.x=event.xconfigure.x+
15342 event.xconfigure.width/10;
15343 windows->widget.y=event.xconfigure.y+
15344 event.xconfigure.height/10;
15345 XConstrainWindowPosition(display,&windows->widget);
15346 window_changes.x=windows->widget.x;
15347 window_changes.y=windows->widget.y;
15348 (void) XReconfigureWMWindow(display,windows->widget.id,
15349 windows->widget.screen,(unsigned int) (CWX | CWY),
15352 if (windows->magnify.geometry == (char *) NULL)
15353 if (windows->magnify.mapped == MagickFalse)
15355 windows->magnify.x=event.xconfigure.x+
15356 event.xconfigure.width+25;
15357 windows->magnify.y=event.xconfigure.y;
15358 XConstrainWindowPosition(display,&windows->magnify);
15359 window_changes.x=windows->magnify.x;
15360 window_changes.y=windows->magnify.y;
15361 (void) XReconfigureWMWindow(display,windows->magnify.id,
15362 windows->magnify.screen,(unsigned int) (CWX | CWY),
15365 if (windows->pan.geometry == (char *) NULL)
15366 if (windows->pan.mapped == MagickFalse)
15368 windows->pan.x=event.xconfigure.x+
15369 event.xconfigure.width+25;
15370 windows->pan.y=event.xconfigure.y+
15371 windows->magnify.height+50;
15372 XConstrainWindowPosition(display,&windows->pan);
15373 window_changes.x=windows->pan.x;
15374 window_changes.y=windows->pan.y;
15375 (void) XReconfigureWMWindow(display,windows->pan.id,
15376 windows->pan.screen,(unsigned int) (CWX | CWY),
15380 if ((event.xconfigure.width == (long) windows->image.width) &&
15381 (event.xconfigure.height == (long) windows->image.height))
15383 windows->image.width=(unsigned int) event.xconfigure.width;
15384 windows->image.height=(unsigned int) event.xconfigure.height;
15385 windows->image.x=0;
15386 windows->image.y=0;
15387 if (display_image->montage != (char *) NULL)
15389 windows->image.x=vid_info.x;
15390 windows->image.y=vid_info.y;
15392 if ((windows->image.mapped != MagickFalse) &&
15393 (windows->image.stasis != MagickFalse))
15396 Update image window configuration.
15398 windows->image.window_changes.width=event.xconfigure.width;
15399 windows->image.window_changes.height=event.xconfigure.height;
15400 (void) XConfigureImage(display,resource_info,windows,
15404 Update pan window configuration.
15406 if ((event.xconfigure.width < windows->image.ximage->width) ||
15407 (event.xconfigure.height < windows->image.ximage->height))
15409 (void) XMapRaised(display,windows->pan.id);
15410 XDrawPanRectangle(display,windows);
15413 if (windows->pan.mapped != MagickFalse)
15414 (void) XWithdrawWindow(display,windows->pan.id,
15415 windows->pan.screen);
15418 if (event.xconfigure.window == windows->magnify.id)
15424 Magnify window has a new configuration.
15426 windows->magnify.width=(unsigned int) event.xconfigure.width;
15427 windows->magnify.height=(unsigned int) event.xconfigure.height;
15428 if (windows->magnify.mapped == MagickFalse)
15431 while ((int) magnify <= event.xconfigure.width)
15433 while ((int) magnify <= event.xconfigure.height)
15436 if (((int) magnify != event.xconfigure.width) ||
15437 ((int) magnify != event.xconfigure.height))
15439 window_changes.width=(int) magnify;
15440 window_changes.height=(int) magnify;
15441 (void) XReconfigureWMWindow(display,windows->magnify.id,
15442 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15446 if ((windows->magnify.mapped != MagickFalse) &&
15447 (windows->magnify.stasis != MagickFalse))
15449 status=XMakeImage(display,resource_info,&windows->magnify,
15450 display_image,windows->magnify.width,windows->magnify.height);
15451 XMakeMagnifyImage(display,windows);
15455 if ((windows->magnify.mapped != MagickFalse) &&
15456 (event.xconfigure.window == windows->pan.id))
15459 Pan icon window has a new configuration.
15461 if (event.xconfigure.send_event != 0)
15463 windows->pan.x=event.xconfigure.x;
15464 windows->pan.y=event.xconfigure.y;
15466 windows->pan.width=(unsigned int) event.xconfigure.width;
15467 windows->pan.height=(unsigned int) event.xconfigure.height;
15470 if (event.xconfigure.window == windows->icon.id)
15473 Icon window has a new configuration.
15475 windows->icon.width=(unsigned int) event.xconfigure.width;
15476 windows->icon.height=(unsigned int) event.xconfigure.height;
15481 case DestroyNotify:
15484 Group leader has exited.
15486 if (display_image->debug != MagickFalse)
15487 (void) LogMagickEvent(X11Event,GetMagickModule(),
15488 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15489 if (event.xdestroywindow.window == windows->group_leader.id)
15499 Selectively install colormap.
15501 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15502 if (event.xcrossing.mode != NotifyUngrab)
15503 XInstallColormap(display,map_info->colormap);
15508 if (display_image->debug != MagickFalse)
15509 (void) LogMagickEvent(X11Event,GetMagickModule(),
15510 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15511 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15514 Refresh windows that are now exposed.
15516 if ((event.xexpose.window == windows->image.id) &&
15517 (windows->image.mapped != MagickFalse))
15519 XRefreshWindow(display,&windows->image,&event);
15520 delay=display_image->delay/MagickMax(
15521 display_image->ticks_per_second,1L);
15522 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15525 if ((event.xexpose.window == windows->magnify.id) &&
15526 (windows->magnify.mapped != MagickFalse))
15528 XMakeMagnifyImage(display,windows);
15531 if (event.xexpose.window == windows->pan.id)
15533 XDrawPanRectangle(display,windows);
15536 if (event.xexpose.window == windows->icon.id)
15538 XRefreshWindow(display,&windows->icon,&event);
15549 Respond to a user key press.
15551 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15552 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15553 *(command+length)='\0';
15554 if (display_image->debug != MagickFalse)
15555 (void) LogMagickEvent(X11Event,GetMagickModule(),
15556 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15557 key_symbol,command);
15558 if (event.xkey.window == windows->image.id)
15560 command_type=XImageWindowCommand(display,resource_info,windows,
15561 event.xkey.state,key_symbol,&display_image);
15562 if (command_type != NullCommand)
15563 nexus=XMagickCommand(display,resource_info,windows,command_type,
15566 if (event.xkey.window == windows->magnify.id)
15567 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol);
15568 if (event.xkey.window == windows->pan.id)
15570 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15571 (void) XWithdrawWindow(display,windows->pan.id,
15572 windows->pan.screen);
15574 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15575 XTextViewWidget(display,resource_info,windows,MagickFalse,
15576 "Help Viewer - Image Pan",ImagePanHelp);
15578 XTranslateImage(display,windows,*image,key_symbol);
15580 delay=display_image->delay/MagickMax(
15581 display_image->ticks_per_second,1L);
15582 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15588 Respond to a user key release.
15590 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15591 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15592 if (display_image->debug != MagickFalse)
15593 (void) LogMagickEvent(X11Event,GetMagickModule(),
15594 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15600 Selectively uninstall colormap.
15602 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15603 if (event.xcrossing.mode != NotifyUngrab)
15604 XUninstallColormap(display,map_info->colormap);
15609 if (display_image->debug != MagickFalse)
15610 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15611 event.xmap.window);
15612 if (event.xmap.window == windows->backdrop.id)
15614 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15616 windows->backdrop.mapped=MagickTrue;
15619 if (event.xmap.window == windows->image.id)
15621 if (windows->backdrop.id != (Window) NULL)
15622 (void) XInstallColormap(display,map_info->colormap);
15623 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15625 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15626 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15628 if (((int) windows->image.width < windows->image.ximage->width) ||
15629 ((int) windows->image.height < windows->image.ximage->height))
15630 (void) XMapRaised(display,windows->pan.id);
15631 windows->image.mapped=MagickTrue;
15634 if (event.xmap.window == windows->magnify.id)
15636 XMakeMagnifyImage(display,windows);
15637 windows->magnify.mapped=MagickTrue;
15638 (void) XWithdrawWindow(display,windows->info.id,
15639 windows->info.screen);
15642 if (event.xmap.window == windows->pan.id)
15644 XMakePanImage(display,resource_info,windows,display_image);
15645 windows->pan.mapped=MagickTrue;
15648 if (event.xmap.window == windows->info.id)
15650 windows->info.mapped=MagickTrue;
15653 if (event.xmap.window == windows->icon.id)
15659 Create an icon image.
15661 taint=display_image->taint;
15662 XMakeStandardColormap(display,icon_visual,icon_resources,
15663 display_image,icon_map,icon_pixel);
15664 (void) XMakeImage(display,icon_resources,&windows->icon,
15665 display_image,windows->icon.width,windows->icon.height);
15666 display_image->taint=taint;
15667 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15668 windows->icon.pixmap);
15669 (void) XClearWindow(display,windows->icon.id);
15670 (void) XWithdrawWindow(display,windows->info.id,
15671 windows->info.screen);
15672 windows->icon.mapped=MagickTrue;
15675 if (event.xmap.window == windows->command.id)
15677 windows->command.mapped=MagickTrue;
15680 if (event.xmap.window == windows->popup.id)
15682 windows->popup.mapped=MagickTrue;
15685 if (event.xmap.window == windows->widget.id)
15687 windows->widget.mapped=MagickTrue;
15692 case MappingNotify:
15694 (void) XRefreshKeyboardMapping(&event.xmapping);
15699 case PropertyNotify:
15715 if (display_image->debug != MagickFalse)
15716 (void) LogMagickEvent(X11Event,GetMagickModule(),
15717 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15718 event.xproperty.atom,event.xproperty.state);
15719 if (event.xproperty.atom != windows->im_remote_command)
15722 Display image named by the remote command protocol.
15724 status=XGetWindowProperty(display,event.xproperty.window,
15725 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15726 AnyPropertyType,&type,&format,&length,&after,&data);
15727 if ((status != Success) || (length == 0))
15729 if (LocaleCompare((char *) data,"-quit") == 0)
15731 XClientMessage(display,windows->image.id,windows->im_protocols,
15732 windows->im_exit,CurrentTime);
15733 (void) XFree((void *) data);
15736 (void) CopyMagickString(resource_info->image_info->filename,
15737 (char *) data,MaxTextExtent);
15738 (void) XFree((void *) data);
15739 nexus=ReadImage(resource_info->image_info,&display_image->exception);
15740 CatchException(&display_image->exception);
15741 if (nexus != (Image *) NULL)
15742 *state|=NextImageState | ExitState;
15745 case ReparentNotify:
15747 if (display_image->debug != MagickFalse)
15748 (void) LogMagickEvent(X11Event,GetMagickModule(),
15749 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15750 event.xreparent.window);
15755 if (display_image->debug != MagickFalse)
15756 (void) LogMagickEvent(X11Event,GetMagickModule(),
15757 "Unmap Notify: 0x%lx",event.xunmap.window);
15758 if (event.xunmap.window == windows->backdrop.id)
15760 windows->backdrop.mapped=MagickFalse;
15763 if (event.xunmap.window == windows->image.id)
15765 windows->image.mapped=MagickFalse;
15768 if (event.xunmap.window == windows->magnify.id)
15770 windows->magnify.mapped=MagickFalse;
15773 if (event.xunmap.window == windows->pan.id)
15775 windows->pan.mapped=MagickFalse;
15778 if (event.xunmap.window == windows->info.id)
15780 windows->info.mapped=MagickFalse;
15783 if (event.xunmap.window == windows->icon.id)
15785 if (map_info->colormap == icon_map->colormap)
15786 XConfigureImageColormap(display,resource_info,windows,
15788 (void) XFreeStandardColormap(display,icon_visual,icon_map,
15790 windows->icon.mapped=MagickFalse;
15793 if (event.xunmap.window == windows->command.id)
15795 windows->command.mapped=MagickFalse;
15798 if (event.xunmap.window == windows->popup.id)
15800 if (windows->backdrop.id != (Window) NULL)
15801 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
15803 windows->popup.mapped=MagickFalse;
15806 if (event.xunmap.window == windows->widget.id)
15808 if (windows->backdrop.id != (Window) NULL)
15809 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
15811 windows->widget.mapped=MagickFalse;
15818 if (display_image->debug != MagickFalse)
15819 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
15824 } while (!(*state & ExitState));
15825 if ((*state & ExitState) == 0)
15826 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
15829 if (resource_info->confirm_edit != MagickFalse)
15832 Query user if image has changed.
15834 if ((resource_info->immutable == MagickFalse) &&
15835 (display_image->taint != MagickFalse))
15840 status=XConfirmWidget(display,windows,"Your image changed.",
15841 "Do you want to save it");
15843 *state&=(~ExitState);
15846 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
15850 if ((windows->visual_info->klass == GrayScale) ||
15851 (windows->visual_info->klass == PseudoColor) ||
15852 (windows->visual_info->klass == DirectColor))
15855 Withdraw pan and Magnify window.
15857 if (windows->info.mapped != MagickFalse)
15858 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15859 if (windows->magnify.mapped != MagickFalse)
15860 (void) XWithdrawWindow(display,windows->magnify.id,
15861 windows->magnify.screen);
15862 if (windows->command.mapped != MagickFalse)
15863 (void) XWithdrawWindow(display,windows->command.id,
15864 windows->command.screen);
15866 if (windows->pan.mapped != MagickFalse)
15867 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
15868 if (resource_info->backdrop == MagickFalse)
15869 if (windows->backdrop.mapped)
15871 (void) XWithdrawWindow(display,windows->backdrop.id,
15872 windows->backdrop.screen);
15873 (void) XDestroyWindow(display,windows->backdrop.id);
15874 windows->backdrop.id=(Window) NULL;
15875 (void) XWithdrawWindow(display,windows->image.id,
15876 windows->image.screen);
15877 (void) XDestroyWindow(display,windows->image.id);
15878 windows->image.id=(Window) NULL;
15880 XSetCursorState(display,windows,MagickTrue);
15881 XCheckRefreshWindows(display,windows);
15882 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
15883 *state&=(~ExitState);
15884 if (*state & ExitState)
15887 Free Standard Colormap.
15889 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
15890 if (resource_info->map_type == (char *) NULL)
15891 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
15895 if (resource_info->copy_image != (Image *) NULL)
15897 resource_info->copy_image=DestroyImage(resource_info->copy_image);
15898 resource_info->copy_image=NewImageList();
15900 DestroyXResources();
15902 (void) XSync(display,MagickFalse);
15904 Restore our progress monitor and warning handlers.
15906 (void) SetErrorHandler(warning_handler);
15907 (void) SetWarningHandler(warning_handler);
15909 Change to home directory.
15911 cwd=getcwd(working_directory,MaxTextExtent);
15916 status=chdir(resource_info->home_directory);
15918 (void) ThrowMagickException(&display_image->exception,GetMagickModule(),
15919 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
15921 *image=display_image;
15927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15931 + D i s p l a y I m a g e s %
15935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15937 % DisplayImages() displays an image sequence to any X window screen. It
15938 % returns a value other than 0 if successful. Check the exception member
15939 % of image to determine the reason for any failure.
15941 % The format of the DisplayImages method is:
15943 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
15946 % A description of each parameter follows:
15948 % o image_info: the image info.
15950 % o image: the image.
15953 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
15956 assert(image_info != (const ImageInfo *) NULL);
15957 assert(image_info->signature == MagickSignature);
15958 assert(image != (Image *) NULL);
15959 assert(image->signature == MagickSignature);
15960 if (image->debug != MagickFalse)
15961 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
15962 (void) ThrowMagickException(&image->exception,GetMagickModule(),
15963 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
15965 return(MagickFalse);
15969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15973 + R e m o t e D i s p l a y C o m m a n d %
15977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15979 % RemoteDisplayCommand() encourages a remote display program to display the
15980 % specified image filename.
15982 % The format of the RemoteDisplayCommand method is:
15984 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
15985 % const char *window,const char *filename,ExceptionInfo *exception)
15987 % A description of each parameter follows:
15989 % o image_info: the image info.
15991 % o window: Specifies the name or id of an X window.
15993 % o filename: the name of the image filename to display.
15995 % o exception: return any errors or warnings in this structure.
15998 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
15999 const char *window,const char *filename,ExceptionInfo *exception)
16001 assert(image_info != (const ImageInfo *) NULL);
16002 assert(image_info->signature == MagickSignature);
16003 assert(filename != (char *) NULL);
16005 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16006 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16007 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename);
16008 return(MagickFalse);