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 >= (ssize_t) 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 ssize_t MagickMax(const ssize_t x,const ssize_t y)
1780 static inline ssize_t MagickMin(const ssize_t x,const ssize_t 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 *) AcquireMagickMemory(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 < (ssize_t) 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 < (ssize_t) 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 < (ssize_t) 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,
3084 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3085 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3086 XInfoWidget(display,windows,text);
3087 XHighlightLine(display,windows->image.id,
3088 windows->image.highlight_context,&segment_info);
3091 if (windows->info.mapped != MagickFalse)
3092 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3094 Wait for next event.
3096 XScreenEvent(display,windows,&event);
3098 XHighlightLine(display,windows->image.id,
3099 windows->image.highlight_context,&segment_info);
3104 segment_info.x2=(short int) event.xmotion.x;
3105 segment_info.y2=(short int) event.xmotion.y;
3111 User has committed to chopping line.
3113 segment_info.x2=(short int) event.xbutton.x;
3114 segment_info.y2=(short int) event.xbutton.y;
3122 segment_info.x2=(short int) event.xmotion.x;
3123 segment_info.y2=(short int) event.xmotion.y;
3129 Check boundary conditions.
3131 if (segment_info.x2 < 0)
3134 if (segment_info.x2 > windows->image.ximage->width)
3135 segment_info.x2=windows->image.ximage->width;
3136 if (segment_info.y2 < 0)
3139 if (segment_info.y2 > windows->image.ximage->height)
3140 segment_info.y2=windows->image.ximage->height;
3141 distance=(unsigned int)
3142 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3143 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3145 Compute chopping geometry.
3147 if (direction == HorizontalChopCommand)
3149 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3150 chop_info.x=windows->image.x+segment_info.x1;
3153 if (segment_info.x1 > (int) segment_info.x2)
3155 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3156 chop_info.x=windows->image.x+segment_info.x2;
3162 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3164 chop_info.y=windows->image.y+segment_info.y1;
3165 if (segment_info.y1 > segment_info.y2)
3167 chop_info.height=(size_t)
3168 (segment_info.y1-segment_info.y2+1);
3169 chop_info.y=windows->image.y+segment_info.y2;
3172 } while ((state & ExitState) == 0);
3173 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3174 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3178 Image chopping is relative to image configuration.
3180 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
3181 XSetCursorState(display,windows,MagickTrue);
3182 XCheckRefreshWindows(display,windows);
3183 windows->image.window_changes.width=windows->image.ximage->width-
3184 (unsigned int) chop_info.width;
3185 windows->image.window_changes.height=windows->image.ximage->height-
3186 (unsigned int) chop_info.height;
3187 width=(unsigned int) (*image)->columns;
3188 height=(unsigned int) (*image)->rows;
3191 if (windows->image.crop_geometry != (char *) NULL)
3192 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3193 scale_factor=(MagickRealType) width/windows->image.ximage->width;
3195 chop_info.x=(int) (scale_factor*chop_info.x+0.5);
3196 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3197 scale_factor=(MagickRealType) height/windows->image.ximage->height;
3199 chop_info.y=(int) (scale_factor*chop_info.y+0.5);
3200 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3204 chop_image=ChopImage(*image,&chop_info,&(*image)->exception);
3205 XSetCursorState(display,windows,MagickFalse);
3206 if (chop_image == (Image *) NULL)
3207 return(MagickFalse);
3208 *image=DestroyImage(*image);
3211 Update image configuration.
3213 XConfigureImageColormap(display,resource_info,windows,*image);
3214 (void) XConfigureImage(display,resource_info,windows,*image);
3219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3223 + X C o l o r E d i t I m a g e %
3227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3229 % XColorEditImage() allows the user to interactively change the color of one
3230 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3232 % The format of the XColorEditImage method is:
3234 % MagickBooleanType XColorEditImage(Display *display,
3235 % XResourceInfo *resource_info,XWindows *windows,Image **image)
3237 % A description of each parameter follows:
3239 % o display: Specifies a connection to an X server; returned from
3242 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3244 % o windows: Specifies a pointer to a XWindows structure.
3246 % o image: the image; returned from ReadImage.
3251 static MagickBooleanType XColorEditImage(Display *display,
3252 XResourceInfo *resource_info,XWindows *windows,Image **image)
3267 static const ModeType
3268 ColorEditCommands[] =
3270 ColorEditMethodCommand,
3271 ColorEditColorCommand,
3272 ColorEditBorderCommand,
3273 ColorEditFuzzCommand,
3274 ColorEditUndoCommand,
3275 ColorEditHelpCommand,
3276 ColorEditDismissCommand
3280 method = PointMethod;
3286 border_color = { 0, 0, 0, 0, 0, 0 };
3289 command[MaxTextExtent],
3290 text[MaxTextExtent];
3306 register PixelPacket
3328 (void) CloneString(&windows->command.name,"Color Edit");
3329 windows->command.data=4;
3330 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3331 (void) XMapRaised(display,windows->command.id);
3332 XClientMessage(display,windows->image.id,windows->im_protocols,
3333 windows->im_update_widget,CurrentTime);
3337 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3338 resource_info->background_color,resource_info->foreground_color);
3339 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3341 Track pointer until button 1 is pressed.
3343 XQueryPosition(display,windows->image.id,&x,&y);
3344 (void) XSelectInput(display,windows->image.id,
3345 windows->image.attributes.event_mask | PointerMotionMask);
3349 if (windows->info.mapped != MagickFalse)
3352 Display pointer position.
3354 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
3355 x+windows->image.x,y+windows->image.y);
3356 XInfoWidget(display,windows,text);
3359 Wait for next event.
3361 XScreenEvent(display,windows,&event);
3362 if (event.xany.window == windows->command.id)
3365 Select a command from the Command widget.
3367 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3370 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3373 switch (ColorEditCommands[id])
3375 case ColorEditMethodCommand:
3381 Select a method from the pop-up menu.
3383 methods=(char **) GetMagickOptions(MagickMethodOptions);
3384 if (methods == (char **) NULL)
3386 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3387 (const char **) methods,command);
3389 method=(PaintMethod) ParseMagickOption(MagickMethodOptions,
3390 MagickFalse,methods[entry]);
3391 methods=DestroyStringList(methods);
3394 case ColorEditColorCommand:
3397 *ColorMenu[MaxNumberPens];
3403 Initialize menu selections.
3405 for (i=0; i < (int) (MaxNumberPens-2); i++)
3406 ColorMenu[i]=resource_info->pen_colors[i];
3407 ColorMenu[MaxNumberPens-2]="Browser...";
3408 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3410 Select a pen color from the pop-up menu.
3412 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3413 (const char **) ColorMenu,command);
3416 if (pen_number == (MaxNumberPens-2))
3419 color_name[MaxTextExtent] = "gray";
3422 Select a pen color from a dialog.
3424 resource_info->pen_colors[pen_number]=color_name;
3425 XColorBrowserWidget(display,windows,"Select",color_name);
3426 if (*color_name == '\0')
3432 (void) XParseColor(display,windows->map_info->colormap,
3433 resource_info->pen_colors[pen_number],&color);
3434 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3435 (unsigned int) MaxColors,&color);
3436 windows->pixel_info->pen_colors[pen_number]=color;
3437 pen_id=(unsigned int) pen_number;
3440 case ColorEditBorderCommand:
3443 *ColorMenu[MaxNumberPens];
3449 Initialize menu selections.
3451 for (i=0; i < (int) (MaxNumberPens-2); i++)
3452 ColorMenu[i]=resource_info->pen_colors[i];
3453 ColorMenu[MaxNumberPens-2]="Browser...";
3454 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3456 Select a pen color from the pop-up menu.
3458 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3459 (const char **) ColorMenu,command);
3462 if (pen_number == (MaxNumberPens-2))
3465 color_name[MaxTextExtent] = "gray";
3468 Select a pen color from a dialog.
3470 resource_info->pen_colors[pen_number]=color_name;
3471 XColorBrowserWidget(display,windows,"Select",color_name);
3472 if (*color_name == '\0')
3478 (void) XParseColor(display,windows->map_info->colormap,
3479 resource_info->pen_colors[pen_number],&border_color);
3482 case ColorEditFuzzCommand:
3485 fuzz[MaxTextExtent];
3500 Select a command from the pop-up menu.
3502 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3508 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*
3512 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3513 (void) XDialogWidget(display,windows,"Ok",
3514 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3517 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3518 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
3521 case ColorEditUndoCommand:
3523 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3527 case ColorEditHelpCommand:
3530 XTextViewWidget(display,resource_info,windows,MagickFalse,
3531 "Help Viewer - Image Annotation",ImageColorEditHelp);
3534 case ColorEditDismissCommand:
3544 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3551 if (event.xbutton.button != Button1)
3553 if ((event.xbutton.window != windows->image.id) &&
3554 (event.xbutton.window != windows->magnify.id))
3561 (void) XMagickCommand(display,resource_info,windows,
3562 SaveToUndoBufferCommand,image);
3563 state|=UpdateConfigurationState;
3568 if (event.xbutton.button != Button1)
3570 if ((event.xbutton.window != windows->image.id) &&
3571 (event.xbutton.window != windows->magnify.id))
3574 Update colormap information.
3578 XConfigureImageColormap(display,resource_info,windows,*image);
3579 (void) XConfigureImage(display,resource_info,windows,*image);
3580 XInfoWidget(display,windows,text);
3581 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3582 state&=(~UpdateConfigurationState);
3592 if (event.xkey.window == windows->magnify.id)
3597 window=windows->magnify.id;
3598 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3600 if (event.xkey.window != windows->image.id)
3603 Respond to a user key press.
3605 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3606 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3607 switch ((int) key_symbol)
3621 XTextViewWidget(display,resource_info,windows,MagickFalse,
3622 "Help Viewer - Image Annotation",ImageColorEditHelp);
3627 (void) XBell(display,0);
3636 Map and unmap Info widget as cursor crosses its boundaries.
3640 if (windows->info.mapped != MagickFalse)
3642 if ((x < (int) (windows->info.x+windows->info.width)) &&
3643 (y < (int) (windows->info.y+windows->info.height)))
3644 (void) XWithdrawWindow(display,windows->info.id,
3645 windows->info.screen);
3648 if ((x > (int) (windows->info.x+windows->info.width)) ||
3649 (y > (int) (windows->info.y+windows->info.height)))
3650 (void) XMapWindow(display,windows->info.id);
3656 if (event.xany.window == windows->magnify.id)
3658 x=windows->magnify.x-windows->image.x;
3659 y=windows->magnify.y-windows->image.y;
3663 if ((state & UpdateConfigurationState) != 0)
3670 Pixel edit is relative to image configuration.
3672 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3674 color=windows->pixel_info->pen_colors[pen_id];
3675 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3676 width=(unsigned int) (*image)->columns;
3677 height=(unsigned int) (*image)->rows;
3680 if (windows->image.crop_geometry != (char *) NULL)
3681 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3684 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3686 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3687 if ((x_offset < 0) || (y_offset < 0))
3689 if ((x_offset >= (ssize_t) (*image)->columns) ||
3690 (y_offset >= (ssize_t) (*image)->rows))
3692 exception=(&(*image)->exception);
3699 Update color information using point algorithm.
3701 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
3702 return(MagickFalse);
3703 q=GetAuthenticPixels(*image,x_offset,y_offset,1,1,exception);
3704 if (q == (PixelPacket *) NULL)
3706 q->red=ScaleShortToQuantum(color.red);
3707 q->green=ScaleShortToQuantum(color.green);
3708 q->blue=ScaleShortToQuantum(color.blue);
3709 (void) SyncAuthenticPixels(*image,&(*image)->exception);
3718 Update color information using replace algorithm.
3720 (void) GetOneVirtualPixel(*image,x_offset,y_offset,&target,
3721 &(*image)->exception);
3722 if ((*image)->storage_class == DirectClass)
3724 for (y=0; y < (ssize_t) (*image)->rows; y++)
3726 q=GetAuthenticPixels(*image,0,y,(*image)->columns,1,
3728 if (q == (PixelPacket *) NULL)
3730 for (x=0; x < (int) (*image)->columns; x++)
3732 if (IsColorSimilar(*image,q,&target))
3734 q->red=ScaleShortToQuantum(color.red);
3735 q->green=ScaleShortToQuantum(color.green);
3736 q->blue=ScaleShortToQuantum(color.blue);
3740 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
3746 for (i=0; i < (int) (*image)->colors; i++)
3747 if (IsColorSimilar(*image,(*image)->colormap+i,&target))
3749 (*image)->colormap[i].red=ScaleShortToQuantum(color.red);
3750 (*image)->colormap[i].green=ScaleShortToQuantum(
3752 (*image)->colormap[i].blue=ScaleShortToQuantum(
3755 (void) SyncImage(*image);
3759 case FloodfillMethod:
3760 case FillToBorderMethod:
3769 Update color information using floodfill algorithm.
3771 (void) GetOneVirtualMagickPixel(*image,x_offset,y_offset,&target,
3773 if (method == FillToBorderMethod)
3775 target.red=(MagickRealType)
3776 ScaleShortToQuantum(border_color.red);
3777 target.green=(MagickRealType)
3778 ScaleShortToQuantum(border_color.green);
3779 target.blue=(MagickRealType)
3780 ScaleShortToQuantum(border_color.blue);
3782 draw_info=CloneDrawInfo(resource_info->image_info,
3784 (void) QueryColorDatabase(resource_info->pen_colors[pen_id],
3785 &draw_info->fill,exception);
3786 (void) FloodfillPaintImage(*image,DefaultChannels,draw_info,&target,
3787 x_offset,y_offset,method == FloodfillMethod ? MagickFalse :
3789 draw_info=DestroyDrawInfo(draw_info);
3795 Update color information using reset algorithm.
3797 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
3798 return(MagickFalse);
3799 for (y=0; y < (ssize_t) (*image)->rows; y++)
3801 q=QueueAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
3802 if (q == (PixelPacket *) NULL)
3804 for (x=0; x < (int) (*image)->columns; x++)
3806 q->red=ScaleShortToQuantum(color.red);
3807 q->green=ScaleShortToQuantum(color.green);
3808 q->blue=ScaleShortToQuantum(color.blue);
3811 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
3817 state&=(~UpdateConfigurationState);
3819 } while ((state & ExitState) == 0);
3820 (void) XSelectInput(display,windows->image.id,
3821 windows->image.attributes.event_mask);
3822 XSetCursorState(display,windows,MagickFalse);
3823 (void) XFreeCursor(display,cursor);
3828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3832 + X C o m p o s i t e I m a g e %
3836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3838 % XCompositeImage() requests an image name from the user, reads the image and
3839 % composites it with the X window image at a location the user chooses with
3842 % The format of the XCompositeImage method is:
3844 % MagickBooleanType XCompositeImage(Display *display,
3845 % XResourceInfo *resource_info,XWindows *windows,Image *image)
3847 % A description of each parameter follows:
3849 % o display: Specifies a connection to an X server; returned from
3852 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3854 % o windows: Specifies a pointer to a XWindows structure.
3856 % o image: the image; returned from ReadImage.
3859 static MagickBooleanType XCompositeImage(Display *display,
3860 XResourceInfo *resource_info,XWindows *windows,Image *image)
3863 displacement_geometry[MaxTextExtent] = "30x30",
3864 filename[MaxTextExtent] = "\0";
3877 static CompositeOperator
3878 compose = CopyCompositeOp;
3880 static const ModeType
3881 CompositeCommands[] =
3883 CompositeOperatorsCommand,
3884 CompositeDissolveCommand,
3885 CompositeDisplaceCommand,
3886 CompositeHelpCommand,
3887 CompositeDismissCommand
3891 text[MaxTextExtent];
3924 Request image file name from user.
3926 XFileBrowserWidget(display,windows,"Composite",filename);
3927 if (*filename == '\0')
3932 XSetCursorState(display,windows,MagickTrue);
3933 XCheckRefreshWindows(display,windows);
3934 (void) CopyMagickString(resource_info->image_info->filename,filename,
3936 composite_image=ReadImage(resource_info->image_info,&image->exception);
3937 CatchException(&image->exception);
3938 XSetCursorState(display,windows,MagickFalse);
3939 if (composite_image == (Image *) NULL)
3940 return(MagickFalse);
3944 (void) CloneString(&windows->command.name,"Composite");
3945 windows->command.data=1;
3946 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
3947 (void) XMapRaised(display,windows->command.id);
3948 XClientMessage(display,windows->image.id,windows->im_protocols,
3949 windows->im_update_widget,CurrentTime);
3951 Track pointer until button 1 is pressed.
3953 XQueryPosition(display,windows->image.id,&x,&y);
3954 (void) XSelectInput(display,windows->image.id,
3955 windows->image.attributes.event_mask | PointerMotionMask);
3956 composite_info.x=windows->image.x+x;
3957 composite_info.y=windows->image.y+y;
3958 composite_info.width=0;
3959 composite_info.height=0;
3960 cursor=XCreateFontCursor(display,XC_ul_angle);
3961 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3966 if (windows->info.mapped != MagickFalse)
3969 Display pointer position.
3971 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
3972 (long) composite_info.x,(long) composite_info.y);
3973 XInfoWidget(display,windows,text);
3975 highlight_info=composite_info;
3976 highlight_info.x=composite_info.x-windows->image.x;
3977 highlight_info.y=composite_info.y-windows->image.y;
3978 XHighlightRectangle(display,windows->image.id,
3979 windows->image.highlight_context,&highlight_info);
3981 Wait for next event.
3983 XScreenEvent(display,windows,&event);
3984 XHighlightRectangle(display,windows->image.id,
3985 windows->image.highlight_context,&highlight_info);
3986 if (event.xany.window == windows->command.id)
3989 Select a command from the Command widget.
3991 id=XCommandWidget(display,windows,CompositeMenu,&event);
3994 switch (CompositeCommands[id])
3996 case CompositeOperatorsCommand:
3999 command[MaxTextExtent],
4003 Select a command from the pop-up menu.
4005 operators=GetMagickOptions(MagickComposeOptions);
4006 if (operators == (char **) NULL)
4008 entry=XMenuWidget(display,windows,CompositeMenu[id],
4009 (const char **) operators,command);
4011 compose=(CompositeOperator) ParseMagickOption(
4012 MagickComposeOptions,MagickFalse,operators[entry]);
4013 operators=DestroyStringList(operators);
4016 case CompositeDissolveCommand:
4019 factor[MaxTextExtent] = "20.0";
4022 Dissolve the two images a given percent.
4024 (void) XSetFunction(display,windows->image.highlight_context,
4026 (void) XDialogWidget(display,windows,"Dissolve",
4027 "Enter the blend factor (0.0 - 99.9%):",factor);
4028 (void) XSetFunction(display,windows->image.highlight_context,
4030 if (*factor == '\0')
4032 blend=StringToDouble(factor);
4033 compose=DissolveCompositeOp;
4036 case CompositeDisplaceCommand:
4039 Get horizontal and vertical scale displacement geometry.
4041 (void) XSetFunction(display,windows->image.highlight_context,
4043 (void) XDialogWidget(display,windows,"Displace",
4044 "Enter the horizontal and vertical scale:",displacement_geometry);
4045 (void) XSetFunction(display,windows->image.highlight_context,
4047 if (*displacement_geometry == '\0')
4049 compose=DisplaceCompositeOp;
4052 case CompositeHelpCommand:
4054 (void) XSetFunction(display,windows->image.highlight_context,
4056 XTextViewWidget(display,resource_info,windows,MagickFalse,
4057 "Help Viewer - Image Composite",ImageCompositeHelp);
4058 (void) XSetFunction(display,windows->image.highlight_context,
4062 case CompositeDismissCommand:
4080 if (image->debug != MagickFalse)
4081 (void) LogMagickEvent(X11Event,GetMagickModule(),
4082 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4083 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4084 if (event.xbutton.button != Button1)
4086 if (event.xbutton.window != windows->image.id)
4091 composite_info.width=composite_image->columns;
4092 composite_info.height=composite_image->rows;
4093 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4094 composite_info.x=windows->image.x+event.xbutton.x;
4095 composite_info.y=windows->image.y+event.xbutton.y;
4100 if (image->debug != MagickFalse)
4101 (void) LogMagickEvent(X11Event,GetMagickModule(),
4102 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4103 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4104 if (event.xbutton.button != Button1)
4106 if (event.xbutton.window != windows->image.id)
4108 if ((composite_info.width != 0) && (composite_info.height != 0))
4111 User has selected the location of the composite image.
4113 composite_info.x=windows->image.x+event.xbutton.x;
4114 composite_info.y=windows->image.y+event.xbutton.y;
4124 command[MaxTextExtent];
4132 if (event.xkey.window != windows->image.id)
4135 Respond to a user key press.
4137 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4138 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4139 *(command+length)='\0';
4140 if (image->debug != MagickFalse)
4141 (void) LogMagickEvent(X11Event,GetMagickModule(),
4142 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4143 switch ((int) key_symbol)
4151 composite_image=DestroyImage(composite_image);
4159 (void) XSetFunction(display,windows->image.highlight_context,
4161 XTextViewWidget(display,resource_info,windows,MagickFalse,
4162 "Help Viewer - Image Composite",ImageCompositeHelp);
4163 (void) XSetFunction(display,windows->image.highlight_context,
4169 (void) XBell(display,0);
4178 Map and unmap Info widget as text cursor crosses its boundaries.
4182 if (windows->info.mapped != MagickFalse)
4184 if ((x < (int) (windows->info.x+windows->info.width)) &&
4185 (y < (int) (windows->info.y+windows->info.height)))
4186 (void) XWithdrawWindow(display,windows->info.id,
4187 windows->info.screen);
4190 if ((x > (int) (windows->info.x+windows->info.width)) ||
4191 (y > (int) (windows->info.y+windows->info.height)))
4192 (void) XMapWindow(display,windows->info.id);
4193 composite_info.x=windows->image.x+x;
4194 composite_info.y=windows->image.y+y;
4199 if (image->debug != MagickFalse)
4200 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4205 } while ((state & ExitState) == 0);
4206 (void) XSelectInput(display,windows->image.id,
4207 windows->image.attributes.event_mask);
4208 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4209 XSetCursorState(display,windows,MagickFalse);
4210 (void) XFreeCursor(display,cursor);
4211 if ((state & EscapeState) != 0)
4214 Image compositing is relative to image configuration.
4216 XSetCursorState(display,windows,MagickTrue);
4217 XCheckRefreshWindows(display,windows);
4218 width=(unsigned int) image->columns;
4219 height=(unsigned int) image->rows;
4222 if (windows->image.crop_geometry != (char *) NULL)
4223 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4224 scale_factor=(MagickRealType) width/windows->image.ximage->width;
4225 composite_info.x+=x;
4226 composite_info.x=(int) (scale_factor*composite_info.x+0.5);
4227 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4228 scale_factor=(MagickRealType) height/windows->image.ximage->height;
4229 composite_info.y+=y;
4230 composite_info.y=(int) (scale_factor*composite_info.y+0.5);
4231 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4232 if ((composite_info.width != composite_image->columns) ||
4233 (composite_info.height != composite_image->rows))
4239 Scale composite image.
4241 resize_image=ResizeImage(composite_image,composite_info.width,
4242 composite_info.height,composite_image->filter,composite_image->blur,
4244 composite_image=DestroyImage(composite_image);
4245 if (resize_image == (Image *) NULL)
4247 XSetCursorState(display,windows,MagickFalse);
4248 return(MagickFalse);
4250 composite_image=resize_image;
4252 if (compose == DisplaceCompositeOp)
4253 (void) SetImageArtifact(composite_image,"compose:args",
4254 displacement_geometry);
4269 register PixelPacket
4273 Create mattes for blending.
4275 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel);
4276 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
4277 ((ssize_t) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
4278 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
4279 return(MagickFalse);
4280 image->matte=MagickTrue;
4281 exception=(&image->exception);
4282 for (y=0; y < (ssize_t) image->rows; y++)
4284 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
4285 if (q == (PixelPacket *) NULL)
4287 for (x=0; x < (int) image->columns; x++)
4292 if (SyncAuthenticPixels(image,exception) == MagickFalse)
4297 Composite image with X Image window.
4299 (void) CompositeImage(image,compose,composite_image,composite_info.x,
4301 composite_image=DestroyImage(composite_image);
4302 XSetCursorState(display,windows,MagickFalse);
4304 Update image configuration.
4306 XConfigureImageColormap(display,resource_info,windows,image);
4307 (void) XConfigureImage(display,resource_info,windows,image);
4312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4316 + X C o n f i g u r e I m a g e %
4320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4322 % XConfigureImage() creates a new X image. It also notifies the window
4323 % manager of the new image size and configures the transient widows.
4325 % The format of the XConfigureImage method is:
4327 % MagickBooleanType XConfigureImage(Display *display,
4328 % XResourceInfo *resource_info,XWindows *windows,Image *image)
4330 % A description of each parameter follows:
4332 % o display: Specifies a connection to an X server; returned from
4335 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4337 % o windows: Specifies a pointer to a XWindows structure.
4339 % o image: the image.
4343 static MagickBooleanType XConfigureImage(Display *display,
4344 XResourceInfo *resource_info,XWindows *windows,Image *image)
4347 geometry[MaxTextExtent];
4368 Dismiss if window dimensions are zero.
4370 width=(unsigned int) windows->image.window_changes.width;
4371 height=(unsigned int) windows->image.window_changes.height;
4372 if (image->debug != MagickFalse)
4373 (void) LogMagickEvent(X11Event,GetMagickModule(),
4374 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4375 windows->image.ximage->height,(double) width,(double) height);
4376 if ((width*height) == 0)
4381 Resize image to fit Image window dimensions.
4383 XSetCursorState(display,windows,MagickTrue);
4384 (void) XFlush(display);
4385 if (((int) width != windows->image.ximage->width) ||
4386 ((int) height != windows->image.ximage->height))
4387 image->taint=MagickTrue;
4388 windows->magnify.x=(int)
4389 width*windows->magnify.x/windows->image.ximage->width;
4390 windows->magnify.y=(int)
4391 height*windows->magnify.y/windows->image.ximage->height;
4392 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4393 windows->image.y=(int)
4394 (height*windows->image.y/windows->image.ximage->height);
4395 status=XMakeImage(display,resource_info,&windows->image,image,
4396 (unsigned int) width,(unsigned int) height);
4397 if (status == MagickFalse)
4398 XNoticeWidget(display,windows,"Unable to configure X image:",
4399 windows->image.name);
4401 Notify window manager of the new configuration.
4403 if (resource_info->image_geometry != (char *) NULL)
4404 (void) FormatMagickString(geometry,MaxTextExtent,"%s>!",
4405 resource_info->image_geometry);
4407 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4408 XDisplayWidth(display,windows->image.screen),
4409 XDisplayHeight(display,windows->image.screen));
4410 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4411 window_changes.width=(int) width;
4412 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4413 window_changes.width=XDisplayWidth(display,windows->image.screen);
4414 window_changes.height=(int) height;
4415 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4416 window_changes.height=XDisplayHeight(display,windows->image.screen);
4417 mask=(size_t) (CWWidth | CWHeight);
4418 if (resource_info->backdrop)
4421 window_changes.x=(int)
4422 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4423 window_changes.y=(int)
4424 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4426 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4427 (unsigned int) mask,&window_changes);
4428 (void) XClearWindow(display,windows->image.id);
4429 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4431 Update Magnify window configuration.
4433 if (windows->magnify.mapped != MagickFalse)
4434 XMakeMagnifyImage(display,windows);
4435 windows->pan.crop_geometry=windows->image.crop_geometry;
4436 XBestIconSize(display,&windows->pan,image);
4437 while (((windows->pan.width << 1) < MaxIconSize) &&
4438 ((windows->pan.height << 1) < MaxIconSize))
4440 windows->pan.width<<=1;
4441 windows->pan.height<<=1;
4443 if (windows->pan.geometry != (char *) NULL)
4444 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4445 &windows->pan.width,&windows->pan.height);
4446 window_changes.width=(int) windows->pan.width;
4447 window_changes.height=(int) windows->pan.height;
4448 size_hints=XAllocSizeHints();
4449 if (size_hints != (XSizeHints *) NULL)
4454 size_hints->flags=PSize | PMinSize | PMaxSize;
4455 size_hints->width=window_changes.width;
4456 size_hints->height=window_changes.height;
4457 size_hints->min_width=size_hints->width;
4458 size_hints->min_height=size_hints->height;
4459 size_hints->max_width=size_hints->width;
4460 size_hints->max_height=size_hints->height;
4461 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4462 (void) XFree((void *) size_hints);
4464 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4465 (unsigned int) (CWWidth | CWHeight),&window_changes);
4467 Update icon window configuration.
4469 windows->icon.crop_geometry=windows->image.crop_geometry;
4470 XBestIconSize(display,&windows->icon,image);
4471 window_changes.width=(int) windows->icon.width;
4472 window_changes.height=(int) windows->icon.height;
4473 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4474 (unsigned int) (CWWidth | CWHeight),&window_changes);
4475 XSetCursorState(display,windows,MagickFalse);
4476 return(status != 0 ? MagickTrue : MagickFalse);
4480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4484 + X C r o p I m a g e %
4488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4490 % XCropImage() allows the user to select a region of the image and crop, copy,
4491 % or cut it. For copy or cut, the image can subsequently be composited onto
4492 % the image with XPasteImage.
4494 % The format of the XCropImage method is:
4496 % MagickBooleanType XCropImage(Display *display,
4497 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4498 % const ClipboardMode mode)
4500 % A description of each parameter follows:
4502 % o display: Specifies a connection to an X server; returned from
4505 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4507 % o windows: Specifies a pointer to a XWindows structure.
4509 % o image: the image; returned from ReadImage.
4511 % o mode: This unsigned value specified whether the image should be
4512 % cropped, copied, or cut.
4515 static MagickBooleanType XCropImage(Display *display,
4516 XResourceInfo *resource_info,XWindows *windows,Image *image,
4517 const ClipboardMode mode)
4526 *RectifyModeMenu[] =
4534 static const ModeType
4544 RectifyDismissCommand
4548 command[MaxTextExtent],
4549 text[MaxTextExtent];
4575 register PixelPacket
4595 (void) CloneString(&windows->command.name,"Copy");
4600 (void) CloneString(&windows->command.name,"Crop");
4605 (void) CloneString(&windows->command.name,"Cut");
4609 RectifyModeMenu[0]=windows->command.name;
4610 windows->command.data=0;
4611 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4612 (void) XMapRaised(display,windows->command.id);
4613 XClientMessage(display,windows->image.id,windows->im_protocols,
4614 windows->im_update_widget,CurrentTime);
4616 Track pointer until button 1 is pressed.
4618 XQueryPosition(display,windows->image.id,&x,&y);
4619 (void) XSelectInput(display,windows->image.id,
4620 windows->image.attributes.event_mask | PointerMotionMask);
4621 crop_info.x=windows->image.x+x;
4622 crop_info.y=windows->image.y+y;
4625 cursor=XCreateFontCursor(display,XC_fleur);
4629 if (windows->info.mapped != MagickFalse)
4632 Display pointer position.
4634 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
4635 (long) crop_info.x,(long) crop_info.y);
4636 XInfoWidget(display,windows,text);
4639 Wait for next event.
4641 XScreenEvent(display,windows,&event);
4642 if (event.xany.window == windows->command.id)
4645 Select a command from the Command widget.
4647 id=XCommandWidget(display,windows,CropModeMenu,&event);
4650 switch (CropCommands[id])
4652 case CropHelpCommand:
4658 XTextViewWidget(display,resource_info,windows,MagickFalse,
4659 "Help Viewer - Image Copy",ImageCopyHelp);
4664 XTextViewWidget(display,resource_info,windows,MagickFalse,
4665 "Help Viewer - Image Crop",ImageCropHelp);
4670 XTextViewWidget(display,resource_info,windows,MagickFalse,
4671 "Help Viewer - Image Cut",ImageCutHelp);
4677 case CropDismissCommand:
4695 if (event.xbutton.button != Button1)
4697 if (event.xbutton.window != windows->image.id)
4700 Note first corner of cropping rectangle-- exit loop.
4702 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4703 crop_info.x=windows->image.x+event.xbutton.x;
4704 crop_info.y=windows->image.y+event.xbutton.y;
4714 if (event.xkey.window != windows->image.id)
4717 Respond to a user key press.
4719 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4720 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4721 switch ((int) key_symbol)
4740 XTextViewWidget(display,resource_info,windows,MagickFalse,
4741 "Help Viewer - Image Copy",ImageCopyHelp);
4746 XTextViewWidget(display,resource_info,windows,MagickFalse,
4747 "Help Viewer - Image Crop",ImageCropHelp);
4752 XTextViewWidget(display,resource_info,windows,MagickFalse,
4753 "Help Viewer - Image Cut",ImageCutHelp);
4761 (void) XBell(display,0);
4769 if (event.xmotion.window != windows->image.id)
4772 Map and unmap Info widget as text cursor crosses its boundaries.
4776 if (windows->info.mapped != MagickFalse)
4778 if ((x < (int) (windows->info.x+windows->info.width)) &&
4779 (y < (int) (windows->info.y+windows->info.height)))
4780 (void) XWithdrawWindow(display,windows->info.id,
4781 windows->info.screen);
4784 if ((x > (int) (windows->info.x+windows->info.width)) ||
4785 (y > (int) (windows->info.y+windows->info.height)))
4786 (void) XMapWindow(display,windows->info.id);
4787 crop_info.x=windows->image.x+x;
4788 crop_info.y=windows->image.y+y;
4794 } while ((state & ExitState) == 0);
4795 (void) XSelectInput(display,windows->image.id,
4796 windows->image.attributes.event_mask);
4797 if ((state & EscapeState) != 0)
4800 User want to exit without cropping.
4802 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4803 (void) XFreeCursor(display,cursor);
4806 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4810 Size rectangle as pointer moves until the mouse button is released.
4812 x=(int) crop_info.x;
4813 y=(int) crop_info.y;
4819 highlight_info=crop_info;
4820 highlight_info.x=crop_info.x-windows->image.x;
4821 highlight_info.y=crop_info.y-windows->image.y;
4822 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4825 Display info and draw cropping rectangle.
4827 if (windows->info.mapped == MagickFalse)
4828 (void) XMapWindow(display,windows->info.id);
4829 (void) FormatMagickString(text,MaxTextExtent,
4830 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4831 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4832 XInfoWidget(display,windows,text);
4833 XHighlightRectangle(display,windows->image.id,
4834 windows->image.highlight_context,&highlight_info);
4837 if (windows->info.mapped != MagickFalse)
4838 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4840 Wait for next event.
4842 XScreenEvent(display,windows,&event);
4843 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4844 XHighlightRectangle(display,windows->image.id,
4845 windows->image.highlight_context,&highlight_info);
4850 crop_info.x=windows->image.x+event.xbutton.x;
4851 crop_info.y=windows->image.y+event.xbutton.y;
4857 User has committed to cropping rectangle.
4859 crop_info.x=windows->image.x+event.xbutton.x;
4860 crop_info.y=windows->image.y+event.xbutton.y;
4861 XSetCursorState(display,windows,MagickFalse);
4863 windows->command.data=0;
4864 (void) XCommandWidget(display,windows,RectifyModeMenu,
4872 crop_info.x=windows->image.x+event.xmotion.x;
4873 crop_info.y=windows->image.y+event.xmotion.y;
4878 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4879 ((state & ExitState) != 0))
4882 Check boundary conditions.
4884 if (crop_info.x < 0)
4887 if (crop_info.x > (int) windows->image.ximage->width)
4888 crop_info.x=windows->image.ximage->width;
4889 if ((int) crop_info.x < x)
4890 crop_info.width=(unsigned int) (x-crop_info.x);
4893 crop_info.width=(unsigned int) (crop_info.x-x);
4896 if (crop_info.y < 0)
4899 if (crop_info.y > (int) windows->image.ximage->height)
4900 crop_info.y=windows->image.ximage->height;
4901 if ((int) crop_info.y < y)
4902 crop_info.height=(unsigned int) (y-crop_info.y);
4905 crop_info.height=(unsigned int) (crop_info.y-y);
4909 } while ((state & ExitState) == 0);
4911 Wait for user to grab a corner of the rectangle or press return.
4914 (void) XMapWindow(display,windows->info.id);
4917 if (windows->info.mapped != MagickFalse)
4920 Display pointer position.
4922 (void) FormatMagickString(text,MaxTextExtent,
4923 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4924 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4925 XInfoWidget(display,windows,text);
4927 highlight_info=crop_info;
4928 highlight_info.x=crop_info.x-windows->image.x;
4929 highlight_info.y=crop_info.y-windows->image.y;
4930 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
4936 XHighlightRectangle(display,windows->image.id,
4937 windows->image.highlight_context,&highlight_info);
4938 XScreenEvent(display,windows,&event);
4939 if (event.xany.window == windows->command.id)
4942 Select a command from the Command widget.
4944 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4945 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
4946 (void) XSetFunction(display,windows->image.highlight_context,
4948 XHighlightRectangle(display,windows->image.id,
4949 windows->image.highlight_context,&highlight_info);
4951 switch (RectifyCommands[id])
4953 case RectifyCopyCommand:
4958 case RectifyHelpCommand:
4960 (void) XSetFunction(display,windows->image.highlight_context,
4966 XTextViewWidget(display,resource_info,windows,MagickFalse,
4967 "Help Viewer - Image Copy",ImageCopyHelp);
4972 XTextViewWidget(display,resource_info,windows,MagickFalse,
4973 "Help Viewer - Image Crop",ImageCropHelp);
4978 XTextViewWidget(display,resource_info,windows,MagickFalse,
4979 "Help Viewer - Image Cut",ImageCutHelp);
4983 (void) XSetFunction(display,windows->image.highlight_context,
4987 case RectifyDismissCommand:
5001 XHighlightRectangle(display,windows->image.id,
5002 windows->image.highlight_context,&highlight_info);
5007 if (event.xbutton.button != Button1)
5009 if (event.xbutton.window != windows->image.id)
5011 x=windows->image.x+event.xbutton.x;
5012 y=windows->image.y+event.xbutton.y;
5013 if ((x < (int) (crop_info.x+RoiDelta)) &&
5014 (x > (int) (crop_info.x-RoiDelta)) &&
5015 (y < (int) (crop_info.y+RoiDelta)) &&
5016 (y > (int) (crop_info.y-RoiDelta)))
5018 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5019 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5020 state|=UpdateConfigurationState;
5023 if ((x < (int) (crop_info.x+RoiDelta)) &&
5024 (x > (int) (crop_info.x-RoiDelta)) &&
5025 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5026 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5028 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5029 state|=UpdateConfigurationState;
5032 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5033 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5034 (y < (int) (crop_info.y+RoiDelta)) &&
5035 (y > (int) (crop_info.y-RoiDelta)))
5037 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5038 state|=UpdateConfigurationState;
5041 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5042 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5043 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5044 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5046 state|=UpdateConfigurationState;
5052 if (event.xbutton.window == windows->pan.id)
5053 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5054 (highlight_info.y != crop_info.y-windows->image.y))
5055 XHighlightRectangle(display,windows->image.id,
5056 windows->image.highlight_context,&highlight_info);
5057 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5058 event.xbutton.time);
5063 if (event.xexpose.window == windows->image.id)
5064 if (event.xexpose.count == 0)
5066 event.xexpose.x=(int) highlight_info.x;
5067 event.xexpose.y=(int) highlight_info.y;
5068 event.xexpose.width=(int) highlight_info.width;
5069 event.xexpose.height=(int) highlight_info.height;
5070 XRefreshWindow(display,&windows->image,&event);
5072 if (event.xexpose.window == windows->info.id)
5073 if (event.xexpose.count == 0)
5074 XInfoWidget(display,windows,text);
5079 if (event.xkey.window != windows->image.id)
5082 Respond to a user key press.
5084 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5085 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5086 switch ((int) key_symbol)
5099 crop_info.x=(ssize_t) (windows->image.width/2L-crop_info.width/2L);
5100 crop_info.y=(ssize_t) (windows->image.height/2L-crop_info.height/2L);
5132 (void) XSetFunction(display,windows->image.highlight_context,
5138 XTextViewWidget(display,resource_info,windows,MagickFalse,
5139 "Help Viewer - Image Copy",ImageCopyHelp);
5144 XTextViewWidget(display,resource_info,windows,MagickFalse,
5145 "Help Viewer - Image Cropg",ImageCropHelp);
5150 XTextViewWidget(display,resource_info,windows,MagickFalse,
5151 "Help Viewer - Image Cutg",ImageCutHelp);
5155 (void) XSetFunction(display,windows->image.highlight_context,
5161 (void) XBell(display,0);
5165 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5173 if (event.xmotion.window != windows->image.id)
5176 Map and unmap Info widget as text cursor crosses its boundaries.
5180 if (windows->info.mapped != MagickFalse)
5182 if ((x < (int) (windows->info.x+windows->info.width)) &&
5183 (y < (int) (windows->info.y+windows->info.height)))
5184 (void) XWithdrawWindow(display,windows->info.id,
5185 windows->info.screen);
5188 if ((x > (int) (windows->info.x+windows->info.width)) ||
5189 (y > (int) (windows->info.y+windows->info.height)))
5190 (void) XMapWindow(display,windows->info.id);
5191 crop_info.x=windows->image.x+event.xmotion.x;
5192 crop_info.y=windows->image.y+event.xmotion.y;
5195 case SelectionRequest:
5200 XSelectionRequestEvent
5204 Set primary selection.
5206 (void) FormatMagickString(text,MaxTextExtent,
5207 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5208 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5209 request=(&(event.xselectionrequest));
5210 (void) XChangeProperty(request->display,request->requestor,
5211 request->property,request->target,8,PropModeReplace,
5212 (unsigned char *) text,(int) strlen(text));
5213 notify.type=SelectionNotify;
5214 notify.display=request->display;
5215 notify.requestor=request->requestor;
5216 notify.selection=request->selection;
5217 notify.target=request->target;
5218 notify.time=request->time;
5219 if (request->property == None)
5220 notify.property=request->target;
5222 notify.property=request->property;
5223 (void) XSendEvent(request->display,request->requestor,False,0,
5224 (XEvent *) ¬ify);
5229 if ((state & UpdateConfigurationState) != 0)
5231 (void) XPutBackEvent(display,&event);
5232 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5235 } while ((state & ExitState) == 0);
5236 } while ((state & ExitState) == 0);
5237 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5238 XSetCursorState(display,windows,MagickFalse);
5239 if ((state & EscapeState) != 0)
5241 if (mode == CropMode)
5242 if (((int) crop_info.width != windows->image.ximage->width) ||
5243 ((int) crop_info.height != windows->image.ximage->height))
5246 Reconfigure Image window as defined by cropping rectangle.
5248 XSetCropGeometry(display,windows,&crop_info,image);
5249 windows->image.window_changes.width=(int) crop_info.width;
5250 windows->image.window_changes.height=(int) crop_info.height;
5251 (void) XConfigureImage(display,resource_info,windows,image);
5255 Copy image before applying image transforms.
5257 XSetCursorState(display,windows,MagickTrue);
5258 XCheckRefreshWindows(display,windows);
5259 width=(unsigned int) image->columns;
5260 height=(unsigned int) image->rows;
5263 if (windows->image.crop_geometry != (char *) NULL)
5264 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5265 scale_factor=(MagickRealType) width/windows->image.ximage->width;
5267 crop_info.x=(int) (scale_factor*crop_info.x+0.5);
5268 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5269 scale_factor=(MagickRealType) height/windows->image.ximage->height;
5271 crop_info.y=(int) (scale_factor*crop_info.y+0.5);
5272 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5273 crop_image=CropImage(image,&crop_info,&image->exception);
5274 XSetCursorState(display,windows,MagickFalse);
5275 if (crop_image == (Image *) NULL)
5276 return(MagickFalse);
5277 if (resource_info->copy_image != (Image *) NULL)
5278 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5279 resource_info->copy_image=crop_image;
5280 if (mode == CopyMode)
5282 (void) XConfigureImage(display,resource_info,windows,image);
5288 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
5289 return(MagickFalse);
5290 image->matte=MagickTrue;
5291 exception=(&image->exception);
5292 for (y=0; y < (ssize_t) crop_info.height; y++)
5294 q=GetAuthenticPixels(image,crop_info.x,y+crop_info.y,crop_info.width,1,
5296 if (q == (PixelPacket *) NULL)
5298 for (x=0; x < (int) crop_info.width; x++)
5300 q->opacity=(Quantum) TransparentOpacity;
5303 if (SyncAuthenticPixels(image,exception) == MagickFalse)
5307 Update image configuration.
5309 XConfigureImageColormap(display,resource_info,windows,image);
5310 (void) XConfigureImage(display,resource_info,windows,image);
5315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5319 + X D r a w I m a g e %
5323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5325 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5328 % The format of the XDrawEditImage method is:
5330 % MagickBooleanType XDrawEditImage(Display *display,
5331 % XResourceInfo *resource_info,XWindows *windows,Image **image)
5333 % A description of each parameter follows:
5335 % o display: Specifies a connection to an X server; returned from
5338 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5340 % o windows: Specifies a pointer to a XWindows structure.
5342 % o image: the image.
5345 static MagickBooleanType XDrawEditImage(Display *display,
5346 XResourceInfo *resource_info,XWindows *windows,Image **image)
5362 element = PointElement;
5364 static const ModeType
5377 stipple = (Pixmap) NULL;
5384 command[MaxTextExtent],
5385 text[MaxTextExtent];
5434 Allocate polygon info.
5436 max_coordinates=2048;
5437 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5438 sizeof(*coordinate_info));
5439 if (coordinate_info == (XPoint *) NULL)
5441 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
5442 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5443 return(MagickFalse);
5448 (void) CloneString(&windows->command.name,"Draw");
5449 windows->command.data=4;
5450 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5451 (void) XMapRaised(display,windows->command.id);
5452 XClientMessage(display,windows->image.id,windows->im_protocols,
5453 windows->im_update_widget,CurrentTime);
5455 Wait for first button press.
5457 root_window=XRootWindow(display,XDefaultScreen(display));
5458 draw_info.stencil=OpaqueStencil;
5460 cursor=XCreateFontCursor(display,XC_tcross);
5463 XQueryPosition(display,windows->image.id,&x,&y);
5464 (void) XSelectInput(display,windows->image.id,
5465 windows->image.attributes.event_mask | PointerMotionMask);
5466 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5470 if (windows->info.mapped != MagickFalse)
5473 Display pointer position.
5475 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
5476 x+windows->image.x,y+windows->image.y);
5477 XInfoWidget(display,windows,text);
5480 Wait for next event.
5482 XScreenEvent(display,windows,&event);
5483 if (event.xany.window == windows->command.id)
5486 Select a command from the Command widget.
5488 id=XCommandWidget(display,windows,DrawMenu,&event);
5491 switch (DrawCommands[id])
5493 case DrawElementCommand:
5512 Select a command from the pop-up menu.
5514 element=(ElementType) (XMenuWidget(display,windows,
5515 DrawMenu[id],Elements,command)+1);
5518 case DrawColorCommand:
5521 *ColorMenu[MaxNumberPens+1];
5533 Initialize menu selections.
5535 for (i=0; i < (int) (MaxNumberPens-2); i++)
5536 ColorMenu[i]=resource_info->pen_colors[i];
5537 ColorMenu[MaxNumberPens-2]="transparent";
5538 ColorMenu[MaxNumberPens-1]="Browser...";
5539 ColorMenu[MaxNumberPens]=(char *) NULL;
5541 Select a pen color from the pop-up menu.
5543 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5544 (const char **) ColorMenu,command);
5547 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5549 if (transparent != MagickFalse)
5551 draw_info.stencil=TransparentStencil;
5554 if (pen_number == (MaxNumberPens-1))
5557 color_name[MaxTextExtent] = "gray";
5560 Select a pen color from a dialog.
5562 resource_info->pen_colors[pen_number]=color_name;
5563 XColorBrowserWidget(display,windows,"Select",color_name);
5564 if (*color_name == '\0')
5570 (void) XParseColor(display,windows->map_info->colormap,
5571 resource_info->pen_colors[pen_number],&color);
5572 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5573 (unsigned int) MaxColors,&color);
5574 windows->pixel_info->pen_colors[pen_number]=color;
5575 pen_id=(unsigned int) pen_number;
5576 draw_info.stencil=OpaqueStencil;
5579 case DrawStippleCommand:
5591 filename[MaxTextExtent] = "\0";
5608 Select a command from the pop-up menu.
5610 StipplesMenu[7]="Open...";
5611 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5615 if (stipple != (Pixmap) NULL)
5616 (void) XFreePixmap(display,stipple);
5617 stipple=(Pixmap) NULL;
5626 stipple=XCreateBitmapFromData(display,root_window,
5627 (char *) BricksBitmap,BricksWidth,BricksHeight);
5632 stipple=XCreateBitmapFromData(display,root_window,
5633 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5638 stipple=XCreateBitmapFromData(display,root_window,
5639 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5644 stipple=XCreateBitmapFromData(display,root_window,
5645 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5650 stipple=XCreateBitmapFromData(display,root_window,
5651 (char *) WavyBitmap,WavyWidth,WavyHeight);
5657 stipple=XCreateBitmapFromData(display,root_window,
5658 (char *) HighlightBitmap,HighlightWidth,
5665 XFileBrowserWidget(display,windows,"Stipple",filename);
5666 if (*filename == '\0')
5671 XSetCursorState(display,windows,MagickTrue);
5672 XCheckRefreshWindows(display,windows);
5673 image_info=AcquireImageInfo();
5674 (void) CopyMagickString(image_info->filename,filename,
5676 stipple_image=ReadImage(image_info,&(*image)->exception);
5677 CatchException(&(*image)->exception);
5678 XSetCursorState(display,windows,MagickFalse);
5679 if (stipple_image == (Image *) NULL)
5681 (void) AcquireUniqueFileResource(filename);
5682 (void) FormatMagickString(stipple_image->filename,MaxTextExtent,
5684 (void) WriteImage(image_info,stipple_image);
5685 stipple_image=DestroyImage(stipple_image);
5686 image_info=DestroyImageInfo(image_info);
5687 status=XReadBitmapFile(display,root_window,filename,&width,
5688 &height,&stipple,&x,&y);
5689 (void) RelinquishUniqueFileResource(filename);
5690 if ((status != BitmapSuccess) != 0)
5691 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5695 case DrawWidthCommand:
5698 width[MaxTextExtent] = "0";
5713 Select a command from the pop-up menu.
5715 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5721 line_width=(unsigned int) StringToUnsignedLong(WidthsMenu[entry]);
5724 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5728 line_width=(unsigned int) StringToUnsignedLong(width);
5731 case DrawUndoCommand:
5733 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5737 case DrawHelpCommand:
5739 XTextViewWidget(display,resource_info,windows,MagickFalse,
5740 "Help Viewer - Image Rotation",ImageDrawHelp);
5741 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5744 case DrawDismissCommand:
5756 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5763 if (event.xbutton.button != Button1)
5765 if (event.xbutton.window != windows->image.id)
5784 if (event.xkey.window != windows->image.id)
5787 Respond to a user key press.
5789 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5790 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5791 switch ((int) key_symbol)
5806 XTextViewWidget(display,resource_info,windows,MagickFalse,
5807 "Help Viewer - Image Rotation",ImageDrawHelp);
5812 (void) XBell(display,0);
5821 Map and unmap Info widget as text cursor crosses its boundaries.
5825 if (windows->info.mapped != MagickFalse)
5827 if ((x < (int) (windows->info.x+windows->info.width)) &&
5828 (y < (int) (windows->info.y+windows->info.height)))
5829 (void) XWithdrawWindow(display,windows->info.id,
5830 windows->info.screen);
5833 if ((x > (int) (windows->info.x+windows->info.width)) ||
5834 (y > (int) (windows->info.y+windows->info.height)))
5835 (void) XMapWindow(display,windows->info.id);
5839 } while ((state & ExitState) == 0);
5840 (void) XSelectInput(display,windows->image.id,
5841 windows->image.attributes.event_mask);
5842 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5843 if ((state & EscapeState) != 0)
5846 Draw element as pointer moves until the button is released.
5856 rectangle_info.width=0;
5857 rectangle_info.height=0;
5858 number_coordinates=1;
5859 coordinate_info->x=x;
5860 coordinate_info->y=y;
5861 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5870 if (number_coordinates > 1)
5872 (void) XDrawLines(display,windows->image.id,
5873 windows->image.highlight_context,coordinate_info,
5874 number_coordinates,CoordModeOrigin);
5875 (void) FormatMagickString(text,MaxTextExtent," %+d%+d",
5876 coordinate_info[number_coordinates-1].x,
5877 coordinate_info[number_coordinates-1].y);
5878 XInfoWidget(display,windows,text);
5887 Display angle of the line.
5889 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5890 line_info.y1),(double) (line_info.x2-line_info.x1)));
5891 (void) FormatMagickString(text,MaxTextExtent," %g",
5893 XInfoWidget(display,windows,text);
5894 XHighlightLine(display,windows->image.id,
5895 windows->image.highlight_context,&line_info);
5898 if (windows->info.mapped != MagickFalse)
5899 (void) XWithdrawWindow(display,windows->info.id,
5900 windows->info.screen);
5903 case RectangleElement:
5904 case FillRectangleElement:
5906 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5909 Display info and draw drawing rectangle.
5911 (void) FormatMagickString(text,MaxTextExtent,
5912 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5913 (double) rectangle_info.height,(double) rectangle_info.x,
5914 (double) rectangle_info.y);
5915 XInfoWidget(display,windows,text);
5916 XHighlightRectangle(display,windows->image.id,
5917 windows->image.highlight_context,&rectangle_info);
5920 if (windows->info.mapped != MagickFalse)
5921 (void) XWithdrawWindow(display,windows->info.id,
5922 windows->info.screen);
5926 case FillCircleElement:
5927 case EllipseElement:
5928 case FillEllipseElement:
5930 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5933 Display info and draw drawing rectangle.
5935 (void) FormatMagickString(text,MaxTextExtent,
5936 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5937 (double) rectangle_info.height,(double) rectangle_info.x,
5938 (double) rectangle_info.y);
5939 XInfoWidget(display,windows,text);
5940 XHighlightEllipse(display,windows->image.id,
5941 windows->image.highlight_context,&rectangle_info);
5944 if (windows->info.mapped != MagickFalse)
5945 (void) XWithdrawWindow(display,windows->info.id,
5946 windows->info.screen);
5949 case PolygonElement:
5950 case FillPolygonElement:
5952 if (number_coordinates > 1)
5953 (void) XDrawLines(display,windows->image.id,
5954 windows->image.highlight_context,coordinate_info,
5955 number_coordinates,CoordModeOrigin);
5959 Display angle of the line.
5961 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5962 line_info.y1),(double) (line_info.x2-line_info.x1)));
5963 (void) FormatMagickString(text,MaxTextExtent," %g",
5965 XInfoWidget(display,windows,text);
5966 XHighlightLine(display,windows->image.id,
5967 windows->image.highlight_context,&line_info);
5970 if (windows->info.mapped != MagickFalse)
5971 (void) XWithdrawWindow(display,windows->info.id,
5972 windows->info.screen);
5977 Wait for next event.
5979 XScreenEvent(display,windows,&event);
5985 if (number_coordinates > 1)
5986 (void) XDrawLines(display,windows->image.id,
5987 windows->image.highlight_context,coordinate_info,
5988 number_coordinates,CoordModeOrigin);
5994 XHighlightLine(display,windows->image.id,
5995 windows->image.highlight_context,&line_info);
5998 case RectangleElement:
5999 case FillRectangleElement:
6001 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6002 XHighlightRectangle(display,windows->image.id,
6003 windows->image.highlight_context,&rectangle_info);
6007 case FillCircleElement:
6008 case EllipseElement:
6009 case FillEllipseElement:
6011 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6012 XHighlightEllipse(display,windows->image.id,
6013 windows->image.highlight_context,&rectangle_info);
6016 case PolygonElement:
6017 case FillPolygonElement:
6019 if (number_coordinates > 1)
6020 (void) XDrawLines(display,windows->image.id,
6021 windows->image.highlight_context,coordinate_info,
6022 number_coordinates,CoordModeOrigin);
6024 XHighlightLine(display,windows->image.id,
6025 windows->image.highlight_context,&line_info);
6036 User has committed to element.
6038 line_info.x2=event.xbutton.x;
6039 line_info.y2=event.xbutton.y;
6040 rectangle_info.x=event.xbutton.x;
6041 rectangle_info.y=event.xbutton.y;
6042 coordinate_info[number_coordinates].x=event.xbutton.x;
6043 coordinate_info[number_coordinates].y=event.xbutton.y;
6044 if (((element != PolygonElement) &&
6045 (element != FillPolygonElement)) || (distance <= 9))
6050 number_coordinates++;
6051 if (number_coordinates < (int) max_coordinates)
6053 line_info.x1=event.xbutton.x;
6054 line_info.y1=event.xbutton.y;
6057 max_coordinates<<=1;
6058 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6059 max_coordinates,sizeof(*coordinate_info));
6060 if (coordinate_info == (XPoint *) NULL)
6061 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
6062 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6069 if (event.xmotion.window != windows->image.id)
6071 if (element != PointElement)
6073 line_info.x2=event.xmotion.x;
6074 line_info.y2=event.xmotion.y;
6075 rectangle_info.x=event.xmotion.x;
6076 rectangle_info.y=event.xmotion.y;
6079 coordinate_info[number_coordinates].x=event.xbutton.x;
6080 coordinate_info[number_coordinates].y=event.xbutton.y;
6081 number_coordinates++;
6082 if (number_coordinates < (int) max_coordinates)
6084 max_coordinates<<=1;
6085 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6086 max_coordinates,sizeof(*coordinate_info));
6087 if (coordinate_info == (XPoint *) NULL)
6088 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
6089 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6096 Check boundary conditions.
6098 if (line_info.x2 < 0)
6101 if (line_info.x2 > (int) windows->image.width)
6102 line_info.x2=(short) windows->image.width;
6103 if (line_info.y2 < 0)
6106 if (line_info.y2 > (int) windows->image.height)
6107 line_info.y2=(short) windows->image.height;
6108 distance=(unsigned int)
6109 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6110 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6111 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6112 ((state & ExitState) != 0))
6114 if (rectangle_info.x < 0)
6117 if (rectangle_info.x > (int) windows->image.width)
6118 rectangle_info.x=(ssize_t) windows->image.width;
6119 if ((int) rectangle_info.x < x)
6120 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6123 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6126 if (rectangle_info.y < 0)
6129 if (rectangle_info.y > (int) windows->image.height)
6130 rectangle_info.y=(ssize_t) windows->image.height;
6131 if ((int) rectangle_info.y < y)
6132 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6135 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6139 } while ((state & ExitState) == 0);
6140 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6141 if ((element == PointElement) || (element == PolygonElement) ||
6142 (element == FillPolygonElement))
6145 Determine polygon bounding box.
6147 rectangle_info.x=coordinate_info->x;
6148 rectangle_info.y=coordinate_info->y;
6149 x=coordinate_info->x;
6150 y=coordinate_info->y;
6151 for (i=1; i < number_coordinates; i++)
6153 if (coordinate_info[i].x > x)
6154 x=coordinate_info[i].x;
6155 if (coordinate_info[i].y > y)
6156 y=coordinate_info[i].y;
6157 if (coordinate_info[i].x < rectangle_info.x)
6158 rectangle_info.x=MagickMax(coordinate_info[i].x,0);
6159 if (coordinate_info[i].y < rectangle_info.y)
6160 rectangle_info.y=MagickMax(coordinate_info[i].y,0);
6162 rectangle_info.width=(size_t) (x-rectangle_info.x);
6163 rectangle_info.height=(size_t) (y-rectangle_info.y);
6164 for (i=0; i < number_coordinates; i++)
6166 coordinate_info[i].x-=rectangle_info.x;
6167 coordinate_info[i].y-=rectangle_info.y;
6174 if ((element == RectangleElement) ||
6175 (element == CircleElement) || (element == EllipseElement))
6177 rectangle_info.width--;
6178 rectangle_info.height--;
6181 Drawing is relative to image configuration.
6183 draw_info.x=(int) rectangle_info.x;
6184 draw_info.y=(int) rectangle_info.y;
6185 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6187 width=(unsigned int) (*image)->columns;
6188 height=(unsigned int) (*image)->rows;
6191 if (windows->image.crop_geometry != (char *) NULL)
6192 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6193 draw_info.x+=windows->image.x-(line_width/2);
6194 if (draw_info.x < 0)
6196 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6197 draw_info.y+=windows->image.y-(line_width/2);
6198 if (draw_info.y < 0)
6200 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6201 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6202 if (draw_info.width > (unsigned int) (*image)->columns)
6203 draw_info.width=(unsigned int) (*image)->columns;
6204 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6205 if (draw_info.height > (unsigned int) (*image)->rows)
6206 draw_info.height=(unsigned int) (*image)->rows;
6207 (void) FormatMagickString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6208 width*draw_info.width/windows->image.ximage->width,
6209 height*draw_info.height/windows->image.ximage->height,
6210 draw_info.x+x,draw_info.y+y);
6212 Initialize drawing attributes.
6214 draw_info.degrees=0.0;
6215 draw_info.element=element;
6216 draw_info.stipple=stipple;
6217 draw_info.line_width=line_width;
6218 draw_info.line_info=line_info;
6219 if (line_info.x1 > (int) (line_width/2))
6220 draw_info.line_info.x1=(short) line_width/2;
6221 if (line_info.y1 > (int) (line_width/2))
6222 draw_info.line_info.y1=(short) line_width/2;
6223 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6224 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6225 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6227 draw_info.line_info.x2=(-draw_info.line_info.x2);
6228 draw_info.line_info.y2=(-draw_info.line_info.y2);
6230 if (draw_info.line_info.x2 < 0)
6232 draw_info.line_info.x2=(-draw_info.line_info.x2);
6233 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6235 if (draw_info.line_info.y2 < 0)
6237 draw_info.line_info.y2=(-draw_info.line_info.y2);
6238 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6240 draw_info.rectangle_info=rectangle_info;
6241 if (draw_info.rectangle_info.x > (int) (line_width/2))
6242 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6243 if (draw_info.rectangle_info.y > (int) (line_width/2))
6244 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6245 draw_info.number_coordinates=(unsigned int) number_coordinates;
6246 draw_info.coordinate_info=coordinate_info;
6247 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6249 Draw element on image.
6251 XSetCursorState(display,windows,MagickTrue);
6252 XCheckRefreshWindows(display,windows);
6253 status=XDrawImage(display,windows->pixel_info,&draw_info,*image);
6254 XSetCursorState(display,windows,MagickFalse);
6256 Update image colormap and return to image drawing.
6258 XConfigureImageColormap(display,resource_info,windows,*image);
6259 (void) XConfigureImage(display,resource_info,windows,*image);
6261 XSetCursorState(display,windows,MagickFalse);
6262 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6263 return(status != 0 ? MagickTrue : MagickFalse);
6267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6271 + X D r a w P a n R e c t a n g l e %
6275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6277 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6278 % displays a zoom image and the rectangle shows which portion of the image is
6279 % displayed in the Image window.
6281 % The format of the XDrawPanRectangle method is:
6283 % XDrawPanRectangle(Display *display,XWindows *windows)
6285 % A description of each parameter follows:
6287 % o display: Specifies a connection to an X server; returned from
6290 % o windows: Specifies a pointer to a XWindows structure.
6293 static void XDrawPanRectangle(Display *display,XWindows *windows)
6302 Determine dimensions of the panning rectangle.
6304 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
6305 highlight_info.x=(int) (scale_factor*windows->image.x+0.5);
6306 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6307 scale_factor=(MagickRealType)
6308 windows->pan.height/windows->image.ximage->height;
6309 highlight_info.y=(int) (scale_factor*windows->image.y+0.5);
6310 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6312 Display the panning rectangle.
6314 (void) XClearWindow(display,windows->pan.id);
6315 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6324 + X I m a g e C a c h e %
6328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6330 % XImageCache() handles the creation, manipulation, and destruction of the
6331 % image cache (undo and redo buffers).
6333 % The format of the XImageCache method is:
6335 % void XImageCache(Display *display,XResourceInfo *resource_info,
6336 % XWindows *windows,const CommandType command,Image **image)
6338 % A description of each parameter follows:
6340 % o display: Specifies a connection to an X server; returned from
6343 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6345 % o windows: Specifies a pointer to a XWindows structure.
6347 % o command: Specifies a command to perform.
6349 % o image: the image; XImageCache
6350 % may transform the image and return a new image pointer.
6353 static void XImageCache(Display *display,XResourceInfo *resource_info,
6354 XWindows *windows,const CommandType command,Image **image)
6360 *redo_image = (Image *) NULL,
6361 *undo_image = (Image *) NULL;
6365 case FreeBuffersCommand:
6368 Free memory from the undo and redo cache.
6370 while (undo_image != (Image *) NULL)
6372 cache_image=undo_image;
6373 undo_image=GetPreviousImageInList(undo_image);
6374 cache_image->list=DestroyImage(cache_image->list);
6375 cache_image=DestroyImage(cache_image);
6377 undo_image=NewImageList();
6378 if (redo_image != (Image *) NULL)
6379 redo_image=DestroyImage(redo_image);
6380 redo_image=NewImageList();
6386 Undo the last image transformation.
6388 if (undo_image == (Image *) NULL)
6390 (void) XBell(display,0);
6393 cache_image=undo_image;
6394 undo_image=GetPreviousImageInList(undo_image);
6395 windows->image.window_changes.width=(int) cache_image->columns;
6396 windows->image.window_changes.height=(int) cache_image->rows;
6397 if (windows->image.crop_geometry != (char *) NULL)
6398 windows->image.crop_geometry=(char *)
6399 RelinquishMagickMemory(windows->image.crop_geometry);
6400 windows->image.crop_geometry=cache_image->geometry;
6401 if (redo_image != (Image *) NULL)
6402 redo_image=DestroyImage(redo_image);
6403 redo_image=(*image);
6404 *image=cache_image->list;
6405 cache_image=DestroyImage(cache_image);
6406 if (windows->image.orphan != MagickFalse)
6408 XConfigureImageColormap(display,resource_info,windows,*image);
6409 (void) XConfigureImage(display,resource_info,windows,*image);
6415 case HalfSizeCommand:
6416 case OriginalSizeCommand:
6417 case DoubleSizeCommand:
6424 case RotateRightCommand:
6425 case RotateLeftCommand:
6430 case ContrastStretchCommand:
6431 case SigmoidalContrastCommand:
6432 case NormalizeCommand:
6433 case EqualizeCommand:
6435 case SaturationCommand:
6436 case BrightnessCommand:
6440 case GrayscaleCommand:
6442 case QuantizeCommand:
6443 case DespeckleCommand:
6445 case ReduceNoiseCommand:
6446 case AddNoiseCommand:
6447 case SharpenCommand:
6449 case ThresholdCommand:
6450 case EdgeDetectCommand:
6454 case SegmentCommand:
6455 case SolarizeCommand:
6456 case SepiaToneCommand:
6458 case ImplodeCommand:
6459 case VignetteCommand:
6461 case OilPaintCommand:
6462 case CharcoalDrawCommand:
6463 case AnnotateCommand:
6464 case AddBorderCommand:
6465 case AddFrameCommand:
6466 case CompositeCommand:
6467 case CommentCommand:
6469 case RegionofInterestCommand:
6470 case SaveToUndoBufferCommand:
6479 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelPacket));
6480 if (undo_image != (Image *) NULL)
6483 Ensure the undo stash.has enough memory available.
6485 previous_image=undo_image;
6486 while (previous_image != (Image *) NULL)
6488 bytes+=previous_image->list->columns*previous_image->list->rows*
6489 sizeof(PixelPacket);
6490 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6492 previous_image=GetPreviousImageInList(previous_image);
6495 bytes-=previous_image->list->columns*previous_image->list->rows*
6496 sizeof(PixelPacket);
6497 if (previous_image == undo_image)
6498 undo_image=NewImageList();
6500 previous_image->next->previous=NewImageList();
6503 while (previous_image != (Image *) NULL)
6506 Delete any excess memory from undo cache.
6508 cache_image=previous_image;
6509 previous_image=GetPreviousImageInList(previous_image);
6510 cache_image->list=DestroyImage(cache_image->list);
6511 cache_image=DestroyImage(cache_image);
6514 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6517 Save image before transformations are applied.
6519 cache_image=AcquireImage((ImageInfo *) NULL);
6520 if (cache_image == (Image *) NULL)
6522 XSetCursorState(display,windows,MagickTrue);
6523 XCheckRefreshWindows(display,windows);
6524 cache_image->list=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
6525 XSetCursorState(display,windows,MagickFalse);
6526 if (cache_image->list == (Image *) NULL)
6528 cache_image=DestroyImage(cache_image);
6531 cache_image->columns=(size_t) windows->image.ximage->width;
6532 cache_image->rows=(size_t) windows->image.ximage->height;
6533 cache_image->geometry=windows->image.crop_geometry;
6534 if (windows->image.crop_geometry != (char *) NULL)
6536 cache_image->geometry=AcquireString((char *) NULL);
6537 (void) CopyMagickString(cache_image->geometry,
6538 windows->image.crop_geometry,MaxTextExtent);
6540 if (undo_image == (Image *) NULL)
6542 undo_image=cache_image;
6545 undo_image->next=cache_image;
6546 undo_image->next->previous=undo_image;
6547 undo_image=undo_image->next;
6553 if (command == RedoCommand)
6556 Redo the last image transformation.
6558 if (redo_image == (Image *) NULL)
6560 (void) XBell(display,0);
6563 windows->image.window_changes.width=(int) redo_image->columns;
6564 windows->image.window_changes.height=(int) redo_image->rows;
6565 if (windows->image.crop_geometry != (char *) NULL)
6566 windows->image.crop_geometry=(char *)
6567 RelinquishMagickMemory(windows->image.crop_geometry);
6568 windows->image.crop_geometry=redo_image->geometry;
6569 *image=DestroyImage(*image);
6571 redo_image=NewImageList();
6572 if (windows->image.orphan != MagickFalse)
6574 XConfigureImageColormap(display,resource_info,windows,*image);
6575 (void) XConfigureImage(display,resource_info,windows,*image);
6578 if (command != InfoCommand)
6583 XSetCursorState(display,windows,MagickTrue);
6584 XCheckRefreshWindows(display,windows);
6585 XDisplayImageInfo(display,resource_info,windows,undo_image,*image);
6586 XSetCursorState(display,windows,MagickFalse);
6590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6594 + X I m a g e W i n d o w C o m m a n d %
6598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6600 % XImageWindowCommand() makes a transform to the image or Image window as
6601 % specified by a user menu button or keyboard command.
6603 % The format of the XMagickCommand method is:
6605 % CommandType XImageWindowCommand(Display *display,
6606 % XResourceInfo *resource_info,XWindows *windows,
6607 % const MagickStatusType state,KeySym key_symbol,Image **image)
6609 % A description of each parameter follows:
6611 % o nexus: Method XImageWindowCommand returns an image when the
6612 % user chooses 'Open Image' from the command menu. Otherwise a null
6613 % image is returned.
6615 % o display: Specifies a connection to an X server; returned from
6618 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6620 % o windows: Specifies a pointer to a XWindows structure.
6622 % o state: key mask.
6624 % o key_symbol: Specifies a command to perform.
6626 % o image: the image; XImageWIndowCommand
6627 % may transform the image and return a new image pointer.
6630 static CommandType XImageWindowCommand(Display *display,
6631 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6632 KeySym key_symbol,Image **image)
6635 delta[MaxTextExtent] = "";
6638 Digits[] = "01234567890";
6643 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6645 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6648 resource_info->quantum=1;
6650 last_symbol=key_symbol;
6651 delta[strlen(delta)+1]='\0';
6652 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6653 resource_info->quantum=StringToLong(delta);
6654 return(NullCommand);
6656 last_symbol=key_symbol;
6657 if (resource_info->immutable)
6660 Virtual image window has a restricted command set.
6665 return(InfoCommand);
6668 return(PrintCommand);
6670 return(NextCommand);
6673 return(QuitCommand);
6677 return(NullCommand);
6679 switch ((int) key_symbol)
6683 if ((state & ControlMask) == 0)
6685 return(OpenCommand);
6688 return(NextCommand);
6690 return(FormerCommand);
6693 if ((state & Mod1Mask) != 0)
6694 return(SwirlCommand);
6695 if ((state & ControlMask) == 0)
6696 return(ShearCommand);
6697 return(SaveCommand);
6702 if ((state & Mod1Mask) != 0)
6703 return(OilPaintCommand);
6704 if ((state & Mod4Mask) != 0)
6705 return(ColorCommand);
6706 if ((state & ControlMask) == 0)
6707 return(NullCommand);
6708 return(PrintCommand);
6712 if ((state & Mod4Mask) != 0)
6713 return(DrawCommand);
6714 if ((state & ControlMask) == 0)
6715 return(NullCommand);
6716 return(DeleteCommand);
6720 if ((state & ControlMask) == 0)
6721 return(NullCommand);
6722 return(SelectCommand);
6726 if ((state & ControlMask) == 0)
6727 return(NullCommand);
6732 return(QuitCommand);
6736 if ((state & ControlMask) == 0)
6737 return(NullCommand);
6738 return(UndoCommand);
6743 if ((state & ControlMask) == 0)
6744 return(RollCommand);
6745 return(RedoCommand);
6749 if ((state & ControlMask) == 0)
6750 return(NullCommand);
6755 if ((state & Mod1Mask) != 0)
6756 return(CharcoalDrawCommand);
6757 if ((state & ControlMask) == 0)
6758 return(CropCommand);
6759 return(CopyCommand);
6764 if ((state & Mod4Mask) != 0)
6765 return(CompositeCommand);
6766 if ((state & ControlMask) == 0)
6767 return(FlipCommand);
6768 return(PasteCommand);
6771 return(HalfSizeCommand);
6773 return(OriginalSizeCommand);
6775 return(DoubleSizeCommand);
6777 return(ResizeCommand);
6779 return(RefreshCommand);
6780 case XK_bracketleft:
6781 return(ChopCommand);
6783 return(FlopCommand);
6785 return(RotateRightCommand);
6787 return(RotateLeftCommand);
6789 return(RotateCommand);
6791 return(TrimCommand);
6795 return(SaturationCommand);
6797 return(BrightnessCommand);
6799 return(GammaCommand);
6801 return(SpiffCommand);
6803 return(DullCommand);
6805 return(NormalizeCommand);
6807 return(EqualizeCommand);
6809 return(NegateCommand);
6811 return(GrayscaleCommand);
6813 return(QuantizeCommand);
6815 return(DespeckleCommand);
6817 return(EmbossCommand);
6819 return(ReduceNoiseCommand);
6821 return(AddNoiseCommand);
6823 return(SharpenCommand);
6825 return(BlurCommand);
6827 return(ThresholdCommand);
6829 return(EdgeDetectCommand);
6831 return(SpreadCommand);
6833 return(ShadeCommand);
6835 return(RaiseCommand);
6837 return(SegmentCommand);
6840 if ((state & Mod1Mask) == 0)
6841 return(NullCommand);
6842 return(ImplodeCommand);
6846 if ((state & Mod1Mask) == 0)
6847 return(NullCommand);
6848 return(WaveCommand);
6852 if ((state & Mod4Mask) == 0)
6853 return(NullCommand);
6854 return(MatteCommand);
6858 if ((state & Mod4Mask) == 0)
6859 return(NullCommand);
6860 return(AddBorderCommand);
6864 if ((state & Mod4Mask) == 0)
6865 return(NullCommand);
6866 return(AddFrameCommand);
6870 if ((state & Mod4Mask) == 0)
6871 return(NullCommand);
6872 return(CommentCommand);
6876 if ((state & Mod1Mask) != 0)
6877 return(ApplyCommand);
6878 if ((state & Mod4Mask) != 0)
6879 return(AnnotateCommand);
6880 if ((state & ControlMask) == 0)
6881 return(NullCommand);
6882 return(RegionofInterestCommand);
6885 return(InfoCommand);
6887 return(ZoomCommand);
6890 if ((state & ShiftMask) == 0)
6891 return(NullCommand);
6892 return(ShowPreviewCommand);
6895 return(LaunchCommand);
6897 return(HelpCommand);
6899 return(BrowseDocumentationCommand);
6902 (void) XMapRaised(display,windows->command.id);
6903 return(NullCommand);
6910 XTranslateImage(display,windows,*image,key_symbol);
6911 return(NullCommand);
6922 if ((state & Mod1Mask) != 0)
6928 Trim one pixel from edge of image.
6932 crop_info.width=(size_t) windows->image.ximage->width;
6933 crop_info.height=(size_t) windows->image.ximage->height;
6934 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
6936 if (resource_info->quantum >= (int) crop_info.height)
6937 resource_info->quantum=(int) crop_info.height-1;
6938 crop_info.height-=resource_info->quantum;
6940 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
6942 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
6943 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
6944 crop_info.y+=resource_info->quantum;
6945 crop_info.height-=resource_info->quantum;
6947 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
6949 if (resource_info->quantum >= (int) crop_info.width)
6950 resource_info->quantum=(int) crop_info.width-1;
6951 crop_info.width-=resource_info->quantum;
6953 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
6955 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
6956 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
6957 crop_info.x+=resource_info->quantum;
6958 crop_info.width-=resource_info->quantum;
6960 if ((int) (windows->image.x+windows->image.width) >
6961 (int) crop_info.width)
6962 windows->image.x=(int) (crop_info.width-windows->image.width);
6963 if ((int) (windows->image.y+windows->image.height) >
6964 (int) crop_info.height)
6965 windows->image.y=(int) (crop_info.height-windows->image.height);
6966 XSetCropGeometry(display,windows,&crop_info,*image);
6967 windows->image.window_changes.width=(int) crop_info.width;
6968 windows->image.window_changes.height=(int) crop_info.height;
6969 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
6970 (void) XConfigureImage(display,resource_info,windows,*image);
6971 return(NullCommand);
6973 XTranslateImage(display,windows,*image,key_symbol);
6974 return(NullCommand);
6977 return(NullCommand);
6979 return(NullCommand);
6983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6987 + X M a g i c k C o m m a n d %
6991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6993 % XMagickCommand() makes a transform to the image or Image window as
6994 % specified by a user menu button or keyboard command.
6996 % The format of the XMagickCommand method is:
6998 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
6999 % XWindows *windows,const CommandType command,Image **image)
7001 % A description of each parameter follows:
7003 % o nexus: Method XMagickCommand returns an image when the
7004 % user chooses 'Load Image' from the command menu. Otherwise a null
7005 % image is returned.
7007 % o display: Specifies a connection to an X server; returned from
7010 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7012 % o windows: Specifies a pointer to a XWindows structure.
7014 % o command: Specifies a command to perform.
7016 % o image: the image; XMagickCommand
7017 % may transform the image and return a new image pointer.
7020 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7021 XWindows *windows,const CommandType command,Image **image)
7024 filename[MaxTextExtent],
7025 geometry[MaxTextExtent],
7026 modulate_factors[MaxTextExtent];
7055 color[MaxTextExtent] = "gray";
7062 Process user command.
7064 XCheckRefreshWindows(display,windows);
7065 XImageCache(display,resource_info,windows,command,image);
7066 nexus=NewImageList();
7067 windows->image.window_changes.width=windows->image.ximage->width;
7068 windows->image.window_changes.height=windows->image.ximage->height;
7069 image_info=CloneImageInfo(resource_info->image_info);
7070 SetGeometryInfo(&geometry_info);
7071 GetQuantizeInfo(&quantize_info);
7079 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7087 for (i=0; i < resource_info->quantum; i++)
7088 XClientMessage(display,windows->image.id,windows->im_protocols,
7089 windows->im_next_image,CurrentTime);
7095 Display former image.
7097 for (i=0; i < resource_info->quantum; i++)
7098 XClientMessage(display,windows->image.id,windows->im_protocols,
7099 windows->im_former_image,CurrentTime);
7110 status=chdir(resource_info->home_directory);
7112 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
7113 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
7114 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7122 status=XSaveImage(display,resource_info,windows,*image);
7123 if (status == MagickFalse)
7125 XNoticeWidget(display,windows,"Unable to write X image:",
7126 (*image)->filename);
7136 status=XPrintImage(display,resource_info,windows,*image);
7137 if (status == MagickFalse)
7139 XNoticeWidget(display,windows,"Unable to print X image:",
7140 (*image)->filename);
7148 filename[MaxTextExtent] = "\0";
7153 XFileBrowserWidget(display,windows,"Delete",filename);
7154 if (*filename == '\0')
7156 status=remove(filename) != 0 ? MagickTrue : MagickFalse;
7157 if (status != MagickFalse)
7158 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7167 color[MaxTextExtent] = "gray",
7168 geometry[MaxTextExtent] = "640x480";
7171 *format = "gradient";
7174 Query user for canvas geometry.
7176 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7178 if (*geometry == '\0')
7182 XColorBrowserWidget(display,windows,"Select",color);
7188 (void) FormatMagickString(image_info->filename,MaxTextExtent,
7189 "%s:%s",format,color);
7190 (void) CloneString(&image_info->size,geometry);
7191 nexus=ReadImage(image_info,&(*image)->exception);
7192 CatchException(&(*image)->exception);
7193 XClientMessage(display,windows->image.id,windows->im_protocols,
7194 windows->im_next_image,CurrentTime);
7197 case VisualDirectoryCommand:
7200 Visual Image directory.
7202 nexus=XVisualDirectoryImage(display,resource_info,windows);
7210 if (resource_info->confirm_exit == MagickFalse)
7211 XClientMessage(display,windows->image.id,windows->im_protocols,
7212 windows->im_exit,CurrentTime);
7219 Confirm program exit.
7221 status=XConfirmWidget(display,windows,"Do you really want to exit",
7222 resource_info->client_name);
7224 XClientMessage(display,windows->image.id,windows->im_protocols,
7225 windows->im_exit,CurrentTime);
7234 (void) XCropImage(display,resource_info,windows,*image,CutMode);
7242 (void) XCropImage(display,resource_info,windows,*image,CopyMode);
7250 status=XPasteImage(display,resource_info,windows,*image);
7251 if (status == MagickFalse)
7253 XNoticeWidget(display,windows,"Unable to paste X image",
7254 (*image)->filename);
7259 case HalfSizeCommand:
7264 windows->image.window_changes.width=windows->image.ximage->width/2;
7265 windows->image.window_changes.height=windows->image.ximage->height/2;
7266 (void) XConfigureImage(display,resource_info,windows,*image);
7269 case OriginalSizeCommand:
7272 Original image size.
7274 windows->image.window_changes.width=(int) (*image)->columns;
7275 windows->image.window_changes.height=(int) (*image)->rows;
7276 (void) XConfigureImage(display,resource_info,windows,*image);
7279 case DoubleSizeCommand:
7282 Double the image size.
7284 windows->image.window_changes.width=windows->image.ximage->width << 1;
7285 windows->image.window_changes.height=windows->image.ximage->height << 1;
7286 (void) XConfigureImage(display,resource_info,windows,*image);
7305 width=(size_t) windows->image.ximage->width;
7306 height=(size_t) windows->image.ximage->height;
7309 (void) FormatMagickString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7310 (double) width,(double) height);
7311 status=XDialogWidget(display,windows,"Resize",
7312 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7313 if (*geometry == '\0')
7316 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7317 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7318 windows->image.window_changes.width=(int) width;
7319 windows->image.window_changes.height=(int) height;
7320 (void) XConfigureImage(display,resource_info,windows,*image);
7326 image_geometry[MaxTextExtent];
7328 if ((windows->image.crop_geometry == (char *) NULL) &&
7329 ((int) (*image)->columns == windows->image.ximage->width) &&
7330 ((int) (*image)->rows == windows->image.ximage->height))
7333 Apply size transforms to image.
7335 XSetCursorState(display,windows,MagickTrue);
7336 XCheckRefreshWindows(display,windows);
7338 Crop and/or scale displayed image.
7340 (void) FormatMagickString(image_geometry,MaxTextExtent,"%dx%d!",
7341 windows->image.ximage->width,windows->image.ximage->height);
7342 (void) TransformImage(image,windows->image.crop_geometry,image_geometry);
7343 if (windows->image.crop_geometry != (char *) NULL)
7344 windows->image.crop_geometry=(char *)
7345 RelinquishMagickMemory(windows->image.crop_geometry);
7348 XConfigureImageColormap(display,resource_info,windows,*image);
7349 (void) XConfigureImage(display,resource_info,windows,*image);
7352 case RefreshCommand:
7354 (void) XConfigureImage(display,resource_info,windows,*image);
7357 case RestoreCommand:
7360 Restore Image window to its original size.
7362 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7363 (windows->image.height == (unsigned int) (*image)->rows) &&
7364 (windows->image.crop_geometry == (char *) NULL))
7366 (void) XBell(display,0);
7369 windows->image.window_changes.width=(int) (*image)->columns;
7370 windows->image.window_changes.height=(int) (*image)->rows;
7371 if (windows->image.crop_geometry != (char *) NULL)
7373 windows->image.crop_geometry=(char *)
7374 RelinquishMagickMemory(windows->image.crop_geometry);
7375 windows->image.crop_geometry=(char *) NULL;
7379 XConfigureImageColormap(display,resource_info,windows,*image);
7380 (void) XConfigureImage(display,resource_info,windows,*image);
7388 (void) XCropImage(display,resource_info,windows,*image,CropMode);
7396 status=XChopImage(display,resource_info,windows,image);
7397 if (status == MagickFalse)
7399 XNoticeWidget(display,windows,"Unable to cut X image",
7400 (*image)->filename);
7411 Flop image scanlines.
7413 XSetCursorState(display,windows,MagickTrue);
7414 XCheckRefreshWindows(display,windows);
7415 flop_image=FlopImage(*image,&(*image)->exception);
7416 if (flop_image != (Image *) NULL)
7418 *image=DestroyImage(*image);
7421 CatchException(&(*image)->exception);
7422 XSetCursorState(display,windows,MagickFalse);
7423 if (windows->image.crop_geometry != (char *) NULL)
7428 width=(unsigned int) (*image)->columns;
7429 height=(unsigned int) (*image)->rows;
7430 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7432 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
7433 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7435 if (windows->image.orphan != MagickFalse)
7437 (void) XConfigureImage(display,resource_info,windows,*image);
7446 Flip image scanlines.
7448 XSetCursorState(display,windows,MagickTrue);
7449 XCheckRefreshWindows(display,windows);
7450 flip_image=FlipImage(*image,&(*image)->exception);
7451 if (flip_image != (Image *) NULL)
7453 *image=DestroyImage(*image);
7456 CatchException(&(*image)->exception);
7457 XSetCursorState(display,windows,MagickFalse);
7458 if (windows->image.crop_geometry != (char *) NULL)
7463 width=(unsigned int) (*image)->columns;
7464 height=(unsigned int) (*image)->rows;
7465 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7467 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
7468 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7470 if (windows->image.orphan != MagickFalse)
7472 (void) XConfigureImage(display,resource_info,windows,*image);
7475 case RotateRightCommand:
7478 Rotate image 90 degrees clockwise.
7480 status=XRotateImage(display,resource_info,windows,90.0,image);
7481 if (status == MagickFalse)
7483 XNoticeWidget(display,windows,"Unable to rotate X image",
7484 (*image)->filename);
7489 case RotateLeftCommand:
7492 Rotate image 90 degrees counter-clockwise.
7494 status=XRotateImage(display,resource_info,windows,-90.0,image);
7495 if (status == MagickFalse)
7497 XNoticeWidget(display,windows,"Unable to rotate X image",
7498 (*image)->filename);
7508 status=XRotateImage(display,resource_info,windows,0.0,image);
7509 if (status == MagickFalse)
7511 XNoticeWidget(display,windows,"Unable to rotate X image",
7512 (*image)->filename);
7523 geometry[MaxTextExtent] = "45.0x45.0";
7526 Query user for shear color and geometry.
7528 XColorBrowserWidget(display,windows,"Select",color);
7531 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7533 if (*geometry == '\0')
7538 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
7539 XSetCursorState(display,windows,MagickTrue);
7540 XCheckRefreshWindows(display,windows);
7541 (void) QueryColorDatabase(color,&(*image)->background_color,
7542 &(*image)->exception);
7543 flags=ParseGeometry(geometry,&geometry_info);
7544 if ((flags & SigmaValue) == 0)
7545 geometry_info.sigma=geometry_info.rho;
7546 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7547 &(*image)->exception);
7548 if (shear_image != (Image *) NULL)
7550 *image=DestroyImage(*image);
7553 CatchException(&(*image)->exception);
7554 XSetCursorState(display,windows,MagickFalse);
7555 if (windows->image.orphan != MagickFalse)
7557 windows->image.window_changes.width=(int) (*image)->columns;
7558 windows->image.window_changes.height=(int) (*image)->rows;
7559 XConfigureImageColormap(display,resource_info,windows,*image);
7560 (void) XConfigureImage(display,resource_info,windows,*image);
7569 geometry[MaxTextExtent] = "+2+2";
7572 Query user for the roll geometry.
7574 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7576 if (*geometry == '\0')
7581 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
7582 XSetCursorState(display,windows,MagickTrue);
7583 XCheckRefreshWindows(display,windows);
7584 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7585 &(*image)->exception);
7586 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7587 &(*image)->exception);
7588 if (roll_image != (Image *) NULL)
7590 *image=DestroyImage(*image);
7593 CatchException(&(*image)->exception);
7594 XSetCursorState(display,windows,MagickFalse);
7595 if (windows->image.orphan != MagickFalse)
7597 windows->image.window_changes.width=(int) (*image)->columns;
7598 windows->image.window_changes.height=(int) (*image)->rows;
7599 XConfigureImageColormap(display,resource_info,windows,*image);
7600 (void) XConfigureImage(display,resource_info,windows,*image);
7606 fuzz[MaxTextExtent];
7609 Query user for the fuzz factor.
7611 (void) FormatMagickString(fuzz,MaxTextExtent,"%g%%",100.0*
7612 (*image)->fuzz/(QuantumRange+1.0));
7613 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7616 (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0);
7620 status=XTrimImage(display,resource_info,windows,*image);
7621 if (status == MagickFalse)
7623 XNoticeWidget(display,windows,"Unable to trim X image",
7624 (*image)->filename);
7632 hue_percent[MaxTextExtent] = "110";
7635 Query user for percent hue change.
7637 (void) XDialogWidget(display,windows,"Apply",
7638 "Enter percent change in image hue (0-200):",hue_percent);
7639 if (*hue_percent == '\0')
7644 XSetCursorState(display,windows,MagickTrue);
7645 XCheckRefreshWindows(display,windows);
7646 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7647 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7649 (void) ModulateImage(*image,modulate_factors);
7650 XSetCursorState(display,windows,MagickFalse);
7651 if (windows->image.orphan != MagickFalse)
7653 XConfigureImageColormap(display,resource_info,windows,*image);
7654 (void) XConfigureImage(display,resource_info,windows,*image);
7657 case SaturationCommand:
7660 saturation_percent[MaxTextExtent] = "110";
7663 Query user for percent saturation change.
7665 (void) XDialogWidget(display,windows,"Apply",
7666 "Enter percent change in color saturation (0-200):",saturation_percent);
7667 if (*saturation_percent == '\0')
7670 Vary color saturation.
7672 XSetCursorState(display,windows,MagickTrue);
7673 XCheckRefreshWindows(display,windows);
7674 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7675 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7677 (void) ModulateImage(*image,modulate_factors);
7678 XSetCursorState(display,windows,MagickFalse);
7679 if (windows->image.orphan != MagickFalse)
7681 XConfigureImageColormap(display,resource_info,windows,*image);
7682 (void) XConfigureImage(display,resource_info,windows,*image);
7685 case BrightnessCommand:
7688 brightness_percent[MaxTextExtent] = "110";
7691 Query user for percent brightness change.
7693 (void) XDialogWidget(display,windows,"Apply",
7694 "Enter percent change in color brightness (0-200):",brightness_percent);
7695 if (*brightness_percent == '\0')
7698 Vary the color brightness.
7700 XSetCursorState(display,windows,MagickTrue);
7701 XCheckRefreshWindows(display,windows);
7702 (void) CopyMagickString(modulate_factors,brightness_percent,
7704 (void) ModulateImage(*image,modulate_factors);
7705 XSetCursorState(display,windows,MagickFalse);
7706 if (windows->image.orphan != MagickFalse)
7708 XConfigureImageColormap(display,resource_info,windows,*image);
7709 (void) XConfigureImage(display,resource_info,windows,*image);
7715 factor[MaxTextExtent] = "1.6";
7718 Query user for gamma value.
7720 (void) XDialogWidget(display,windows,"Gamma",
7721 "Enter gamma value (e.g. 1.0,1.0,1.6):",factor);
7722 if (*factor == '\0')
7725 Gamma correct image.
7727 XSetCursorState(display,windows,MagickTrue);
7728 XCheckRefreshWindows(display,windows);
7729 (void) GammaImage(*image,factor);
7730 XSetCursorState(display,windows,MagickFalse);
7731 if (windows->image.orphan != MagickFalse)
7733 XConfigureImageColormap(display,resource_info,windows,*image);
7734 (void) XConfigureImage(display,resource_info,windows,*image);
7740 Sharpen the image contrast.
7742 XSetCursorState(display,windows,MagickTrue);
7743 XCheckRefreshWindows(display,windows);
7744 (void) ContrastImage(*image,MagickTrue);
7745 XSetCursorState(display,windows,MagickFalse);
7746 if (windows->image.orphan != MagickFalse)
7748 XConfigureImageColormap(display,resource_info,windows,*image);
7749 (void) XConfigureImage(display,resource_info,windows,*image);
7755 Dull the image contrast.
7757 XSetCursorState(display,windows,MagickTrue);
7758 XCheckRefreshWindows(display,windows);
7759 (void) ContrastImage(*image,MagickFalse);
7760 XSetCursorState(display,windows,MagickFalse);
7761 if (windows->image.orphan != MagickFalse)
7763 XConfigureImageColormap(display,resource_info,windows,*image);
7764 (void) XConfigureImage(display,resource_info,windows,*image);
7767 case ContrastStretchCommand:
7774 levels[MaxTextExtent] = "1%";
7777 Query user for gamma value.
7779 (void) XDialogWidget(display,windows,"Contrast Stretch",
7780 "Enter black and white points:",levels);
7781 if (*levels == '\0')
7784 Contrast stretch image.
7786 XSetCursorState(display,windows,MagickTrue);
7787 XCheckRefreshWindows(display,windows);
7788 flags=ParseGeometry(levels,&geometry_info);
7789 black_point=geometry_info.rho;
7790 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7791 if ((flags & PercentValue) != 0)
7793 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7794 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7796 white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point;
7797 (void) ContrastStretchImageChannel(*image,DefaultChannels,black_point,
7799 XSetCursorState(display,windows,MagickFalse);
7800 if (windows->image.orphan != MagickFalse)
7802 XConfigureImageColormap(display,resource_info,windows,*image);
7803 (void) XConfigureImage(display,resource_info,windows,*image);
7806 case SigmoidalContrastCommand:
7809 levels[MaxTextExtent] = "3x50%";
7812 Query user for gamma value.
7814 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7815 "Enter contrast and midpoint:",levels);
7816 if (*levels == '\0')
7819 Contrast stretch image.
7821 XSetCursorState(display,windows,MagickTrue);
7822 XCheckRefreshWindows(display,windows);
7823 (void) SigmoidalContrastImage(*image,MagickTrue,levels);
7824 XSetCursorState(display,windows,MagickFalse);
7825 if (windows->image.orphan != MagickFalse)
7827 XConfigureImageColormap(display,resource_info,windows,*image);
7828 (void) XConfigureImage(display,resource_info,windows,*image);
7831 case NormalizeCommand:
7834 Perform histogram normalization on the image.
7836 XSetCursorState(display,windows,MagickTrue);
7837 XCheckRefreshWindows(display,windows);
7838 (void) NormalizeImage(*image);
7839 XSetCursorState(display,windows,MagickFalse);
7840 if (windows->image.orphan != MagickFalse)
7842 XConfigureImageColormap(display,resource_info,windows,*image);
7843 (void) XConfigureImage(display,resource_info,windows,*image);
7846 case EqualizeCommand:
7849 Perform histogram equalization on the image.
7851 XSetCursorState(display,windows,MagickTrue);
7852 XCheckRefreshWindows(display,windows);
7853 (void) EqualizeImage(*image);
7854 XSetCursorState(display,windows,MagickFalse);
7855 if (windows->image.orphan != MagickFalse)
7857 XConfigureImageColormap(display,resource_info,windows,*image);
7858 (void) XConfigureImage(display,resource_info,windows,*image);
7864 Negate colors in image.
7866 XSetCursorState(display,windows,MagickTrue);
7867 XCheckRefreshWindows(display,windows);
7868 (void) NegateImage(*image,MagickFalse);
7869 XSetCursorState(display,windows,MagickFalse);
7870 if (windows->image.orphan != MagickFalse)
7872 XConfigureImageColormap(display,resource_info,windows,*image);
7873 (void) XConfigureImage(display,resource_info,windows,*image);
7876 case GrayscaleCommand:
7879 Convert image to grayscale.
7881 XSetCursorState(display,windows,MagickTrue);
7882 XCheckRefreshWindows(display,windows);
7883 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
7884 GrayscaleType : GrayscaleMatteType);
7885 XSetCursorState(display,windows,MagickFalse);
7886 if (windows->image.orphan != MagickFalse)
7888 XConfigureImageColormap(display,resource_info,windows,*image);
7889 (void) XConfigureImage(display,resource_info,windows,*image);
7898 filename[MaxTextExtent] = "\0";
7901 Request image file name from user.
7903 XFileBrowserWidget(display,windows,"Map",filename);
7904 if (*filename == '\0')
7909 XSetCursorState(display,windows,MagickTrue);
7910 XCheckRefreshWindows(display,windows);
7911 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
7912 affinity_image=ReadImage(image_info,&(*image)->exception);
7913 if (affinity_image != (Image *) NULL)
7915 (void) RemapImage(&quantize_info,*image,affinity_image);
7916 affinity_image=DestroyImage(affinity_image);
7918 CatchException(&(*image)->exception);
7919 XSetCursorState(display,windows,MagickFalse);
7920 if (windows->image.orphan != MagickFalse)
7922 XConfigureImageColormap(display,resource_info,windows,*image);
7923 (void) XConfigureImage(display,resource_info,windows,*image);
7926 case QuantizeCommand:
7932 colors[MaxTextExtent] = "256";
7935 Query user for maximum number of colors.
7937 status=XDialogWidget(display,windows,"Quantize",
7938 "Maximum number of colors:",colors);
7939 if (*colors == '\0')
7942 Color reduce the image.
7944 XSetCursorState(display,windows,MagickTrue);
7945 XCheckRefreshWindows(display,windows);
7946 quantize_info.number_colors=StringToUnsignedLong(colors);
7947 quantize_info.dither=status != 0 ? MagickTrue : MagickFalse;
7948 (void) QuantizeImage(&quantize_info,*image);
7949 XSetCursorState(display,windows,MagickFalse);
7950 if (windows->image.orphan != MagickFalse)
7952 XConfigureImageColormap(display,resource_info,windows,*image);
7953 (void) XConfigureImage(display,resource_info,windows,*image);
7956 case DespeckleCommand:
7964 XSetCursorState(display,windows,MagickTrue);
7965 XCheckRefreshWindows(display,windows);
7966 despeckle_image=DespeckleImage(*image,&(*image)->exception);
7967 if (despeckle_image != (Image *) NULL)
7969 *image=DestroyImage(*image);
7970 *image=despeckle_image;
7972 CatchException(&(*image)->exception);
7973 XSetCursorState(display,windows,MagickFalse);
7974 if (windows->image.orphan != MagickFalse)
7976 XConfigureImageColormap(display,resource_info,windows,*image);
7977 (void) XConfigureImage(display,resource_info,windows,*image);
7986 radius[MaxTextExtent] = "0.0x1.0";
7989 Query user for emboss radius.
7991 (void) XDialogWidget(display,windows,"Emboss",
7992 "Enter the emboss radius and standard deviation:",radius);
7993 if (*radius == '\0')
7996 Reduce noise in the image.
7998 XSetCursorState(display,windows,MagickTrue);
7999 XCheckRefreshWindows(display,windows);
8000 flags=ParseGeometry(radius,&geometry_info);
8001 if ((flags & SigmaValue) == 0)
8002 geometry_info.sigma=1.0;
8003 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8004 &(*image)->exception);
8005 if (emboss_image != (Image *) NULL)
8007 *image=DestroyImage(*image);
8008 *image=emboss_image;
8010 CatchException(&(*image)->exception);
8011 XSetCursorState(display,windows,MagickFalse);
8012 if (windows->image.orphan != MagickFalse)
8014 XConfigureImageColormap(display,resource_info,windows,*image);
8015 (void) XConfigureImage(display,resource_info,windows,*image);
8018 case ReduceNoiseCommand:
8024 radius[MaxTextExtent] = "0";
8027 Query user for noise radius.
8029 (void) XDialogWidget(display,windows,"Reduce Noise",
8030 "Enter the noise radius:",radius);
8031 if (*radius == '\0')
8034 Reduce noise in the image.
8036 XSetCursorState(display,windows,MagickTrue);
8037 XCheckRefreshWindows(display,windows);
8038 flags=ParseGeometry(radius,&geometry_info);
8039 noise_image=ReduceNoiseImage(*image,geometry_info.rho,
8040 &(*image)->exception);
8041 if (noise_image != (Image *) NULL)
8043 *image=DestroyImage(*image);
8046 CatchException(&(*image)->exception);
8047 XSetCursorState(display,windows,MagickFalse);
8048 if (windows->image.orphan != MagickFalse)
8050 XConfigureImageColormap(display,resource_info,windows,*image);
8051 (void) XConfigureImage(display,resource_info,windows,*image);
8054 case AddNoiseCommand:
8063 noise_type[MaxTextExtent] = "Gaussian";
8066 Add noise to the image.
8068 noises=GetMagickOptions(MagickNoiseOptions);
8069 if (noises == (char **) NULL)
8071 XListBrowserWidget(display,windows,&windows->widget,
8072 (const char **) noises,"Add Noise",
8073 "Select a type of noise to add to your image:",noise_type);
8074 noises=DestroyStringList(noises);
8075 if (*noise_type == '\0')
8077 XSetCursorState(display,windows,MagickTrue);
8078 XCheckRefreshWindows(display,windows);
8079 noise_image=AddNoiseImage(*image,(NoiseType) ParseMagickOption(
8080 MagickNoiseOptions,MagickFalse,noise_type),&(*image)->exception);
8081 if (noise_image != (Image *) NULL)
8083 *image=DestroyImage(*image);
8086 CatchException(&(*image)->exception);
8087 XSetCursorState(display,windows,MagickFalse);
8088 if (windows->image.orphan != MagickFalse)
8090 XConfigureImageColormap(display,resource_info,windows,*image);
8091 (void) XConfigureImage(display,resource_info,windows,*image);
8094 case SharpenCommand:
8100 radius[MaxTextExtent] = "0.0x1.0";
8103 Query user for sharpen radius.
8105 (void) XDialogWidget(display,windows,"Sharpen",
8106 "Enter the sharpen radius and standard deviation:",radius);
8107 if (*radius == '\0')
8110 Sharpen image scanlines.
8112 XSetCursorState(display,windows,MagickTrue);
8113 XCheckRefreshWindows(display,windows);
8114 flags=ParseGeometry(radius,&geometry_info);
8115 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8116 &(*image)->exception);
8117 if (sharp_image != (Image *) NULL)
8119 *image=DestroyImage(*image);
8122 CatchException(&(*image)->exception);
8123 XSetCursorState(display,windows,MagickFalse);
8124 if (windows->image.orphan != MagickFalse)
8126 XConfigureImageColormap(display,resource_info,windows,*image);
8127 (void) XConfigureImage(display,resource_info,windows,*image);
8136 radius[MaxTextExtent] = "0.0x1.0";
8139 Query user for blur radius.
8141 (void) XDialogWidget(display,windows,"Blur",
8142 "Enter the blur radius and standard deviation:",radius);
8143 if (*radius == '\0')
8148 XSetCursorState(display,windows,MagickTrue);
8149 XCheckRefreshWindows(display,windows);
8150 flags=ParseGeometry(radius,&geometry_info);
8151 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8152 &(*image)->exception);
8153 if (blur_image != (Image *) NULL)
8155 *image=DestroyImage(*image);
8158 CatchException(&(*image)->exception);
8159 XSetCursorState(display,windows,MagickFalse);
8160 if (windows->image.orphan != MagickFalse)
8162 XConfigureImageColormap(display,resource_info,windows,*image);
8163 (void) XConfigureImage(display,resource_info,windows,*image);
8166 case ThresholdCommand:
8172 factor[MaxTextExtent] = "128";
8175 Query user for threshold value.
8177 (void) XDialogWidget(display,windows,"Threshold",
8178 "Enter threshold value:",factor);
8179 if (*factor == '\0')
8182 Gamma correct image.
8184 XSetCursorState(display,windows,MagickTrue);
8185 XCheckRefreshWindows(display,windows);
8186 threshold=SiPrefixToDouble(factor,QuantumRange);
8187 (void) BilevelImage(*image,threshold);
8188 XSetCursorState(display,windows,MagickFalse);
8189 if (windows->image.orphan != MagickFalse)
8191 XConfigureImageColormap(display,resource_info,windows,*image);
8192 (void) XConfigureImage(display,resource_info,windows,*image);
8195 case EdgeDetectCommand:
8201 radius[MaxTextExtent] = "0";
8204 Query user for edge factor.
8206 (void) XDialogWidget(display,windows,"Detect Edges",
8207 "Enter the edge detect radius:",radius);
8208 if (*radius == '\0')
8211 Detect edge in image.
8213 XSetCursorState(display,windows,MagickTrue);
8214 XCheckRefreshWindows(display,windows);
8215 flags=ParseGeometry(radius,&geometry_info);
8216 edge_image=EdgeImage(*image,geometry_info.rho,&(*image)->exception);
8217 if (edge_image != (Image *) NULL)
8219 *image=DestroyImage(*image);
8222 CatchException(&(*image)->exception);
8223 XSetCursorState(display,windows,MagickFalse);
8224 if (windows->image.orphan != MagickFalse)
8226 XConfigureImageColormap(display,resource_info,windows,*image);
8227 (void) XConfigureImage(display,resource_info,windows,*image);
8236 amount[MaxTextExtent] = "2";
8239 Query user for spread amount.
8241 (void) XDialogWidget(display,windows,"Spread",
8242 "Enter the displacement amount:",amount);
8243 if (*amount == '\0')
8246 Displace image pixels by a random amount.
8248 XSetCursorState(display,windows,MagickTrue);
8249 XCheckRefreshWindows(display,windows);
8250 flags=ParseGeometry(amount,&geometry_info);
8251 spread_image=EdgeImage(*image,geometry_info.rho,&(*image)->exception);
8252 if (spread_image != (Image *) NULL)
8254 *image=DestroyImage(*image);
8255 *image=spread_image;
8257 CatchException(&(*image)->exception);
8258 XSetCursorState(display,windows,MagickFalse);
8259 if (windows->image.orphan != MagickFalse)
8261 XConfigureImageColormap(display,resource_info,windows,*image);
8262 (void) XConfigureImage(display,resource_info,windows,*image);
8274 geometry[MaxTextExtent] = "30x30";
8277 Query user for the shade geometry.
8279 status=XDialogWidget(display,windows,"Shade",
8280 "Enter the azimuth and elevation of the light source:",geometry);
8281 if (*geometry == '\0')
8286 XSetCursorState(display,windows,MagickTrue);
8287 XCheckRefreshWindows(display,windows);
8288 flags=ParseGeometry(geometry,&geometry_info);
8289 if ((flags & SigmaValue) == 0)
8290 geometry_info.sigma=1.0;
8291 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
8292 geometry_info.rho,geometry_info.sigma,&(*image)->exception);
8293 if (shade_image != (Image *) NULL)
8295 *image=DestroyImage(*image);
8298 CatchException(&(*image)->exception);
8299 XSetCursorState(display,windows,MagickFalse);
8300 if (windows->image.orphan != MagickFalse)
8302 XConfigureImageColormap(display,resource_info,windows,*image);
8303 (void) XConfigureImage(display,resource_info,windows,*image);
8309 bevel_width[MaxTextExtent] = "10";
8312 Query user for bevel width.
8314 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8315 if (*bevel_width == '\0')
8320 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
8321 XSetCursorState(display,windows,MagickTrue);
8322 XCheckRefreshWindows(display,windows);
8323 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8324 &(*image)->exception);
8325 (void) RaiseImage(*image,&page_geometry,MagickTrue);
8326 XSetCursorState(display,windows,MagickFalse);
8327 if (windows->image.orphan != MagickFalse)
8329 XConfigureImageColormap(display,resource_info,windows,*image);
8330 (void) XConfigureImage(display,resource_info,windows,*image);
8333 case SegmentCommand:
8336 threshold[MaxTextExtent] = "1.0x1.5";
8339 Query user for smoothing threshold.
8341 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8343 if (*threshold == '\0')
8348 XSetCursorState(display,windows,MagickTrue);
8349 XCheckRefreshWindows(display,windows);
8350 flags=ParseGeometry(threshold,&geometry_info);
8351 if ((flags & SigmaValue) == 0)
8352 geometry_info.sigma=1.0;
8353 (void) SegmentImage(*image,RGBColorspace,MagickFalse,geometry_info.rho,
8354 geometry_info.sigma);
8355 XSetCursorState(display,windows,MagickFalse);
8356 if (windows->image.orphan != MagickFalse)
8358 XConfigureImageColormap(display,resource_info,windows,*image);
8359 (void) XConfigureImage(display,resource_info,windows,*image);
8362 case SepiaToneCommand:
8371 factor[MaxTextExtent] = "80%";
8374 Query user for sepia-tone factor.
8376 (void) XDialogWidget(display,windows,"Sepia Tone",
8377 "Enter the sepia tone factor (0 - 99.9%):",factor);
8378 if (*factor == '\0')
8381 Sepia tone image pixels.
8383 XSetCursorState(display,windows,MagickTrue);
8384 XCheckRefreshWindows(display,windows);
8385 threshold=SiPrefixToDouble(factor,QuantumRange);
8386 sepia_image=SepiaToneImage(*image,threshold,&(*image)->exception);
8387 if (sepia_image != (Image *) NULL)
8389 *image=DestroyImage(*image);
8392 CatchException(&(*image)->exception);
8393 XSetCursorState(display,windows,MagickFalse);
8394 if (windows->image.orphan != MagickFalse)
8396 XConfigureImageColormap(display,resource_info,windows,*image);
8397 (void) XConfigureImage(display,resource_info,windows,*image);
8400 case SolarizeCommand:
8406 factor[MaxTextExtent] = "60%";
8409 Query user for solarize factor.
8411 (void) XDialogWidget(display,windows,"Solarize",
8412 "Enter the solarize factor (0 - 99.9%):",factor);
8413 if (*factor == '\0')
8416 Solarize image pixels.
8418 XSetCursorState(display,windows,MagickTrue);
8419 XCheckRefreshWindows(display,windows);
8420 threshold=SiPrefixToDouble(factor,QuantumRange);
8421 (void) SolarizeImage(*image,threshold);
8422 XSetCursorState(display,windows,MagickFalse);
8423 if (windows->image.orphan != MagickFalse)
8425 XConfigureImageColormap(display,resource_info,windows,*image);
8426 (void) XConfigureImage(display,resource_info,windows,*image);
8435 degrees[MaxTextExtent] = "60";
8438 Query user for swirl angle.
8440 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8442 if (*degrees == '\0')
8445 Swirl image pixels about the center.
8447 XSetCursorState(display,windows,MagickTrue);
8448 XCheckRefreshWindows(display,windows);
8449 flags=ParseGeometry(degrees,&geometry_info);
8450 swirl_image=SwirlImage(*image,geometry_info.rho,&(*image)->exception);
8451 if (swirl_image != (Image *) NULL)
8453 *image=DestroyImage(*image);
8456 CatchException(&(*image)->exception);
8457 XSetCursorState(display,windows,MagickFalse);
8458 if (windows->image.orphan != MagickFalse)
8460 XConfigureImageColormap(display,resource_info,windows,*image);
8461 (void) XConfigureImage(display,resource_info,windows,*image);
8464 case ImplodeCommand:
8470 factor[MaxTextExtent] = "0.3";
8473 Query user for implode factor.
8475 (void) XDialogWidget(display,windows,"Implode",
8476 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8477 if (*factor == '\0')
8480 Implode image pixels about the center.
8482 XSetCursorState(display,windows,MagickTrue);
8483 XCheckRefreshWindows(display,windows);
8484 flags=ParseGeometry(factor,&geometry_info);
8485 implode_image=ImplodeImage(*image,geometry_info.rho,&(*image)->exception);
8486 if (implode_image != (Image *) NULL)
8488 *image=DestroyImage(*image);
8489 *image=implode_image;
8491 CatchException(&(*image)->exception);
8492 XSetCursorState(display,windows,MagickFalse);
8493 if (windows->image.orphan != MagickFalse)
8495 XConfigureImageColormap(display,resource_info,windows,*image);
8496 (void) XConfigureImage(display,resource_info,windows,*image);
8499 case VignetteCommand:
8505 geometry[MaxTextExtent] = "0x20";
8508 Query user for the vignette geometry.
8510 (void) XDialogWidget(display,windows,"Vignette",
8511 "Enter the radius, sigma, and x and y offsets:",geometry);
8512 if (*geometry == '\0')
8515 Soften the edges of the image in vignette style
8517 XSetCursorState(display,windows,MagickTrue);
8518 XCheckRefreshWindows(display,windows);
8519 flags=ParseGeometry(geometry,&geometry_info);
8520 if ((flags & SigmaValue) == 0)
8521 geometry_info.sigma=1.0;
8522 if ((flags & XiValue) == 0)
8523 geometry_info.xi=0.1*(*image)->columns;
8524 if ((flags & PsiValue) == 0)
8525 geometry_info.psi=0.1*(*image)->rows;
8526 vignette_image=VignetteImage(*image,geometry_info.rho,geometry_info.sigma,
8527 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
8528 0.5),&(*image)->exception);
8529 if (vignette_image != (Image *) NULL)
8531 *image=DestroyImage(*image);
8532 *image=vignette_image;
8534 CatchException(&(*image)->exception);
8535 XSetCursorState(display,windows,MagickFalse);
8536 if (windows->image.orphan != MagickFalse)
8538 XConfigureImageColormap(display,resource_info,windows,*image);
8539 (void) XConfigureImage(display,resource_info,windows,*image);
8548 geometry[MaxTextExtent] = "25x150";
8551 Query user for the wave geometry.
8553 (void) XDialogWidget(display,windows,"Wave",
8554 "Enter the amplitude and length of the wave:",geometry);
8555 if (*geometry == '\0')
8558 Alter an image along a sine wave.
8560 XSetCursorState(display,windows,MagickTrue);
8561 XCheckRefreshWindows(display,windows);
8562 flags=ParseGeometry(geometry,&geometry_info);
8563 if ((flags & SigmaValue) == 0)
8564 geometry_info.sigma=1.0;
8565 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8566 &(*image)->exception);
8567 if (wave_image != (Image *) NULL)
8569 *image=DestroyImage(*image);
8572 CatchException(&(*image)->exception);
8573 XSetCursorState(display,windows,MagickFalse);
8574 if (windows->image.orphan != MagickFalse)
8576 XConfigureImageColormap(display,resource_info,windows,*image);
8577 (void) XConfigureImage(display,resource_info,windows,*image);
8580 case OilPaintCommand:
8586 radius[MaxTextExtent] = "0";
8589 Query user for circular neighborhood radius.
8591 (void) XDialogWidget(display,windows,"Oil Paint",
8592 "Enter the mask radius:",radius);
8593 if (*radius == '\0')
8596 OilPaint image scanlines.
8598 XSetCursorState(display,windows,MagickTrue);
8599 XCheckRefreshWindows(display,windows);
8600 flags=ParseGeometry(radius,&geometry_info);
8601 paint_image=OilPaintImage(*image,geometry_info.rho,&(*image)->exception);
8602 if (paint_image != (Image *) NULL)
8604 *image=DestroyImage(*image);
8607 CatchException(&(*image)->exception);
8608 XSetCursorState(display,windows,MagickFalse);
8609 if (windows->image.orphan != MagickFalse)
8611 XConfigureImageColormap(display,resource_info,windows,*image);
8612 (void) XConfigureImage(display,resource_info,windows,*image);
8615 case CharcoalDrawCommand:
8621 radius[MaxTextExtent] = "0x1";
8624 Query user for charcoal radius.
8626 (void) XDialogWidget(display,windows,"Charcoal Draw",
8627 "Enter the charcoal radius and sigma:",radius);
8628 if (*radius == '\0')
8633 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
8634 XSetCursorState(display,windows,MagickTrue);
8635 XCheckRefreshWindows(display,windows);
8636 flags=ParseGeometry(radius,&geometry_info);
8637 if ((flags & SigmaValue) == 0)
8638 geometry_info.sigma=geometry_info.rho;
8639 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8640 &(*image)->exception);
8641 if (charcoal_image != (Image *) NULL)
8643 *image=DestroyImage(*image);
8644 *image=charcoal_image;
8646 CatchException(&(*image)->exception);
8647 XSetCursorState(display,windows,MagickFalse);
8648 if (windows->image.orphan != MagickFalse)
8650 XConfigureImageColormap(display,resource_info,windows,*image);
8651 (void) XConfigureImage(display,resource_info,windows,*image);
8654 case AnnotateCommand:
8657 Annotate the image with text.
8659 status=XAnnotateEditImage(display,resource_info,windows,*image);
8660 if (status == MagickFalse)
8662 XNoticeWidget(display,windows,"Unable to annotate X image",
8663 (*image)->filename);
8673 status=XDrawEditImage(display,resource_info,windows,image);
8674 if (status == MagickFalse)
8676 XNoticeWidget(display,windows,"Unable to draw on the X image",
8677 (*image)->filename);
8687 status=XColorEditImage(display,resource_info,windows,image);
8688 if (status == MagickFalse)
8690 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8691 (*image)->filename);
8701 status=XMatteEditImage(display,resource_info,windows,image);
8702 if (status == MagickFalse)
8704 XNoticeWidget(display,windows,"Unable to matte edit X image",
8705 (*image)->filename);
8710 case CompositeCommand:
8715 status=XCompositeImage(display,resource_info,windows,*image);
8716 if (status == MagickFalse)
8718 XNoticeWidget(display,windows,"Unable to composite X image",
8719 (*image)->filename);
8724 case AddBorderCommand:
8730 geometry[MaxTextExtent] = "6x6";
8733 Query user for border color and geometry.
8735 XColorBrowserWidget(display,windows,"Select",color);
8738 (void) XDialogWidget(display,windows,"Add Border",
8739 "Enter border geometry:",geometry);
8740 if (*geometry == '\0')
8743 Add a border to the image.
8745 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
8746 XSetCursorState(display,windows,MagickTrue);
8747 XCheckRefreshWindows(display,windows);
8748 (void) QueryColorDatabase(color,&(*image)->border_color,
8749 &(*image)->exception);
8750 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8751 &(*image)->exception);
8752 border_image=BorderImage(*image,&page_geometry,&(*image)->exception);
8753 if (border_image != (Image *) NULL)
8755 *image=DestroyImage(*image);
8756 *image=border_image;
8758 CatchException(&(*image)->exception);
8759 XSetCursorState(display,windows,MagickFalse);
8760 if (windows->image.orphan != MagickFalse)
8762 windows->image.window_changes.width=(int) (*image)->columns;
8763 windows->image.window_changes.height=(int) (*image)->rows;
8764 XConfigureImageColormap(display,resource_info,windows,*image);
8765 (void) XConfigureImage(display,resource_info,windows,*image);
8768 case AddFrameCommand:
8777 geometry[MaxTextExtent] = "6x6";
8780 Query user for frame color and geometry.
8782 XColorBrowserWidget(display,windows,"Select",color);
8785 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8787 if (*geometry == '\0')
8790 Surround image with an ornamental border.
8792 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
8793 XSetCursorState(display,windows,MagickTrue);
8794 XCheckRefreshWindows(display,windows);
8795 (void) QueryColorDatabase(color,&(*image)->matte_color,
8796 &(*image)->exception);
8797 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8798 &(*image)->exception);
8799 frame_info.width=page_geometry.width;
8800 frame_info.height=page_geometry.height;
8801 frame_info.outer_bevel=page_geometry.x;
8802 frame_info.inner_bevel=page_geometry.y;
8803 frame_info.x=(ssize_t) frame_info.width;
8804 frame_info.y=(ssize_t) frame_info.height;
8805 frame_info.width=(*image)->columns+2*frame_info.width;
8806 frame_info.height=(*image)->rows+2*frame_info.height;
8807 frame_image=FrameImage(*image,&frame_info,&(*image)->exception);
8808 if (frame_image != (Image *) NULL)
8810 *image=DestroyImage(*image);
8813 CatchException(&(*image)->exception);
8814 XSetCursorState(display,windows,MagickFalse);
8815 if (windows->image.orphan != MagickFalse)
8817 windows->image.window_changes.width=(int) (*image)->columns;
8818 windows->image.window_changes.height=(int) (*image)->rows;
8819 XConfigureImageColormap(display,resource_info,windows,*image);
8820 (void) XConfigureImage(display,resource_info,windows,*image);
8823 case CommentCommand:
8837 unique_file=AcquireUniqueFileResource(image_info->filename);
8838 if (unique_file == -1)
8839 XNoticeWidget(display,windows,"Unable to edit image comment",
8840 image_info->filename);
8841 value=GetImageProperty(*image,"comment");
8842 if (value == (char *) NULL)
8843 unique_file=close(unique_file)-1;
8849 file=fdopen(unique_file,"w");
8850 if (file == (FILE *) NULL)
8852 XNoticeWidget(display,windows,"Unable to edit image comment",
8853 image_info->filename);
8856 for (p=value; *p != '\0'; p++)
8857 (void) fputc((int) *p,file);
8858 (void) fputc('\n',file);
8859 (void) fclose(file);
8861 XSetCursorState(display,windows,MagickTrue);
8862 XCheckRefreshWindows(display,windows);
8863 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
8864 &(*image)->exception);
8865 if (status == MagickFalse)
8866 XNoticeWidget(display,windows,"Unable to edit image comment",
8873 comment=FileToString(image_info->filename,~0UL,&(*image)->exception);
8874 if (comment != (char *) NULL)
8876 (void) SetImageProperty(*image,"comment",comment);
8877 (*image)->taint=MagickTrue;
8880 (void) RelinquishUniqueFileResource(image_info->filename);
8881 XSetCursorState(display,windows,MagickFalse);
8889 XSetCursorState(display,windows,MagickTrue);
8890 XCheckRefreshWindows(display,windows);
8891 (void) AcquireUniqueFilename(filename);
8892 (void) FormatMagickString((*image)->filename,MaxTextExtent,"launch:%s",
8894 status=WriteImage(image_info,*image);
8895 if (status == MagickFalse)
8896 XNoticeWidget(display,windows,"Unable to launch image editor",
8900 nexus=ReadImage(resource_info->image_info,&(*image)->exception);
8901 CatchException(&(*image)->exception);
8902 XClientMessage(display,windows->image.id,windows->im_protocols,
8903 windows->im_next_image,CurrentTime);
8905 (void) RelinquishUniqueFileResource(filename);
8906 XSetCursorState(display,windows,MagickFalse);
8909 case RegionofInterestCommand:
8912 Apply an image processing technique to a region of interest.
8914 (void) XROIImage(display,resource_info,windows,image);
8924 if (windows->magnify.mapped != MagickFalse)
8925 (void) XRaiseWindow(display,windows->magnify.id);
8931 XSetCursorState(display,windows,MagickTrue);
8932 (void) XMapRaised(display,windows->magnify.id);
8933 XSetCursorState(display,windows,MagickFalse);
8937 case ShowPreviewCommand:
8946 preview_type[MaxTextExtent] = "Gamma";
8949 Select preview type from menu.
8951 previews=GetMagickOptions(MagickPreviewOptions);
8952 if (previews == (char **) NULL)
8954 XListBrowserWidget(display,windows,&windows->widget,
8955 (const char **) previews,"Preview",
8956 "Select an enhancement, effect, or F/X:",preview_type);
8957 previews=DestroyStringList(previews);
8958 if (*preview_type == '\0')
8963 XSetCursorState(display,windows,MagickTrue);
8964 XCheckRefreshWindows(display,windows);
8965 image_info->preview_type=(PreviewType)
8966 ParseMagickOption(MagickPreviewOptions,MagickFalse,preview_type);
8967 image_info->group=(ssize_t) windows->image.id;
8968 (void) DeleteImageProperty(*image,"label");
8969 (void) SetImageProperty(*image,"label","Preview");
8970 (void) AcquireUniqueFilename(filename);
8971 (void) FormatMagickString((*image)->filename,MaxTextExtent,"preview:%s",
8973 status=WriteImage(image_info,*image);
8974 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8975 preview_image=ReadImage(image_info,&(*image)->exception);
8976 (void) RelinquishUniqueFileResource(filename);
8977 if (preview_image == (Image *) NULL)
8979 (void) FormatMagickString(preview_image->filename,MaxTextExtent,"show:%s",
8981 status=WriteImage(image_info,preview_image);
8982 preview_image=DestroyImage(preview_image);
8983 if (status == MagickFalse)
8984 XNoticeWidget(display,windows,"Unable to show image preview",
8985 (*image)->filename);
8986 XDelay(display,1500);
8987 XSetCursorState(display,windows,MagickFalse);
8990 case ShowHistogramCommand:
8996 Show image histogram.
8998 XSetCursorState(display,windows,MagickTrue);
8999 XCheckRefreshWindows(display,windows);
9000 image_info->group=(ssize_t) windows->image.id;
9001 (void) DeleteImageProperty(*image,"label");
9002 (void) SetImageProperty(*image,"label","Histogram");
9003 (void) AcquireUniqueFilename(filename);
9004 (void) FormatMagickString((*image)->filename,MaxTextExtent,"histogram:%s",
9006 status=WriteImage(image_info,*image);
9007 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9008 histogram_image=ReadImage(image_info,&(*image)->exception);
9009 (void) RelinquishUniqueFileResource(filename);
9010 if (histogram_image == (Image *) NULL)
9012 (void) FormatMagickString(histogram_image->filename,MaxTextExtent,
9013 "show:%s",filename);
9014 status=WriteImage(image_info,histogram_image);
9015 histogram_image=DestroyImage(histogram_image);
9016 if (status == MagickFalse)
9017 XNoticeWidget(display,windows,"Unable to show histogram",
9018 (*image)->filename);
9019 XDelay(display,1500);
9020 XSetCursorState(display,windows,MagickFalse);
9023 case ShowMatteCommand:
9028 if ((*image)->matte == MagickFalse)
9030 XNoticeWidget(display,windows,
9031 "Image does not have any matte information",(*image)->filename);
9037 XSetCursorState(display,windows,MagickTrue);
9038 XCheckRefreshWindows(display,windows);
9039 image_info->group=(ssize_t) windows->image.id;
9040 (void) DeleteImageProperty(*image,"label");
9041 (void) SetImageProperty(*image,"label","Matte");
9042 (void) AcquireUniqueFilename(filename);
9043 (void) FormatMagickString((*image)->filename,MaxTextExtent,"matte:%s",
9045 status=WriteImage(image_info,*image);
9046 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9047 matte_image=ReadImage(image_info,&(*image)->exception);
9048 (void) RelinquishUniqueFileResource(filename);
9049 if (matte_image == (Image *) NULL)
9051 (void) FormatMagickString(matte_image->filename,MaxTextExtent,"show:%s",
9053 status=WriteImage(image_info,matte_image);
9054 matte_image=DestroyImage(matte_image);
9055 if (status == MagickFalse)
9056 XNoticeWidget(display,windows,"Unable to show matte",
9057 (*image)->filename);
9058 XDelay(display,1500);
9059 XSetCursorState(display,windows,MagickFalse);
9062 case BackgroundCommand:
9067 status=XBackgroundImage(display,resource_info,windows,image);
9068 if (status == MagickFalse)
9070 nexus=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
9071 if (nexus != (Image *) NULL)
9072 XClientMessage(display,windows->image.id,windows->im_protocols,
9073 windows->im_next_image,CurrentTime);
9076 case SlideShowCommand:
9079 delay[MaxTextExtent] = "5";
9082 Display next image after pausing.
9084 (void) XDialogWidget(display,windows,"Slide Show",
9085 "Pause how many 1/100ths of a second between images:",delay);
9088 resource_info->delay=StringToUnsignedLong(delay);
9089 XClientMessage(display,windows->image.id,windows->im_protocols,
9090 windows->im_next_image,CurrentTime);
9093 case PreferencesCommand:
9096 Set user preferences.
9098 status=XPreferencesWidget(display,resource_info,windows);
9099 if (status == MagickFalse)
9101 nexus=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
9102 if (nexus != (Image *) NULL)
9103 XClientMessage(display,windows->image.id,windows->im_protocols,
9104 windows->im_next_image,CurrentTime);
9110 User requested help.
9112 XTextViewWidget(display,resource_info,windows,MagickFalse,
9113 "Help Viewer - Display",DisplayHelp);
9116 case BrowseDocumentationCommand:
9126 Browse the ImageMagick documentation.
9128 root_window=XRootWindow(display,XDefaultScreen(display));
9129 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9130 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9131 if (mozilla_window != (Window) NULL)
9134 command[MaxTextExtent],
9138 Display documentation using Netscape remote control.
9140 url=GetMagickHomeURL();
9141 (void) FormatMagickString(command,MaxTextExtent,
9142 "openurl(%s,new-tab)",url);
9143 url=DestroyString(url);
9144 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9145 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9146 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9147 XSetCursorState(display,windows,MagickFalse);
9150 XSetCursorState(display,windows,MagickTrue);
9151 XCheckRefreshWindows(display,windows);
9152 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9153 &(*image)->exception);
9154 if (status == MagickFalse)
9155 XNoticeWidget(display,windows,"Unable to browse documentation",
9157 XDelay(display,1500);
9158 XSetCursorState(display,windows,MagickFalse);
9161 case VersionCommand:
9163 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9164 GetMagickCopyright());
9167 case SaveToUndoBufferCommand:
9171 (void) XBell(display,0);
9175 image_info=DestroyImageInfo(image_info);
9180 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9184 + X M a g n i f y I m a g e %
9188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9190 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9191 % The magnified portion is displayed in a separate window.
9193 % The format of the XMagnifyImage method is:
9195 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
9197 % A description of each parameter follows:
9199 % o display: Specifies a connection to an X server; returned from
9202 % o windows: Specifies a pointer to a XWindows structure.
9204 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9205 % the entire image is refreshed.
9208 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
9211 text[MaxTextExtent];
9221 Update magnified image until the mouse button is released.
9223 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9227 windows->magnify.x=windows->image.x+x;
9228 windows->magnify.y=windows->image.y+y;
9232 Map and unmap Info widget as text cursor crosses its boundaries.
9234 if (windows->info.mapped != MagickFalse)
9236 if ((x < (int) (windows->info.x+windows->info.width)) &&
9237 (y < (int) (windows->info.y+windows->info.height)))
9238 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9241 if ((x > (int) (windows->info.x+windows->info.width)) ||
9242 (y > (int) (windows->info.y+windows->info.height)))
9243 (void) XMapWindow(display,windows->info.id);
9244 if (windows->info.mapped != MagickFalse)
9247 Display pointer position.
9249 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
9250 windows->magnify.x,windows->magnify.y);
9251 XInfoWidget(display,windows,text);
9254 Wait for next event.
9256 XScreenEvent(display,windows,event);
9257 switch (event->type)
9264 User has finished magnifying image.
9283 Check boundary conditions.
9288 if (x >= (int) windows->image.width)
9289 x=(int) windows->image.width-1;
9293 if (y >= (int) windows->image.height)
9294 y=(int) windows->image.height-1;
9295 } while ((state & ExitState) == 0);
9297 Display magnified image.
9299 XSetCursorState(display,windows,MagickFalse);
9303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9307 + X M a g n i f y W i n d o w C o m m a n d %
9311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9313 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9314 % pixel as specified by the key symbol.
9316 % The format of the XMagnifyWindowCommand method is:
9318 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9319 % const MagickStatusType state,const KeySym key_symbol)
9321 % A description of each parameter follows:
9323 % o display: Specifies a connection to an X server; returned from
9326 % o windows: Specifies a pointer to a XWindows structure.
9328 % o state: key mask.
9330 % o key_symbol: Specifies a KeySym which indicates which side of the image
9334 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9335 const MagickStatusType state,const KeySym key_symbol)
9341 User specified a magnify factor or position.
9344 if ((state & Mod1Mask) != 0)
9346 switch ((int) key_symbol)
9350 (void) XWithdrawWindow(display,windows->magnify.id,
9351 windows->magnify.screen);
9357 windows->magnify.x=(int) windows->image.width/2;
9358 windows->magnify.y=(int) windows->image.height/2;
9364 if (windows->magnify.x > 0)
9365 windows->magnify.x-=quantum;
9371 if (windows->magnify.y > 0)
9372 windows->magnify.y-=quantum;
9378 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9379 windows->magnify.x+=quantum;
9385 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9386 windows->magnify.y+=quantum;
9400 windows->magnify.data=(key_symbol-XK_0);
9414 windows->magnify.data=(key_symbol-XK_KP_0);
9420 XMakeMagnifyImage(display,windows);
9424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9428 + X M a k e P a n I m a g e %
9432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9434 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9437 % The format of the XMakePanImage method is:
9439 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9440 % XWindows *windows,Image *image)
9442 % A description of each parameter follows:
9444 % o display: Specifies a connection to an X server; returned from
9447 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9449 % o windows: Specifies a pointer to a XWindows structure.
9451 % o image: the image.
9454 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9455 XWindows *windows,Image *image)
9461 Create and display image for panning icon.
9463 XSetCursorState(display,windows,MagickTrue);
9464 XCheckRefreshWindows(display,windows);
9465 windows->pan.x=windows->image.x;
9466 windows->pan.y=windows->image.y;
9467 status=XMakeImage(display,resource_info,&windows->pan,image,
9468 windows->pan.width,windows->pan.height);
9469 if (status == MagickFalse)
9470 ThrowXWindowFatalException(XServerError,image->exception.reason,
9471 image->exception.description);
9472 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9473 windows->pan.pixmap);
9474 (void) XClearWindow(display,windows->pan.id);
9475 XDrawPanRectangle(display,windows);
9476 XSetCursorState(display,windows,MagickFalse);
9480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9484 + X M a t t a E d i t I m a g e %
9488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9490 % XMatteEditImage() allows the user to interactively change the Matte channel
9491 % of an image. If the image is PseudoClass it is promoted to DirectClass
9492 % before the matte information is stored.
9494 % The format of the XMatteEditImage method is:
9496 % MagickBooleanType XMatteEditImage(Display *display,
9497 % XResourceInfo *resource_info,XWindows *windows,Image **image)
9499 % A description of each parameter follows:
9501 % o display: Specifies a connection to an X server; returned from
9504 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9506 % o windows: Specifies a pointer to a XWindows structure.
9508 % o image: the image; returned from ReadImage.
9511 static MagickBooleanType XMatteEditImage(Display *display,
9512 XResourceInfo *resource_info,XWindows *windows,Image **image)
9515 matte[MaxTextExtent] = "0";
9530 static const ModeType
9531 MatteEditCommands[] =
9534 MatteEditBorderCommand,
9535 MatteEditFuzzCommand,
9536 MatteEditValueCommand,
9537 MatteEditUndoCommand,
9538 MatteEditHelpCommand,
9539 MatteEditDismissCommand
9543 method = PointMethod;
9546 border_color = { 0, 0, 0, 0, 0, 0 };
9549 command[MaxTextExtent],
9550 text[MaxTextExtent];
9566 register PixelPacket
9582 (void) CloneString(&windows->command.name,"Matte Edit");
9583 windows->command.data=4;
9584 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9585 (void) XMapRaised(display,windows->command.id);
9586 XClientMessage(display,windows->image.id,windows->im_protocols,
9587 windows->im_update_widget,CurrentTime);
9591 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9592 resource_info->background_color,resource_info->foreground_color);
9593 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9595 Track pointer until button 1 is pressed.
9597 XQueryPosition(display,windows->image.id,&x,&y);
9598 (void) XSelectInput(display,windows->image.id,
9599 windows->image.attributes.event_mask | PointerMotionMask);
9603 if (windows->info.mapped != MagickFalse)
9606 Display pointer position.
9608 (void) FormatMagickString(text,MaxTextExtent," %+d%+d ",
9609 x+windows->image.x,y+windows->image.y);
9610 XInfoWidget(display,windows,text);
9613 Wait for next event.
9615 XScreenEvent(display,windows,&event);
9616 if (event.xany.window == windows->command.id)
9619 Select a command from the Command widget.
9621 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9624 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9627 switch (MatteEditCommands[id])
9629 case MatteEditMethod:
9635 Select a method from the pop-up menu.
9637 methods=GetMagickOptions(MagickMethodOptions);
9638 if (methods == (char **) NULL)
9640 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9641 (const char **) methods,command);
9643 method=(PaintMethod) ParseMagickOption(MagickMethodOptions,
9644 MagickFalse,methods[entry]);
9645 methods=DestroyStringList(methods);
9648 case MatteEditBorderCommand:
9651 *ColorMenu[MaxNumberPens];
9657 Initialize menu selections.
9659 for (i=0; i < (int) (MaxNumberPens-2); i++)
9660 ColorMenu[i]=resource_info->pen_colors[i];
9661 ColorMenu[MaxNumberPens-2]="Browser...";
9662 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9664 Select a pen color from the pop-up menu.
9666 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9667 (const char **) ColorMenu,command);
9670 if (pen_number == (MaxNumberPens-2))
9673 color_name[MaxTextExtent] = "gray";
9676 Select a pen color from a dialog.
9678 resource_info->pen_colors[pen_number]=color_name;
9679 XColorBrowserWidget(display,windows,"Select",color_name);
9680 if (*color_name == '\0')
9686 (void) XParseColor(display,windows->map_info->colormap,
9687 resource_info->pen_colors[pen_number],&border_color);
9690 case MatteEditFuzzCommand:
9693 fuzz[MaxTextExtent];
9708 Select a command from the pop-up menu.
9710 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9716 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*QuantumRange+
9720 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9721 (void) XDialogWidget(display,windows,"Ok",
9722 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9725 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9726 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
9729 case MatteEditValueCommand:
9732 message[MaxTextExtent];
9744 Select a command from the pop-up menu.
9746 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9752 (void) FormatMagickString(matte,MaxTextExtent,QuantumFormat,
9754 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9755 (void) FormatMagickString(matte,MaxTextExtent,QuantumFormat,
9756 (Quantum) TransparentOpacity);
9759 (void) FormatMagickString(message,MaxTextExtent,
9760 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9762 (void) XDialogWidget(display,windows,"Matte",message,matte);
9767 case MatteEditUndoCommand:
9769 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9773 case MatteEditHelpCommand:
9775 XTextViewWidget(display,resource_info,windows,MagickFalse,
9776 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9779 case MatteEditDismissCommand:
9791 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9798 if (event.xbutton.button != Button1)
9800 if ((event.xbutton.window != windows->image.id) &&
9801 (event.xbutton.window != windows->magnify.id))
9808 (void) XMagickCommand(display,resource_info,windows,
9809 SaveToUndoBufferCommand,image);
9810 state|=UpdateConfigurationState;
9815 if (event.xbutton.button != Button1)
9817 if ((event.xbutton.window != windows->image.id) &&
9818 (event.xbutton.window != windows->magnify.id))
9821 Update colormap information.
9825 XConfigureImageColormap(display,resource_info,windows,*image);
9826 (void) XConfigureImage(display,resource_info,windows,*image);
9827 XInfoWidget(display,windows,text);
9828 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9829 state&=(~UpdateConfigurationState);
9837 command[MaxTextExtent];
9842 if (event.xkey.window == windows->magnify.id)
9847 window=windows->magnify.id;
9848 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
9850 if (event.xkey.window != windows->image.id)
9853 Respond to a user key press.
9855 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
9856 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9857 switch ((int) key_symbol)
9871 XTextViewWidget(display,resource_info,windows,MagickFalse,
9872 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9877 (void) XBell(display,0);
9886 Map and unmap Info widget as cursor crosses its boundaries.
9890 if (windows->info.mapped != MagickFalse)
9892 if ((x < (int) (windows->info.x+windows->info.width)) &&
9893 (y < (int) (windows->info.y+windows->info.height)))
9894 (void) XWithdrawWindow(display,windows->info.id,
9895 windows->info.screen);
9898 if ((x > (int) (windows->info.x+windows->info.width)) ||
9899 (y > (int) (windows->info.y+windows->info.height)))
9900 (void) XMapWindow(display,windows->info.id);
9906 if (event.xany.window == windows->magnify.id)
9908 x=windows->magnify.x-windows->image.x;
9909 y=windows->magnify.y-windows->image.y;
9913 if ((state & UpdateConfigurationState) != 0)
9923 Matte edit is relative to image configuration.
9925 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
9927 XPutPixel(windows->image.ximage,x_offset,y_offset,
9928 windows->pixel_info->background_color.pixel);
9929 width=(unsigned int) (*image)->columns;
9930 height=(unsigned int) (*image)->rows;
9933 if (windows->image.crop_geometry != (char *) NULL)
9934 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
9937 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
9939 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
9940 if ((x_offset < 0) || (y_offset < 0))
9942 if ((x_offset >= (int) (*image)->columns) ||
9943 (y_offset >= (int) (*image)->rows))
9945 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
9946 return(MagickFalse);
9947 (*image)->matte=MagickTrue;
9948 exception=(&(*image)->exception);
9955 Update matte information using point algorithm.
9957 q=GetAuthenticPixels(*image,x_offset,y_offset,1,1,exception);
9958 if (q == (PixelPacket *) NULL)
9960 q->opacity=(Quantum) StringToLong(matte);
9961 (void) SyncAuthenticPixels(*image,exception);
9970 Update matte information using replace algorithm.
9972 (void) GetOneVirtualPixel(*image,x_offset,y_offset,&target,
9974 for (y=0; y < (ssize_t) (*image)->rows; y++)
9976 q=GetAuthenticPixels(*image,0,y,(*image)->columns,1,
9977 &(*image)->exception);
9978 if (q == (PixelPacket *) NULL)
9980 for (x=0; x < (int) (*image)->columns; x++)
9982 if (IsColorSimilar(*image,q,&target))
9983 q->opacity=(Quantum) StringToLong(matte);
9986 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
9991 case FloodfillMethod:
9992 case FillToBorderMethod:
10001 Update matte information using floodfill algorithm.
10003 (void) GetOneVirtualMagickPixel(*image,x_offset,y_offset,&target,
10005 if (method == FillToBorderMethod)
10007 target.red=(MagickRealType)
10008 ScaleShortToQuantum(border_color.red);
10009 target.green=(MagickRealType)
10010 ScaleShortToQuantum(border_color.green);
10011 target.blue=(MagickRealType)
10012 ScaleShortToQuantum(border_color.blue);
10014 draw_info=CloneDrawInfo(resource_info->image_info,
10015 (DrawInfo *) NULL);
10016 draw_info->fill.opacity=ClampToQuantum(StringToDouble(matte));
10017 (void) FloodfillPaintImage(*image,OpacityChannel,draw_info,&target,
10018 x_offset,y_offset,method == FloodfillMethod ? MagickFalse :
10020 draw_info=DestroyDrawInfo(draw_info);
10026 Update matte information using reset algorithm.
10028 if (SetImageStorageClass(*image,DirectClass) == MagickFalse)
10029 return(MagickFalse);
10030 for (y=0; y < (ssize_t) (*image)->rows; y++)
10032 q=QueueAuthenticPixels(*image,0,y,(*image)->columns,1,exception);
10033 if (q == (PixelPacket *) NULL)
10035 for (x=0; x < (int) (*image)->columns; x++)
10037 q->opacity=(Quantum) StringToLong(matte);
10040 if (SyncAuthenticPixels(*image,exception) == MagickFalse)
10043 if (StringToLong(matte) == OpaqueOpacity)
10044 (*image)->matte=MagickFalse;
10048 state&=(~UpdateConfigurationState);
10050 } while ((state & ExitState) == 0);
10051 (void) XSelectInput(display,windows->image.id,
10052 windows->image.attributes.event_mask);
10053 XSetCursorState(display,windows,MagickFalse);
10054 (void) XFreeCursor(display,cursor);
10055 return(MagickTrue);
10059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10063 + X O p e n I m a g e %
10067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10069 % XOpenImage() loads an image from a file.
10071 % The format of the XOpenImage method is:
10073 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10074 % XWindows *windows,const unsigned int command)
10076 % A description of each parameter follows:
10078 % o display: Specifies a connection to an X server; returned from
10081 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10083 % o windows: Specifies a pointer to a XWindows structure.
10085 % o command: A value other than zero indicates that the file is selected
10086 % from the command line argument list.
10089 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10090 XWindows *windows,const MagickBooleanType command)
10105 filename[MaxTextExtent] = "\0";
10108 Request file name from user.
10110 if (command == MagickFalse)
10111 XFileBrowserWidget(display,windows,"Open",filename);
10127 Select next image from the command line.
10129 status=XGetCommand(display,windows->image.id,&files,&count);
10132 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10133 return((Image *) NULL);
10135 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10136 if (filelist == (char **) NULL)
10138 ThrowXWindowFatalException(ResourceLimitError,
10139 "MemoryAllocationFailed","...");
10140 (void) XFreeStringList(files);
10141 return((Image *) NULL);
10144 for (i=1; i < count; i++)
10145 if (*files[i] != '-')
10146 filelist[j++]=files[i];
10147 filelist[j]=(char *) NULL;
10148 XListBrowserWidget(display,windows,&windows->widget,
10149 (const char **) filelist,"Load","Select Image to Load:",filename);
10150 filelist=(char **) RelinquishMagickMemory(filelist);
10151 (void) XFreeStringList(files);
10153 if (*filename == '\0')
10154 return((Image *) NULL);
10155 image_info=CloneImageInfo(resource_info->image_info);
10156 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10158 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10159 exception=AcquireExceptionInfo();
10160 (void) SetImageInfo(image_info,0,exception);
10161 if (LocaleCompare(image_info->magick,"X") == 0)
10164 seconds[MaxTextExtent];
10167 User may want to delay the X server screen grab.
10169 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10170 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10172 if (*seconds == '\0')
10173 return((Image *) NULL);
10174 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10176 magick_info=GetMagickInfo(image_info->magick,exception);
10177 if ((magick_info != (const MagickInfo *) NULL) &&
10178 (magick_info->raw != MagickFalse))
10181 geometry[MaxTextExtent];
10184 Request image size from the user.
10186 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10187 if (image_info->size != (char *) NULL)
10188 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10189 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10191 (void) CloneString(&image_info->size,geometry);
10196 XSetCursorState(display,windows,MagickTrue);
10197 XCheckRefreshWindows(display,windows);
10198 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10199 nexus=ReadImage(image_info,exception);
10200 CatchException(exception);
10201 XSetCursorState(display,windows,MagickFalse);
10202 if (nexus != (Image *) NULL)
10203 XClientMessage(display,windows->image.id,windows->im_protocols,
10204 windows->im_next_image,CurrentTime);
10212 Unknown image format.
10214 text=FileToString(filename,~0,exception);
10215 if (text == (char *) NULL)
10216 return((Image *) NULL);
10217 textlist=StringToList(text);
10218 if (textlist != (char **) NULL)
10221 title[MaxTextExtent];
10226 (void) FormatMagickString(title,MaxTextExtent,
10227 "Unknown format: %s",filename);
10228 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10229 (const char **) textlist);
10230 for (i=0; textlist[i] != (char *) NULL; i++)
10231 textlist[i]=DestroyString(textlist[i]);
10232 textlist=(char **) RelinquishMagickMemory(textlist);
10234 text=DestroyString(text);
10236 exception=DestroyExceptionInfo(exception);
10237 image_info=DestroyImageInfo(image_info);
10242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10246 + X P a n I m a g e %
10250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10252 % XPanImage() pans the image until the mouse button is released.
10254 % The format of the XPanImage method is:
10256 % void XPanImage(Display *display,XWindows *windows,XEvent *event)
10258 % A description of each parameter follows:
10260 % o display: Specifies a connection to an X server; returned from
10263 % o windows: Specifies a pointer to a XWindows structure.
10265 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10266 % the entire image is refreshed.
10269 static void XPanImage(Display *display,XWindows *windows,XEvent *event)
10272 text[MaxTextExtent];
10290 if ((windows->image.ximage->width > (int) windows->image.width) &&
10291 (windows->image.ximage->height > (int) windows->image.height))
10292 cursor=XCreateFontCursor(display,XC_fleur);
10294 if (windows->image.ximage->width > (int) windows->image.width)
10295 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10297 if (windows->image.ximage->height > (int) windows->image.height)
10298 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10300 cursor=XCreateFontCursor(display,XC_arrow);
10301 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10303 Pan image as pointer moves until the mouse button is released.
10305 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10306 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10307 pan_info.width=windows->pan.width*windows->image.width/
10308 windows->image.ximage->width;
10309 pan_info.height=windows->pan.height*windows->image.height/
10310 windows->image.ximage->height;
10313 state=UpdateConfigurationState;
10316 switch (event->type)
10321 User choose an initial pan location.
10323 pan_info.x=event->xbutton.x;
10324 pan_info.y=event->xbutton.y;
10325 state|=UpdateConfigurationState;
10328 case ButtonRelease:
10331 User has finished panning the image.
10333 pan_info.x=event->xbutton.x;
10334 pan_info.y=event->xbutton.y;
10335 state|=UpdateConfigurationState | ExitState;
10340 pan_info.x=event->xmotion.x;
10341 pan_info.y=event->xmotion.y;
10342 state|=UpdateConfigurationState;
10347 if ((state & UpdateConfigurationState) != 0)
10350 Check boundary conditions.
10352 if (pan_info.x < (int) (pan_info.width/2))
10355 pan_info.x=(int) (x_factor*(pan_info.x-(pan_info.width/2)));
10356 if (pan_info.x < 0)
10359 if ((int) (pan_info.x+windows->image.width) >
10360 windows->image.ximage->width)
10361 pan_info.x=(ssize_t)
10362 (windows->image.ximage->width-windows->image.width);
10363 if (pan_info.y < (ssize_t) (pan_info.height/2))
10366 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10367 if (pan_info.y < 0)
10370 if ((int) (pan_info.y+windows->image.height) >
10371 windows->image.ximage->height)
10372 pan_info.y=(ssize_t)
10373 (windows->image.ximage->height-windows->image.height);
10374 if ((windows->image.x != (int) pan_info.x) ||
10375 (windows->image.y != (int) pan_info.y))
10378 Display image pan offset.
10380 windows->image.x=(int) pan_info.x;
10381 windows->image.y=(int) pan_info.y;
10382 (void) FormatMagickString(text,MaxTextExtent," %ux%u%+d%+d ",
10383 windows->image.width,windows->image.height,windows->image.x,
10385 XInfoWidget(display,windows,text);
10387 Refresh Image window.
10389 XDrawPanRectangle(display,windows);
10390 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10392 state&=(~UpdateConfigurationState);
10395 Wait for next event.
10397 if ((state & ExitState) == 0)
10398 XScreenEvent(display,windows,event);
10399 } while ((state & ExitState) == 0);
10403 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10404 (void) XFreeCursor(display,cursor);
10405 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10413 + X P a s t e I m a g e %
10417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10419 % XPasteImage() pastes an image previously saved with XCropImage in the X
10420 % window image at a location the user chooses with the pointer.
10422 % The format of the XPasteImage method is:
10424 % MagickBooleanType XPasteImage(Display *display,
10425 % XResourceInfo *resource_info,XWindows *windows,Image *image)
10427 % A description of each parameter follows:
10429 % o display: Specifies a connection to an X server; returned from
10432 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10434 % o windows: Specifies a pointer to a XWindows structure.
10436 % o image: the image; returned from ReadImage.
10439 static MagickBooleanType XPasteImage(Display *display,
10440 XResourceInfo *resource_info,XWindows *windows,Image *image)
10451 static const ModeType
10454 PasteOperatorsCommand,
10456 PasteDismissCommand
10459 static CompositeOperator
10460 compose = CopyCompositeOp;
10463 text[MaxTextExtent];
10497 if (resource_info->copy_image == (Image *) NULL)
10498 return(MagickFalse);
10499 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,
10500 &image->exception);
10502 Map Command widget.
10504 (void) CloneString(&windows->command.name,"Paste");
10505 windows->command.data=1;
10506 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10507 (void) XMapRaised(display,windows->command.id);
10508 XClientMessage(display,windows->image.id,windows->im_protocols,
10509 windows->im_update_widget,CurrentTime);
10511 Track pointer until button 1 is pressed.
10513 XSetCursorState(display,windows,MagickFalse);
10514 XQueryPosition(display,windows->image.id,&x,&y);
10515 (void) XSelectInput(display,windows->image.id,
10516 windows->image.attributes.event_mask | PointerMotionMask);
10517 paste_info.x=windows->image.x+x;
10518 paste_info.y=windows->image.y+y;
10519 paste_info.width=0;
10520 paste_info.height=0;
10521 cursor=XCreateFontCursor(display,XC_ul_angle);
10522 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10523 state=DefaultState;
10526 if (windows->info.mapped != MagickFalse)
10529 Display pointer position.
10531 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
10532 (long) paste_info.x,(long) paste_info.y);
10533 XInfoWidget(display,windows,text);
10535 highlight_info=paste_info;
10536 highlight_info.x=paste_info.x-windows->image.x;
10537 highlight_info.y=paste_info.y-windows->image.y;
10538 XHighlightRectangle(display,windows->image.id,
10539 windows->image.highlight_context,&highlight_info);
10541 Wait for next event.
10543 XScreenEvent(display,windows,&event);
10544 XHighlightRectangle(display,windows->image.id,
10545 windows->image.highlight_context,&highlight_info);
10546 if (event.xany.window == windows->command.id)
10549 Select a command from the Command widget.
10551 id=XCommandWidget(display,windows,PasteMenu,&event);
10554 switch (PasteCommands[id])
10556 case PasteOperatorsCommand:
10559 command[MaxTextExtent],
10563 Select a command from the pop-up menu.
10565 operators=GetMagickOptions(MagickComposeOptions);
10566 if (operators == (char **) NULL)
10568 entry=XMenuWidget(display,windows,PasteMenu[id],
10569 (const char **) operators,command);
10571 compose=(CompositeOperator) ParseMagickOption(
10572 MagickComposeOptions,MagickFalse,operators[entry]);
10573 operators=DestroyStringList(operators);
10576 case PasteHelpCommand:
10578 XTextViewWidget(display,resource_info,windows,MagickFalse,
10579 "Help Viewer - Image Composite",ImagePasteHelp);
10582 case PasteDismissCommand:
10587 state|=EscapeState;
10596 switch (event.type)
10600 if (image->debug != MagickFalse)
10601 (void) LogMagickEvent(X11Event,GetMagickModule(),
10602 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10603 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10604 if (event.xbutton.button != Button1)
10606 if (event.xbutton.window != windows->image.id)
10609 Paste rectangle is relative to image configuration.
10611 width=(unsigned int) image->columns;
10612 height=(unsigned int) image->rows;
10615 if (windows->image.crop_geometry != (char *) NULL)
10616 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10618 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10619 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10620 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10621 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10622 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10623 paste_info.x=windows->image.x+event.xbutton.x;
10624 paste_info.y=windows->image.y+event.xbutton.y;
10627 case ButtonRelease:
10629 if (image->debug != MagickFalse)
10630 (void) LogMagickEvent(X11Event,GetMagickModule(),
10631 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10632 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10633 if (event.xbutton.button != Button1)
10635 if (event.xbutton.window != windows->image.id)
10637 if ((paste_info.width != 0) && (paste_info.height != 0))
10640 User has selected the location of the paste image.
10642 paste_info.x=windows->image.x+event.xbutton.x;
10643 paste_info.y=windows->image.y+event.xbutton.y;
10653 command[MaxTextExtent];
10661 if (event.xkey.window != windows->image.id)
10664 Respond to a user key press.
10666 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10667 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10668 *(command+length)='\0';
10669 if (image->debug != MagickFalse)
10670 (void) LogMagickEvent(X11Event,GetMagickModule(),
10671 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10672 switch ((int) key_symbol)
10680 paste_image=DestroyImage(paste_image);
10681 state|=EscapeState;
10688 (void) XSetFunction(display,windows->image.highlight_context,
10690 XTextViewWidget(display,resource_info,windows,MagickFalse,
10691 "Help Viewer - Image Composite",ImagePasteHelp);
10692 (void) XSetFunction(display,windows->image.highlight_context,
10698 (void) XBell(display,0);
10707 Map and unmap Info widget as text cursor crosses its boundaries.
10711 if (windows->info.mapped != MagickFalse)
10713 if ((x < (int) (windows->info.x+windows->info.width)) &&
10714 (y < (int) (windows->info.y+windows->info.height)))
10715 (void) XWithdrawWindow(display,windows->info.id,
10716 windows->info.screen);
10719 if ((x > (int) (windows->info.x+windows->info.width)) ||
10720 (y > (int) (windows->info.y+windows->info.height)))
10721 (void) XMapWindow(display,windows->info.id);
10722 paste_info.x=windows->image.x+x;
10723 paste_info.y=windows->image.y+y;
10728 if (image->debug != MagickFalse)
10729 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10734 } while ((state & ExitState) == 0);
10735 (void) XSelectInput(display,windows->image.id,
10736 windows->image.attributes.event_mask);
10737 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10738 XSetCursorState(display,windows,MagickFalse);
10739 (void) XFreeCursor(display,cursor);
10740 if ((state & EscapeState) != 0)
10741 return(MagickTrue);
10743 Image pasting is relative to image configuration.
10745 XSetCursorState(display,windows,MagickTrue);
10746 XCheckRefreshWindows(display,windows);
10747 width=(unsigned int) image->columns;
10748 height=(unsigned int) image->rows;
10751 if (windows->image.crop_geometry != (char *) NULL)
10752 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10753 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10755 paste_info.x=(int) (scale_factor*paste_info.x+0.5);
10756 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10757 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10759 paste_info.y=(int) (scale_factor*paste_info.y*scale_factor+0.5);
10760 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10762 Paste image with X Image window.
10764 (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y);
10765 paste_image=DestroyImage(paste_image);
10766 XSetCursorState(display,windows,MagickFalse);
10768 Update image colormap.
10770 XConfigureImageColormap(display,resource_info,windows,image);
10771 (void) XConfigureImage(display,resource_info,windows,image);
10772 return(MagickTrue);
10776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10780 + X P r i n t I m a g e %
10784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10786 % XPrintImage() prints an image to a Postscript printer.
10788 % The format of the XPrintImage method is:
10790 % MagickBooleanType XPrintImage(Display *display,
10791 % XResourceInfo *resource_info,XWindows *windows,Image *image)
10793 % A description of each parameter follows:
10795 % o display: Specifies a connection to an X server; returned from
10798 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10800 % o windows: Specifies a pointer to a XWindows structure.
10802 % o image: the image.
10805 static MagickBooleanType XPrintImage(Display *display,
10806 XResourceInfo *resource_info,XWindows *windows,Image *image)
10809 filename[MaxTextExtent],
10810 geometry[MaxTextExtent];
10822 Request Postscript page geometry from user.
10824 image_info=CloneImageInfo(resource_info->image_info);
10825 (void) FormatMagickString(geometry,MaxTextExtent,"Letter");
10826 if (image_info->page != (char *) NULL)
10827 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
10828 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
10829 "Select Postscript Page Geometry:",geometry);
10830 if (*geometry == '\0')
10831 return(MagickTrue);
10832 image_info->page=GetPageGeometry(geometry);
10834 Apply image transforms.
10836 XSetCursorState(display,windows,MagickTrue);
10837 XCheckRefreshWindows(display,windows);
10838 print_image=CloneImage(image,0,0,MagickTrue,&image->exception);
10839 if (print_image == (Image *) NULL)
10840 return(MagickFalse);
10841 (void) FormatMagickString(geometry,MaxTextExtent,"%dx%d!",
10842 windows->image.ximage->width,windows->image.ximage->height);
10843 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry);
10847 (void) AcquireUniqueFilename(filename);
10848 (void) FormatMagickString(print_image->filename,MaxTextExtent,"print:%s",
10850 status=WriteImage(image_info,print_image);
10851 (void) RelinquishUniqueFileResource(filename);
10852 print_image=DestroyImage(print_image);
10853 image_info=DestroyImageInfo(image_info);
10854 XSetCursorState(display,windows,MagickFalse);
10855 return(status != 0 ? MagickTrue : MagickFalse);
10859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10863 + X R O I I m a g e %
10867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10869 % XROIImage() applies an image processing technique to a region of interest.
10871 % The format of the XROIImage method is:
10873 % MagickBooleanType XROIImage(Display *display,
10874 % XResourceInfo *resource_info,XWindows *windows,Image **image)
10876 % A description of each parameter follows:
10878 % o display: Specifies a connection to an X server; returned from
10881 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10883 % o windows: Specifies a pointer to a XWindows structure.
10885 % o image: the image; returned from ReadImage.
10888 static MagickBooleanType XROIImage(Display *display,
10889 XResourceInfo *resource_info,XWindows *windows,Image **image)
10891 #define ApplyMenus 7
10941 "Contrast Stretch...",
10942 "Sigmoidal Contrast...",
10976 "Charcoal Draw...",
10979 *MiscellanyMenu[] =
10990 **Menus[ApplyMenus] =
11001 static const CommandType
11024 TransformCommands[] =
11028 RotateRightCommand,
11031 EnhanceCommands[] =
11039 ContrastStretchCommand,
11040 SigmoidalContrastCommand,
11048 EffectsCommands[] =
11052 ReduceNoiseCommand,
11071 CharcoalDrawCommand
11073 MiscellanyCommands[] =
11077 ShowPreviewCommand,
11078 ShowHistogramCommand,
11087 static const CommandType
11088 *Commands[ApplyMenus] =
11100 command[MaxTextExtent],
11101 text[MaxTextExtent];
11121 MagickProgressMonitor
11140 Map Command widget.
11142 (void) CloneString(&windows->command.name,"ROI");
11143 windows->command.data=0;
11144 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11145 (void) XMapRaised(display,windows->command.id);
11146 XClientMessage(display,windows->image.id,windows->im_protocols,
11147 windows->im_update_widget,CurrentTime);
11149 Track pointer until button 1 is pressed.
11151 XQueryPosition(display,windows->image.id,&x,&y);
11152 (void) XSelectInput(display,windows->image.id,
11153 windows->image.attributes.event_mask | PointerMotionMask);
11154 roi_info.x=windows->image.x+x;
11155 roi_info.y=windows->image.y+y;
11158 cursor=XCreateFontCursor(display,XC_fleur);
11159 state=DefaultState;
11162 if (windows->info.mapped != MagickFalse)
11165 Display pointer position.
11167 (void) FormatMagickString(text,MaxTextExtent," %+ld%+ld ",
11168 (long) roi_info.x,(long) roi_info.y);
11169 XInfoWidget(display,windows,text);
11172 Wait for next event.
11174 XScreenEvent(display,windows,&event);
11175 if (event.xany.window == windows->command.id)
11178 Select a command from the Command widget.
11180 id=XCommandWidget(display,windows,ROIMenu,&event);
11183 switch (ROICommands[id])
11185 case ROIHelpCommand:
11187 XTextViewWidget(display,resource_info,windows,MagickFalse,
11188 "Help Viewer - Region of Interest",ImageROIHelp);
11191 case ROIDismissCommand:
11196 state|=EscapeState;
11205 switch (event.type)
11209 if (event.xbutton.button != Button1)
11211 if (event.xbutton.window != windows->image.id)
11214 Note first corner of region of interest rectangle-- exit loop.
11216 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11217 roi_info.x=windows->image.x+event.xbutton.x;
11218 roi_info.y=windows->image.y+event.xbutton.y;
11222 case ButtonRelease:
11231 if (event.xkey.window != windows->image.id)
11234 Respond to a user key press.
11236 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11237 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11238 switch ((int) key_symbol)
11246 state|=EscapeState;
11253 XTextViewWidget(display,resource_info,windows,MagickFalse,
11254 "Help Viewer - Region of Interest",ImageROIHelp);
11259 (void) XBell(display,0);
11268 Map and unmap Info widget as text cursor crosses its boundaries.
11272 if (windows->info.mapped != MagickFalse)
11274 if ((x < (int) (windows->info.x+windows->info.width)) &&
11275 (y < (int) (windows->info.y+windows->info.height)))
11276 (void) XWithdrawWindow(display,windows->info.id,
11277 windows->info.screen);
11280 if ((x > (int) (windows->info.x+windows->info.width)) ||
11281 (y > (int) (windows->info.y+windows->info.height)))
11282 (void) XMapWindow(display,windows->info.id);
11283 roi_info.x=windows->image.x+x;
11284 roi_info.y=windows->image.y+y;
11290 } while ((state & ExitState) == 0);
11291 (void) XSelectInput(display,windows->image.id,
11292 windows->image.attributes.event_mask);
11293 if ((state & EscapeState) != 0)
11296 User want to exit without region of interest.
11298 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11299 (void) XFreeCursor(display,cursor);
11300 return(MagickTrue);
11302 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11306 Size rectangle as pointer moves until the mouse button is released.
11308 x=(int) roi_info.x;
11309 y=(int) roi_info.y;
11312 state=DefaultState;
11315 highlight_info=roi_info;
11316 highlight_info.x=roi_info.x-windows->image.x;
11317 highlight_info.y=roi_info.y-windows->image.y;
11318 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11321 Display info and draw region of interest rectangle.
11323 if (windows->info.mapped == MagickFalse)
11324 (void) XMapWindow(display,windows->info.id);
11325 (void) FormatMagickString(text,MaxTextExtent,
11326 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11327 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11328 XInfoWidget(display,windows,text);
11329 XHighlightRectangle(display,windows->image.id,
11330 windows->image.highlight_context,&highlight_info);
11333 if (windows->info.mapped != MagickFalse)
11334 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11336 Wait for next event.
11338 XScreenEvent(display,windows,&event);
11339 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11340 XHighlightRectangle(display,windows->image.id,
11341 windows->image.highlight_context,&highlight_info);
11342 switch (event.type)
11346 roi_info.x=windows->image.x+event.xbutton.x;
11347 roi_info.y=windows->image.y+event.xbutton.y;
11350 case ButtonRelease:
11353 User has committed to region of interest rectangle.
11355 roi_info.x=windows->image.x+event.xbutton.x;
11356 roi_info.y=windows->image.y+event.xbutton.y;
11357 XSetCursorState(display,windows,MagickFalse);
11359 if (LocaleCompare(windows->command.name,"Apply") == 0)
11361 (void) CloneString(&windows->command.name,"Apply");
11362 windows->command.data=ApplyMenus;
11363 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11370 roi_info.x=windows->image.x+event.xmotion.x;
11371 roi_info.y=windows->image.y+event.xmotion.y;
11376 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11377 ((state & ExitState) != 0))
11380 Check boundary conditions.
11382 if (roi_info.x < 0)
11385 if (roi_info.x > (int) windows->image.ximage->width)
11386 roi_info.x=windows->image.ximage->width;
11387 if ((int) roi_info.x < x)
11388 roi_info.width=(unsigned int) (x-roi_info.x);
11391 roi_info.width=(unsigned int) (roi_info.x-x);
11394 if (roi_info.y < 0)
11397 if (roi_info.y > (int) windows->image.ximage->height)
11398 roi_info.y=windows->image.ximage->height;
11399 if ((int) roi_info.y < y)
11400 roi_info.height=(unsigned int) (y-roi_info.y);
11403 roi_info.height=(unsigned int) (roi_info.y-y);
11407 } while ((state & ExitState) == 0);
11409 Wait for user to grab a corner of the rectangle or press return.
11411 state=DefaultState;
11412 command_type=NullCommand;
11413 (void) XMapWindow(display,windows->info.id);
11416 if (windows->info.mapped != MagickFalse)
11419 Display pointer position.
11421 (void) FormatMagickString(text,MaxTextExtent,
11422 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11423 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11424 XInfoWidget(display,windows,text);
11426 highlight_info=roi_info;
11427 highlight_info.x=roi_info.x-windows->image.x;
11428 highlight_info.y=roi_info.y-windows->image.y;
11429 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11431 state|=EscapeState;
11435 if ((state & UpdateRegionState) != 0)
11437 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11438 switch (command_type)
11443 (void) XMagickCommand(display,resource_info,windows,command_type,
11450 Region of interest is relative to image configuration.
11452 progress_monitor=SetImageProgressMonitor(*image,
11453 (MagickProgressMonitor) NULL,(*image)->client_data);
11454 crop_info=roi_info;
11455 width=(unsigned int) (*image)->columns;
11456 height=(unsigned int) (*image)->rows;
11459 if (windows->image.crop_geometry != (char *) NULL)
11460 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11462 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11464 crop_info.x=(int) (scale_factor*crop_info.x+0.5);
11465 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11466 scale_factor=(MagickRealType)
11467 height/windows->image.ximage->height;
11469 crop_info.y=(int) (scale_factor*crop_info.y+0.5);
11470 crop_info.height=(unsigned int)
11471 (scale_factor*crop_info.height+0.5);
11472 roi_image=CropImage(*image,&crop_info,&(*image)->exception);
11473 (void) SetImageProgressMonitor(*image,progress_monitor,
11474 (*image)->client_data);
11475 if (roi_image == (Image *) NULL)
11478 Apply image processing technique to the region of interest.
11480 windows->image.orphan=MagickTrue;
11481 (void) XMagickCommand(display,resource_info,windows,command_type,
11483 progress_monitor=SetImageProgressMonitor(*image,
11484 (MagickProgressMonitor) NULL,(*image)->client_data);
11485 (void) XMagickCommand(display,resource_info,windows,
11486 SaveToUndoBufferCommand,image);
11487 windows->image.orphan=MagickFalse;
11488 (void) CompositeImage(*image,CopyCompositeOp,roi_image,
11489 crop_info.x,crop_info.y);
11490 roi_image=DestroyImage(roi_image);
11491 (void) SetImageProgressMonitor(*image,progress_monitor,
11492 (*image)->client_data);
11496 if (command_type != InfoCommand)
11498 XConfigureImageColormap(display,resource_info,windows,*image);
11499 (void) XConfigureImage(display,resource_info,windows,*image);
11501 XCheckRefreshWindows(display,windows);
11502 XInfoWidget(display,windows,text);
11503 (void) XSetFunction(display,windows->image.highlight_context,
11505 state&=(~UpdateRegionState);
11507 XHighlightRectangle(display,windows->image.id,
11508 windows->image.highlight_context,&highlight_info);
11509 XScreenEvent(display,windows,&event);
11510 if (event.xany.window == windows->command.id)
11513 Select a command from the Command widget.
11515 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11516 command_type=NullCommand;
11517 id=XCommandWidget(display,windows,ApplyMenu,&event);
11520 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11521 command_type=ApplyCommands[id];
11522 if (id < ApplyMenus)
11525 Select a command from a pop-up menu.
11527 entry=XMenuWidget(display,windows,ApplyMenu[id],
11528 (const char **) Menus[id],command);
11531 (void) CopyMagickString(command,Menus[id][entry],
11533 command_type=Commands[id][entry];
11537 (void) XSetFunction(display,windows->image.highlight_context,
11539 XHighlightRectangle(display,windows->image.id,
11540 windows->image.highlight_context,&highlight_info);
11541 if (command_type == HelpCommand)
11543 (void) XSetFunction(display,windows->image.highlight_context,
11545 XTextViewWidget(display,resource_info,windows,MagickFalse,
11546 "Help Viewer - Region of Interest",ImageROIHelp);
11547 (void) XSetFunction(display,windows->image.highlight_context,
11551 if (command_type == QuitCommand)
11556 state|=EscapeState;
11560 if (command_type != NullCommand)
11561 state|=UpdateRegionState;
11564 XHighlightRectangle(display,windows->image.id,
11565 windows->image.highlight_context,&highlight_info);
11566 switch (event.type)
11570 x=windows->image.x;
11571 y=windows->image.y;
11572 if (event.xbutton.button != Button1)
11574 if (event.xbutton.window != windows->image.id)
11576 x=windows->image.x+event.xbutton.x;
11577 y=windows->image.y+event.xbutton.y;
11578 if ((x < (int) (roi_info.x+RoiDelta)) &&
11579 (x > (int) (roi_info.x-RoiDelta)) &&
11580 (y < (int) (roi_info.y+RoiDelta)) &&
11581 (y > (int) (roi_info.y-RoiDelta)))
11583 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11584 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11585 state|=UpdateConfigurationState;
11588 if ((x < (int) (roi_info.x+RoiDelta)) &&
11589 (x > (int) (roi_info.x-RoiDelta)) &&
11590 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11591 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11593 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
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+RoiDelta)) &&
11600 (y > (int) (roi_info.y-RoiDelta)))
11602 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11603 state|=UpdateConfigurationState;
11606 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11607 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11608 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11609 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11611 state|=UpdateConfigurationState;
11615 case ButtonRelease:
11617 if (event.xbutton.window == windows->pan.id)
11618 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11619 (highlight_info.y != crop_info.y-windows->image.y))
11620 XHighlightRectangle(display,windows->image.id,
11621 windows->image.highlight_context,&highlight_info);
11622 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11623 event.xbutton.time);
11628 if (event.xexpose.window == windows->image.id)
11629 if (event.xexpose.count == 0)
11631 event.xexpose.x=(int) highlight_info.x;
11632 event.xexpose.y=(int) highlight_info.y;
11633 event.xexpose.width=(int) highlight_info.width;
11634 event.xexpose.height=(int) highlight_info.height;
11635 XRefreshWindow(display,&windows->image,&event);
11637 if (event.xexpose.window == windows->info.id)
11638 if (event.xexpose.count == 0)
11639 XInfoWidget(display,windows,text);
11647 if (event.xkey.window != windows->image.id)
11650 Respond to a user key press.
11652 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11653 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11654 switch ((int) key_symbol)
11661 state|=EscapeState;
11670 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11671 roi_info.y=(ssize_t) (windows->image.height/2L-roi_info.height/2L);
11703 (void) XSetFunction(display,windows->image.highlight_context,
11705 XTextViewWidget(display,resource_info,windows,MagickFalse,
11706 "Help Viewer - Region of Interest",ImageROIHelp);
11707 (void) XSetFunction(display,windows->image.highlight_context,
11713 command_type=XImageWindowCommand(display,resource_info,windows,
11714 event.xkey.state,key_symbol,image);
11715 if (command_type != NullCommand)
11716 state|=UpdateRegionState;
11720 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11728 if (event.xbutton.window != windows->image.id)
11731 Map and unmap Info widget as text cursor crosses its boundaries.
11735 if (windows->info.mapped != MagickFalse)
11737 if ((x < (int) (windows->info.x+windows->info.width)) &&
11738 (y < (int) (windows->info.y+windows->info.height)))
11739 (void) XWithdrawWindow(display,windows->info.id,
11740 windows->info.screen);
11743 if ((x > (int) (windows->info.x+windows->info.width)) ||
11744 (y > (int) (windows->info.y+windows->info.height)))
11745 (void) XMapWindow(display,windows->info.id);
11746 roi_info.x=windows->image.x+event.xmotion.x;
11747 roi_info.y=windows->image.y+event.xmotion.y;
11750 case SelectionRequest:
11755 XSelectionRequestEvent
11759 Set primary selection.
11761 (void) FormatMagickString(text,MaxTextExtent,
11762 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11763 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11764 request=(&(event.xselectionrequest));
11765 (void) XChangeProperty(request->display,request->requestor,
11766 request->property,request->target,8,PropModeReplace,
11767 (unsigned char *) text,(int) strlen(text));
11768 notify.type=SelectionNotify;
11769 notify.display=request->display;
11770 notify.requestor=request->requestor;
11771 notify.selection=request->selection;
11772 notify.target=request->target;
11773 notify.time=request->time;
11774 if (request->property == None)
11775 notify.property=request->target;
11777 notify.property=request->property;
11778 (void) XSendEvent(request->display,request->requestor,False,0,
11779 (XEvent *) ¬ify);
11784 if ((state & UpdateConfigurationState) != 0)
11786 (void) XPutBackEvent(display,&event);
11787 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11790 } while ((state & ExitState) == 0);
11791 } while ((state & ExitState) == 0);
11792 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11793 XSetCursorState(display,windows,MagickFalse);
11794 if ((state & EscapeState) != 0)
11795 return(MagickTrue);
11796 return(MagickTrue);
11800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11804 + X R o t a t e I m a g e %
11808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11810 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11811 % rotation angle is computed from the slope of a line drawn by the user.
11813 % The format of the XRotateImage method is:
11815 % MagickBooleanType XRotateImage(Display *display,
11816 % XResourceInfo *resource_info,XWindows *windows,double degrees,
11819 % A description of each parameter follows:
11821 % o display: Specifies a connection to an X server; returned from
11824 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11826 % o windows: Specifies a pointer to a XWindows structure.
11828 % o degrees: Specifies the number of degrees to rotate the image.
11830 % o image: the image.
11833 static MagickBooleanType XRotateImage(Display *display,
11834 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image)
11847 direction = HorizontalRotateCommand;
11849 static const ModeType
11850 DirectionCommands[] =
11852 HorizontalRotateCommand,
11853 VerticalRotateCommand
11857 RotateColorCommand,
11858 RotateDirectionCommand,
11860 RotateDismissCommand
11863 static unsigned int
11867 command[MaxTextExtent],
11868 text[MaxTextExtent];
11879 normalized_degrees;
11889 if (degrees == 0.0)
11904 Map Command widget.
11906 (void) CloneString(&windows->command.name,"Rotate");
11907 windows->command.data=2;
11908 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
11909 (void) XMapRaised(display,windows->command.id);
11910 XClientMessage(display,windows->image.id,windows->im_protocols,
11911 windows->im_update_widget,CurrentTime);
11913 Wait for first button press.
11915 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11916 XQueryPosition(display,windows->image.id,&x,&y);
11921 state=DefaultState;
11924 XHighlightLine(display,windows->image.id,
11925 windows->image.highlight_context,&rotate_info);
11927 Wait for next event.
11929 XScreenEvent(display,windows,&event);
11930 XHighlightLine(display,windows->image.id,
11931 windows->image.highlight_context,&rotate_info);
11932 if (event.xany.window == windows->command.id)
11935 Select a command from the Command widget.
11937 id=XCommandWidget(display,windows,RotateMenu,&event);
11940 (void) XSetFunction(display,windows->image.highlight_context,
11942 switch (RotateCommands[id])
11944 case RotateColorCommand:
11947 *ColorMenu[MaxNumberPens];
11956 Initialize menu selections.
11958 for (i=0; i < (int) (MaxNumberPens-2); i++)
11959 ColorMenu[i]=resource_info->pen_colors[i];
11960 ColorMenu[MaxNumberPens-2]="Browser...";
11961 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
11963 Select a pen color from the pop-up menu.
11965 pen_number=XMenuWidget(display,windows,RotateMenu[id],
11966 (const char **) ColorMenu,command);
11967 if (pen_number < 0)
11969 if (pen_number == (MaxNumberPens-2))
11972 color_name[MaxTextExtent] = "gray";
11975 Select a pen color from a dialog.
11977 resource_info->pen_colors[pen_number]=color_name;
11978 XColorBrowserWidget(display,windows,"Select",color_name);
11979 if (*color_name == '\0')
11985 (void) XParseColor(display,windows->map_info->colormap,
11986 resource_info->pen_colors[pen_number],&color);
11987 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
11988 (unsigned int) MaxColors,&color);
11989 windows->pixel_info->pen_colors[pen_number]=color;
11990 pen_id=(unsigned int) pen_number;
11993 case RotateDirectionCommand:
12004 Select a command from the pop-up menu.
12006 id=XMenuWidget(display,windows,RotateMenu[id],
12007 Directions,command);
12009 direction=DirectionCommands[id];
12012 case RotateHelpCommand:
12014 XTextViewWidget(display,resource_info,windows,MagickFalse,
12015 "Help Viewer - Image Rotation",ImageRotateHelp);
12018 case RotateDismissCommand:
12023 state|=EscapeState;
12030 (void) XSetFunction(display,windows->image.highlight_context,
12034 switch (event.type)
12038 if (event.xbutton.button != Button1)
12040 if (event.xbutton.window != windows->image.id)
12045 (void) XSetFunction(display,windows->image.highlight_context,
12047 rotate_info.x1=event.xbutton.x;
12048 rotate_info.y1=event.xbutton.y;
12052 case ButtonRelease:
12059 command[MaxTextExtent];
12064 if (event.xkey.window != windows->image.id)
12067 Respond to a user key press.
12069 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12070 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12071 switch ((int) key_symbol)
12079 state|=EscapeState;
12086 (void) XSetFunction(display,windows->image.highlight_context,
12088 XTextViewWidget(display,resource_info,windows,MagickFalse,
12089 "Help Viewer - Image Rotation",ImageRotateHelp);
12090 (void) XSetFunction(display,windows->image.highlight_context,
12096 (void) XBell(display,0);
12104 rotate_info.x1=event.xmotion.x;
12105 rotate_info.y1=event.xmotion.y;
12108 rotate_info.x2=rotate_info.x1;
12109 rotate_info.y2=rotate_info.y1;
12110 if (direction == HorizontalRotateCommand)
12111 rotate_info.x2+=32;
12113 rotate_info.y2-=32;
12114 } while ((state & ExitState) == 0);
12115 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12116 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12117 if ((state & EscapeState) != 0)
12118 return(MagickTrue);
12120 Draw line as pointer moves until the mouse button is released.
12123 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12124 state=DefaultState;
12130 Display info and draw rotation line.
12132 if (windows->info.mapped == MagickFalse)
12133 (void) XMapWindow(display,windows->info.id);
12134 (void) FormatMagickString(text,MaxTextExtent," %g",
12135 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12136 XInfoWidget(display,windows,text);
12137 XHighlightLine(display,windows->image.id,
12138 windows->image.highlight_context,&rotate_info);
12141 if (windows->info.mapped != MagickFalse)
12142 (void) XWithdrawWindow(display,windows->info.id,
12143 windows->info.screen);
12145 Wait for next event.
12147 XScreenEvent(display,windows,&event);
12149 XHighlightLine(display,windows->image.id,
12150 windows->image.highlight_context,&rotate_info);
12151 switch (event.type)
12155 case ButtonRelease:
12158 User has committed to rotation line.
12160 rotate_info.x2=event.xbutton.x;
12161 rotate_info.y2=event.xbutton.y;
12169 rotate_info.x2=event.xmotion.x;
12170 rotate_info.y2=event.xmotion.y;
12176 Check boundary conditions.
12178 if (rotate_info.x2 < 0)
12181 if (rotate_info.x2 > (int) windows->image.width)
12182 rotate_info.x2=(short) windows->image.width;
12183 if (rotate_info.y2 < 0)
12186 if (rotate_info.y2 > (int) windows->image.height)
12187 rotate_info.y2=(short) windows->image.height;
12189 Compute rotation angle from the slope of the line.
12192 distance=(unsigned int)
12193 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12194 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12196 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12197 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12198 } while ((state & ExitState) == 0);
12199 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12200 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12202 return(MagickTrue);
12204 if (direction == VerticalRotateCommand)
12206 if (degrees == 0.0)
12207 return(MagickTrue);
12211 normalized_degrees=degrees;
12212 while (normalized_degrees < -45.0)
12213 normalized_degrees+=360.0;
12214 for (rotations=0; normalized_degrees > 45.0; rotations++)
12215 normalized_degrees-=90.0;
12216 if (normalized_degrees != 0.0)
12217 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image);
12218 XSetCursorState(display,windows,MagickTrue);
12219 XCheckRefreshWindows(display,windows);
12220 (*image)->background_color.red=ScaleShortToQuantum(
12221 windows->pixel_info->pen_colors[pen_id].red);
12222 (*image)->background_color.green=ScaleShortToQuantum(
12223 windows->pixel_info->pen_colors[pen_id].green);
12224 (*image)->background_color.blue=ScaleShortToQuantum(
12225 windows->pixel_info->pen_colors[pen_id].blue);
12226 rotate_image=RotateImage(*image,degrees,&(*image)->exception);
12227 XSetCursorState(display,windows,MagickFalse);
12228 if (rotate_image == (Image *) NULL)
12229 return(MagickFalse);
12230 *image=DestroyImage(*image);
12231 *image=rotate_image;
12232 if (windows->image.crop_geometry != (char *) NULL)
12235 Rotate crop geometry.
12237 width=(unsigned int) (*image)->columns;
12238 height=(unsigned int) (*image)->rows;
12239 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12240 switch (rotations % 4)
12250 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12251 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12258 Rotate 180 degrees.
12260 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12261 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12267 Rotate 270 degrees.
12269 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12270 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12275 if (windows->image.orphan != MagickFalse)
12276 return(MagickTrue);
12277 if (normalized_degrees != 0.0)
12280 Update image colormap.
12282 windows->image.window_changes.width=(int) (*image)->columns;
12283 windows->image.window_changes.height=(int) (*image)->rows;
12284 if (windows->image.crop_geometry != (char *) NULL)
12287 Obtain dimensions of image from crop geometry.
12289 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12291 windows->image.window_changes.width=(int) width;
12292 windows->image.window_changes.height=(int) height;
12294 XConfigureImageColormap(display,resource_info,windows,*image);
12297 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12299 windows->image.window_changes.width=windows->image.ximage->height;
12300 windows->image.window_changes.height=windows->image.ximage->width;
12303 Update image configuration.
12305 (void) XConfigureImage(display,resource_info,windows,*image);
12306 return(MagickTrue);
12310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12314 + X S a v e I m a g e %
12318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12320 % XSaveImage() saves an image to a file.
12322 % The format of the XSaveImage method is:
12324 % MagickBooleanType XSaveImage(Display *display,
12325 % XResourceInfo *resource_info,XWindows *windows,Image *image)
12327 % A description of each parameter follows:
12329 % o display: Specifies a connection to an X server; returned from
12332 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12334 % o windows: Specifies a pointer to a XWindows structure.
12336 % o image: the image.
12339 static MagickBooleanType XSaveImage(Display *display,
12340 XResourceInfo *resource_info,XWindows *windows,Image *image)
12343 filename[MaxTextExtent],
12344 geometry[MaxTextExtent];
12356 Request file name from user.
12358 if (resource_info->write_filename != (char *) NULL)
12359 (void) CopyMagickString(filename,resource_info->write_filename,
12364 path[MaxTextExtent];
12369 GetPathComponent(image->filename,HeadPath,path);
12370 GetPathComponent(image->filename,TailPath,filename);
12371 status=chdir(path);
12373 (void) ThrowMagickException(&image->exception,GetMagickModule(),
12374 FileOpenError,"UnableToOpenFile","%s",path);
12376 XFileBrowserWidget(display,windows,"Save",filename);
12377 if (*filename == '\0')
12378 return(MagickTrue);
12379 if (IsPathAccessible(filename) != MagickFalse)
12385 File exists-- seek user's permission before overwriting.
12387 status=XConfirmWidget(display,windows,"Overwrite",filename);
12389 return(MagickTrue);
12391 image_info=CloneImageInfo(resource_info->image_info);
12392 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12393 (void) SetImageInfo(image_info,1,&image->exception);
12394 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12395 (LocaleCompare(image_info->magick,"JPG") == 0))
12398 quality[MaxTextExtent];
12404 Request JPEG quality from user.
12406 (void) FormatMagickString(quality,MaxTextExtent,"%.20g",(double)
12408 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12410 if (*quality == '\0')
12411 return(MagickTrue);
12412 image->quality=StringToUnsignedLong(quality);
12413 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12415 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12416 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12417 (LocaleCompare(image_info->magick,"PS") == 0) ||
12418 (LocaleCompare(image_info->magick,"PS2") == 0))
12421 geometry[MaxTextExtent];
12424 Request page geometry from user.
12426 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12427 if (LocaleCompare(image_info->magick,"PDF") == 0)
12428 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12429 if (image_info->page != (char *) NULL)
12430 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12431 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12432 "Select page geometry:",geometry);
12433 if (*geometry != '\0')
12434 image_info->page=GetPageGeometry(geometry);
12437 Apply image transforms.
12439 XSetCursorState(display,windows,MagickTrue);
12440 XCheckRefreshWindows(display,windows);
12441 save_image=CloneImage(image,0,0,MagickTrue,&image->exception);
12442 if (save_image == (Image *) NULL)
12443 return(MagickFalse);
12444 (void) FormatMagickString(geometry,MaxTextExtent,"%dx%d!",
12445 windows->image.ximage->width,windows->image.ximage->height);
12446 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry);
12450 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12451 status=WriteImage(image_info,save_image);
12452 if (status != MagickFalse)
12453 image->taint=MagickFalse;
12454 save_image=DestroyImage(save_image);
12455 image_info=DestroyImageInfo(image_info);
12456 XSetCursorState(display,windows,MagickFalse);
12457 return(status != 0 ? MagickTrue : MagickFalse);
12461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12465 + X S c r e e n E v e n t %
12469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12471 % XScreenEvent() handles global events associated with the Pan and Magnify
12474 % The format of the XScreenEvent function is:
12476 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12478 % A description of each parameter follows:
12480 % o display: Specifies a pointer to the Display structure; returned from
12483 % o windows: Specifies a pointer to a XWindows structure.
12485 % o event: Specifies a pointer to a X11 XEvent structure.
12490 #if defined(__cplusplus) || defined(c_plusplus)
12494 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12499 windows=(XWindows *) data;
12500 if ((event->type == ClientMessage) &&
12501 (event->xclient.window == windows->image.id))
12502 return(MagickFalse);
12503 return(MagickTrue);
12506 #if defined(__cplusplus) || defined(c_plusplus)
12510 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12516 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12517 if (event->xany.window == windows->command.id)
12519 switch (event->type)
12522 case ButtonRelease:
12524 if ((event->xbutton.button == Button3) &&
12525 (event->xbutton.state & Mod1Mask))
12528 Convert Alt-Button3 to Button2.
12530 event->xbutton.button=Button2;
12531 event->xbutton.state&=(~Mod1Mask);
12533 if (event->xbutton.window == windows->backdrop.id)
12535 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12536 event->xbutton.time);
12539 if (event->xbutton.window == windows->pan.id)
12541 XPanImage(display,windows,event);
12544 if (event->xbutton.window == windows->image.id)
12545 if (event->xbutton.button == Button2)
12548 Update magnified image.
12550 x=event->xbutton.x;
12551 y=event->xbutton.y;
12555 if (x >= (int) windows->image.width)
12556 x=(int) (windows->image.width-1);
12557 windows->magnify.x=windows->image.x+x;
12561 if (y >= (int) windows->image.height)
12562 y=(int) (windows->image.height-1);
12563 windows->magnify.y=windows->image.y+y;
12564 if (windows->magnify.mapped == MagickFalse)
12565 (void) XMapRaised(display,windows->magnify.id);
12566 XMakeMagnifyImage(display,windows);
12567 if (event->type == ButtonRelease)
12568 (void) XWithdrawWindow(display,windows->info.id,
12569 windows->info.screen);
12574 case ClientMessage:
12577 If client window delete message, exit.
12579 if (event->xclient.message_type != windows->wm_protocols)
12581 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12583 if (event->xclient.window == windows->magnify.id)
12585 (void) XWithdrawWindow(display,windows->magnify.id,
12586 windows->magnify.screen);
12591 case ConfigureNotify:
12593 if (event->xconfigure.window == windows->magnify.id)
12599 Magnify window has a new configuration.
12601 windows->magnify.width=(unsigned int) event->xconfigure.width;
12602 windows->magnify.height=(unsigned int) event->xconfigure.height;
12603 if (windows->magnify.mapped == MagickFalse)
12606 while ((int) magnify <= event->xconfigure.width)
12608 while ((int) magnify <= event->xconfigure.height)
12611 if (((int) magnify != event->xconfigure.width) ||
12612 ((int) magnify != event->xconfigure.height))
12617 window_changes.width=(int) magnify;
12618 window_changes.height=(int) magnify;
12619 (void) XReconfigureWMWindow(display,windows->magnify.id,
12620 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12624 XMakeMagnifyImage(display,windows);
12631 if (event->xexpose.window == windows->image.id)
12633 XRefreshWindow(display,&windows->image,event);
12636 if (event->xexpose.window == windows->pan.id)
12637 if (event->xexpose.count == 0)
12639 XDrawPanRectangle(display,windows);
12642 if (event->xexpose.window == windows->magnify.id)
12643 if (event->xexpose.count == 0)
12645 XMakeMagnifyImage(display,windows);
12653 command[MaxTextExtent];
12658 if (event->xkey.window != windows->magnify.id)
12661 Respond to a user key press.
12663 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12664 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12665 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol);
12670 if (event->xmap.window == windows->magnify.id)
12672 windows->magnify.mapped=MagickTrue;
12673 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12676 if (event->xmap.window == windows->info.id)
12678 windows->info.mapped=MagickTrue;
12685 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12686 if (event->xmotion.window == windows->image.id)
12687 if (windows->magnify.mapped != MagickFalse)
12690 Update magnified image.
12692 x=event->xmotion.x;
12693 y=event->xmotion.y;
12697 if (x >= (int) windows->image.width)
12698 x=(int) (windows->image.width-1);
12699 windows->magnify.x=windows->image.x+x;
12703 if (y >= (int) windows->image.height)
12704 y=(int) (windows->image.height-1);
12705 windows->magnify.y=windows->image.y+y;
12706 XMakeMagnifyImage(display,windows);
12712 if (event->xunmap.window == windows->magnify.id)
12714 windows->magnify.mapped=MagickFalse;
12717 if (event->xunmap.window == windows->info.id)
12719 windows->info.mapped=MagickFalse;
12730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12734 + X S e t C r o p G e o m e t r y %
12738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12740 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12741 % and translates it to a cropping geometry relative to the image.
12743 % The format of the XSetCropGeometry method is:
12745 % void XSetCropGeometry(Display *display,XWindows *windows,
12746 % RectangleInfo *crop_info,Image *image)
12748 % A description of each parameter follows:
12750 % o display: Specifies a connection to an X server; returned from
12753 % o windows: Specifies a pointer to a XWindows structure.
12755 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12756 % Image window to crop.
12758 % o image: the image.
12761 static void XSetCropGeometry(Display *display,XWindows *windows,
12762 RectangleInfo *crop_info,Image *image)
12765 text[MaxTextExtent];
12778 if (windows->info.mapped != MagickFalse)
12781 Display info on cropping rectangle.
12783 (void) FormatMagickString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12784 (double) crop_info->width,(double) crop_info->height,(double)
12785 crop_info->x,(double) crop_info->y);
12786 XInfoWidget(display,windows,text);
12789 Cropping geometry is relative to any previous crop geometry.
12793 width=(unsigned int) image->columns;
12794 height=(unsigned int) image->rows;
12795 if (windows->image.crop_geometry != (char *) NULL)
12796 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12798 windows->image.crop_geometry=AcquireString((char *) NULL);
12800 Define the crop geometry string from the cropping rectangle.
12802 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12803 if (crop_info->x > 0)
12804 x+=(int) (scale_factor*crop_info->x+0.5);
12805 width=(unsigned int) (scale_factor*crop_info->width+0.5);
12808 scale_factor=(MagickRealType) height/windows->image.ximage->height;
12809 if (crop_info->y > 0)
12810 y+=(int) (scale_factor*crop_info->y+0.5);
12811 height=(unsigned int) (scale_factor*crop_info->height+0.5);
12814 (void) FormatMagickString(windows->image.crop_geometry,MaxTextExtent,
12815 "%ux%u%+d%+d",width,height,x,y);
12819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12823 + X T i l e I m a g e %
12827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12829 % XTileImage() loads or deletes a selected tile from a visual image directory.
12830 % The load or delete command is chosen from a menu.
12832 % The format of the XTileImage method is:
12834 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
12835 % XWindows *windows,Image *image,XEvent *event)
12837 % A description of each parameter follows:
12839 % o tile_image: XTileImage reads or deletes the tile image
12840 % and returns it. A null image is returned if an error occurs.
12842 % o display: Specifies a connection to an X server; returned from
12845 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12847 % o windows: Specifies a pointer to a XWindows structure.
12849 % o image: the image; returned from ReadImage.
12851 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
12852 % the entire image is refreshed.
12855 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
12856 XWindows *windows,Image *image,XEvent *event)
12869 static const ModeType
12880 command[MaxTextExtent],
12881 filename[MaxTextExtent];
12908 Tile image is relative to montage image configuration.
12912 width=(unsigned int) image->columns;
12913 height=(unsigned int) image->rows;
12914 if (windows->image.crop_geometry != (char *) NULL)
12915 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12916 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12917 event->xbutton.x+=windows->image.x;
12918 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
12919 scale_factor=(MagickRealType) height/windows->image.ximage->height;
12920 event->xbutton.y+=windows->image.y;
12921 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
12923 Determine size and location of each tile in the visual image directory.
12925 width=(unsigned int) image->columns;
12926 height=(unsigned int) image->rows;
12929 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
12930 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
12931 (event->xbutton.x-x)/width;
12935 Button press is outside any tile.
12937 (void) XBell(display,0);
12938 return((Image *) NULL);
12941 Determine file name from the tile directory.
12943 p=image->directory;
12944 for (i=tile; (i != 0) && (*p != '\0'); )
12953 Button press is outside any tile.
12955 (void) XBell(display,0);
12956 return((Image *) NULL);
12959 Select a command from the pop-up menu.
12961 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
12963 return((Image *) NULL);
12965 while ((*q != '\n') && (*q != '\0'))
12967 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
12969 Perform command for the selected tile.
12971 XSetCursorState(display,windows,MagickTrue);
12972 XCheckRefreshWindows(display,windows);
12973 tile_image=NewImageList();
12974 switch (TileCommands[id])
12976 case TileLoadCommand:
12981 XCheckRefreshWindows(display,windows);
12982 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
12984 (void) CopyMagickString(resource_info->image_info->filename,filename,
12986 tile_image=ReadImage(resource_info->image_info,&image->exception);
12987 CatchException(&image->exception);
12988 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12991 case TileNextCommand:
12994 Display next image.
12996 XClientMessage(display,windows->image.id,windows->im_protocols,
12997 windows->im_next_image,CurrentTime);
13000 case TileFormerCommand:
13003 Display former image.
13005 XClientMessage(display,windows->image.id,windows->im_protocols,
13006 windows->im_former_image,CurrentTime);
13009 case TileDeleteCommand:
13014 if (IsPathAccessible(filename) == MagickFalse)
13016 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13019 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13022 status=remove(filename) != 0 ? MagickTrue : MagickFalse;
13023 if (status != MagickFalse)
13025 XNoticeWidget(display,windows,"Unable to delete image file:",
13030 case TileUpdateCommand:
13045 register PixelPacket
13049 Ensure all the images exist.
13052 for (p=image->directory; *p != '\0'; p++)
13055 while ((*q != '\n') && (*q != '\0'))
13057 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13059 if (IsPathAccessible(filename) != MagickFalse)
13065 Overwrite tile with background color.
13067 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13068 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13069 exception=(&image->exception);
13070 (void) GetOneVirtualPixel(image,0,0,&pixel,exception);
13071 for (i=0; i < (int) height; i++)
13073 s=GetAuthenticPixels(image,x_offset,y_offset+i,width,1,exception);
13074 if (s == (PixelPacket *) NULL)
13076 for (j=0; j < (int) width; j++)
13078 if (SyncAuthenticPixels(image,exception) == MagickFalse)
13083 windows->image.window_changes.width=(int) image->columns;
13084 windows->image.window_changes.height=(int) image->rows;
13085 XConfigureImageColormap(display,resource_info,windows,image);
13086 (void) XConfigureImage(display,resource_info,windows,image);
13092 XSetCursorState(display,windows,MagickFalse);
13093 return(tile_image);
13097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13101 + X T r a n s l a t e I m a g e %
13105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13107 % XTranslateImage() translates the image within an Image window by one pixel
13108 % as specified by the key symbol. If the image has a `montage string the
13109 % translation is respect to the width and height contained within the string.
13111 % The format of the XTranslateImage method is:
13113 % void XTranslateImage(Display *display,XWindows *windows,
13114 % Image *image,const KeySym key_symbol)
13116 % A description of each parameter follows:
13118 % o display: Specifies a connection to an X server; returned from
13121 % o windows: Specifies a pointer to a XWindows structure.
13123 % o image: the image.
13125 % o key_symbol: Specifies a KeySym which indicates which side of the image
13129 static void XTranslateImage(Display *display,XWindows *windows,
13130 Image *image,const KeySym key_symbol)
13133 text[MaxTextExtent];
13144 User specified a pan position offset.
13146 x_offset=windows->image.width;
13147 y_offset=windows->image.height;
13148 if (image->montage != (char *) NULL)
13149 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13150 switch ((int) key_symbol)
13155 windows->image.x=(int) windows->image.width/2;
13156 windows->image.y=(int) windows->image.height/2;
13162 windows->image.x-=x_offset;
13169 windows->image.y-=y_offset;
13175 windows->image.x+=x_offset;
13182 windows->image.y+=y_offset;
13189 Check boundary conditions.
13191 if (windows->image.x < 0)
13192 windows->image.x=0;
13194 if ((int) (windows->image.x+windows->image.width) >
13195 windows->image.ximage->width)
13196 windows->image.x=windows->image.ximage->width-windows->image.width;
13197 if (windows->image.y < 0)
13198 windows->image.y=0;
13200 if ((int) (windows->image.y+windows->image.height) >
13201 windows->image.ximage->height)
13202 windows->image.y=windows->image.ximage->height-windows->image.height;
13204 Refresh Image window.
13206 (void) FormatMagickString(text,MaxTextExtent," %ux%u%+d%+d ",
13207 windows->image.width,windows->image.height,windows->image.x,
13209 XInfoWidget(display,windows,text);
13210 XCheckRefreshWindows(display,windows);
13211 XDrawPanRectangle(display,windows);
13212 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13213 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13221 + X T r i m I m a g e %
13225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13227 % XTrimImage() trims the edges from the Image window.
13229 % The format of the XTrimImage method is:
13231 % MagickBooleanType XTrimImage(Display *display,
13232 % XResourceInfo *resource_info,XWindows *windows,Image *image)
13234 % A description of each parameter follows:
13236 % o display: Specifies a connection to an X server; returned from
13239 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13241 % o windows: Specifies a pointer to a XWindows structure.
13243 % o image: the image.
13246 static MagickBooleanType XTrimImage(Display *display,
13247 XResourceInfo *resource_info,XWindows *windows,Image *image)
13261 Trim edges from image.
13263 XSetCursorState(display,windows,MagickTrue);
13264 XCheckRefreshWindows(display,windows);
13266 Crop the left edge.
13268 background=XGetPixel(windows->image.ximage,0,0);
13269 trim_info.width=(size_t) windows->image.ximage->width;
13270 for (x=0; x < windows->image.ximage->width; x++)
13272 for (y=0; y < windows->image.ximage->height; y++)
13274 pixel=XGetPixel(windows->image.ximage,x,y);
13275 if (pixel != background)
13278 if (y < windows->image.ximage->height)
13282 if (trim_info.x == (int) windows->image.ximage->width)
13284 XSetCursorState(display,windows,MagickFalse);
13285 return(MagickFalse);
13288 Crop the right edge.
13290 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13291 for (x=windows->image.ximage->width-1; x != 0; x--)
13293 for (y=0; y < windows->image.ximage->height; y++)
13295 pixel=XGetPixel(windows->image.ximage,x,y);
13296 if (pixel != background)
13299 if (y < windows->image.ximage->height)
13302 trim_info.width=(size_t) (x-trim_info.x+1);
13306 background=XGetPixel(windows->image.ximage,0,0);
13307 trim_info.height=(size_t) windows->image.ximage->height;
13308 for (y=0; y < windows->image.ximage->height; y++)
13310 for (x=0; x < windows->image.ximage->width; x++)
13312 pixel=XGetPixel(windows->image.ximage,x,y);
13313 if (pixel != background)
13316 if (x < windows->image.ximage->width)
13321 Crop the bottom edge.
13323 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13324 for (y=windows->image.ximage->height-1; y != 0; y--)
13326 for (x=0; x < windows->image.ximage->width; x++)
13328 pixel=XGetPixel(windows->image.ximage,x,y);
13329 if (pixel != background)
13332 if (x < windows->image.ximage->width)
13335 trim_info.height=(size_t) y-trim_info.y+1;
13336 if (((unsigned int) trim_info.width != windows->image.width) ||
13337 ((unsigned int) trim_info.height != windows->image.height))
13340 Reconfigure Image window as defined by the trimming rectangle.
13342 XSetCropGeometry(display,windows,&trim_info,image);
13343 windows->image.window_changes.width=(int) trim_info.width;
13344 windows->image.window_changes.height=(int) trim_info.height;
13345 (void) XConfigureImage(display,resource_info,windows,image);
13347 XSetCursorState(display,windows,MagickFalse);
13348 return(MagickTrue);
13352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13356 + X V i s u a l D i r e c t o r y I m a g e %
13360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13362 % XVisualDirectoryImage() creates a Visual Image Directory.
13364 % The format of the XVisualDirectoryImage method is:
13366 % Image *XVisualDirectoryImage(Display *display,
13367 % XResourceInfo *resource_info,XWindows *windows)
13369 % A description of each parameter follows:
13371 % o nexus: Method XVisualDirectoryImage returns a visual image
13372 % directory if it can be created successfully. Otherwise a null image
13375 % o display: Specifies a connection to an X server; returned from
13378 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13380 % o windows: Specifies a pointer to a XWindows structure.
13383 static Image *XVisualDirectoryImage(Display *display,
13384 XResourceInfo *resource_info,XWindows *windows)
13386 #define TileImageTag "Scale/Image"
13387 #define XClientName "montage"
13423 filename[MaxTextExtent] = "\0",
13424 filenames[MaxTextExtent] = "*";
13427 background_resources;
13430 Request file name from user.
13432 XFileBrowserWidget(display,windows,"Directory",filenames);
13433 if (*filenames == '\0')
13434 return((Image *) NULL);
13436 Expand the filenames.
13438 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13439 if (filelist == (char **) NULL)
13441 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13443 return((Image *) NULL);
13446 filelist[0]=filenames;
13447 status=ExpandFilenames(&number_files,&filelist);
13448 if ((status == MagickFalse) || (number_files == 0))
13450 if (number_files == 0)
13451 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13453 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13455 return((Image *) NULL);
13458 Set image background resources.
13460 background_resources=(*resource_info);
13461 background_resources.window_id=AcquireString("");
13462 (void) FormatMagickString(background_resources.window_id,MaxTextExtent,
13463 "0x%lx",windows->image.id);
13464 background_resources.backdrop=MagickTrue;
13466 Read each image and convert them to a tile.
13468 backdrop=(windows->visual_info->klass == TrueColor) ||
13469 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13470 read_info=CloneImageInfo(resource_info->image_info);
13471 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13473 images=NewImageList();
13474 exception=AcquireExceptionInfo();
13475 XSetCursorState(display,windows,MagickTrue);
13476 XCheckRefreshWindows(display,windows);
13477 for (i=0; i < (ssize_t) number_files; i++)
13479 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13480 filelist[i]=DestroyString(filelist[i]);
13481 *read_info->magick='\0';
13482 (void) CloneString(&read_info->size,DefaultTileGeometry);
13483 next_image=ReadImage(read_info,exception);
13484 CatchException(exception);
13485 if (next_image != (Image *) NULL)
13487 (void) DeleteImageProperty(next_image,"label");
13488 (void) SetImageProperty(next_image,"label",DefaultTileLabel);
13489 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13491 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13492 geometry.height,exception);
13493 if (thumbnail_image != (Image *) NULL)
13495 next_image=DestroyImage(next_image);
13496 next_image=thumbnail_image;
13500 (void) XDisplayBackgroundImage(display,&background_resources,
13502 XSetCursorState(display,windows,MagickTrue);
13504 AppendImageToList(&images,next_image);
13505 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13510 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13511 (MagickSizeType) number_files);
13512 if (proceed == MagickFalse)
13517 exception=DestroyExceptionInfo(exception);
13518 filelist=(char **) RelinquishMagickMemory(filelist);
13519 read_info=DestroyImageInfo(read_info);
13520 if (images == (Image *) NULL)
13522 XSetCursorState(display,windows,MagickFalse);
13523 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13524 return((Image *) NULL);
13527 Create the Visual Image Directory.
13529 montage_info=CloneMontageInfo(resource_info->image_info,(MontageInfo *) NULL);
13530 if (resource_info->font != (char *) NULL)
13531 (void) CloneString(&montage_info->font,resource_info->font);
13532 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13533 montage_image=MontageImageList(resource_info->image_info,montage_info,
13534 GetFirstImageInList(images),&images->exception);
13535 montage_info=DestroyMontageInfo(montage_info);
13536 images=DestroyImageList(images);
13537 XSetCursorState(display,windows,MagickFalse);
13538 if (montage_image == (Image *) NULL)
13539 return(montage_image);
13540 XClientMessage(display,windows->image.id,windows->im_protocols,
13541 windows->im_next_image,CurrentTime);
13542 return(montage_image);
13546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13550 % X D i s p l a y B a c k g r o u n d I m a g e %
13554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13556 % XDisplayBackgroundImage() displays an image in the background of a window.
13558 % The format of the XDisplayBackgroundImage method is:
13560 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13561 % XResourceInfo *resource_info,Image *image)
13563 % A description of each parameter follows:
13565 % o display: Specifies a connection to an X server; returned from
13568 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13570 % o image: the image.
13573 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13574 XResourceInfo *resource_info,Image *image)
13577 geometry[MaxTextExtent],
13578 visual_type[MaxTextExtent];
13591 static XStandardColormap
13595 *visual_info = (XVisualInfo *) NULL;
13616 Determine target window.
13618 assert(image != (Image *) NULL);
13619 assert(image->signature == MagickSignature);
13620 if (image->debug != MagickFalse)
13621 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13622 resources=(*resource_info);
13623 window_info.id=(Window) NULL;
13624 root_window=XRootWindow(display,XDefaultScreen(display));
13625 if (LocaleCompare(resources.window_id,"root") == 0)
13626 window_info.id=root_window;
13629 if (isdigit((unsigned char) *resources.window_id) != 0)
13630 window_info.id=XWindowByID(display,root_window,
13631 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13632 if (window_info.id == (Window) NULL)
13633 window_info.id=XWindowByName(display,root_window,resources.window_id);
13635 if (window_info.id == (Window) NULL)
13637 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13638 resources.window_id);
13639 return(MagickFalse);
13642 Determine window visual id.
13644 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13645 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13646 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13647 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13649 (void) FormatMagickString(visual_type,MaxTextExtent,"0x%lx",
13650 XVisualIDFromVisual(window_attributes.visual));
13651 if (visual_info == (XVisualInfo *) NULL)
13654 Allocate standard colormap.
13656 map_info=XAllocStandardColormap();
13657 if (map_info == (XStandardColormap *) NULL)
13658 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13660 map_info->colormap=(Colormap) NULL;
13661 pixel.pixels=(unsigned long *) NULL;
13663 Initialize visual info.
13665 resources.map_type=(char *) NULL;
13666 resources.visual_type=visual_type;
13667 visual_info=XBestVisualInfo(display,map_info,&resources);
13668 if (visual_info == (XVisualInfo *) NULL)
13669 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13670 resources.visual_type);
13672 Initialize window info.
13674 window_info.ximage=(XImage *) NULL;
13675 window_info.matte_image=(XImage *) NULL;
13676 window_info.pixmap=(Pixmap) NULL;
13677 window_info.matte_pixmap=(Pixmap) NULL;
13680 Free previous root colors.
13682 if (window_info.id == root_window)
13683 (void) XDestroyWindowColors(display,root_window);
13685 Initialize Standard Colormap.
13687 resources.colormap=SharedColormap;
13688 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel);
13690 Graphic context superclass.
13692 context_values.background=pixel.background_color.pixel;
13693 context_values.foreground=pixel.foreground_color.pixel;
13694 pixel.annotate_context=XCreateGC(display,window_info.id,
13695 (size_t) (GCBackground | GCForeground),&context_values);
13696 if (pixel.annotate_context == (GC) NULL)
13697 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13700 Initialize Image window attributes.
13702 window_info.name=AcquireString("\0");
13703 window_info.icon_name=AcquireString("\0");
13704 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13705 &resources,&window_info);
13707 Create the X image.
13709 window_info.width=(unsigned int) image->columns;
13710 window_info.height=(unsigned int) image->rows;
13711 if ((image->columns != window_info.width) ||
13712 (image->rows != window_info.height))
13713 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13715 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>",
13716 window_attributes.width,window_attributes.height);
13717 geometry_info.width=window_info.width;
13718 geometry_info.height=window_info.height;
13719 geometry_info.x=(ssize_t) window_info.x;
13720 geometry_info.y=(ssize_t) window_info.y;
13721 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13722 &geometry_info.width,&geometry_info.height);
13723 window_info.width=(unsigned int) geometry_info.width;
13724 window_info.height=(unsigned int) geometry_info.height;
13725 window_info.x=(int) geometry_info.x;
13726 window_info.y=(int) geometry_info.y;
13727 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13728 window_info.height);
13729 if (status == MagickFalse)
13730 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13734 if (image->debug != MagickFalse)
13736 (void) LogMagickEvent(X11Event,GetMagickModule(),
13737 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13738 (double) image->columns,(double) image->rows);
13739 if (image->colors != 0)
13740 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13742 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13745 Adjust image dimensions as specified by backdrop or geometry options.
13747 width=(int) window_info.width;
13748 height=(int) window_info.height;
13749 if (resources.backdrop != MagickFalse)
13752 Center image on window.
13754 window_info.x=(window_attributes.width/2)-
13755 (window_info.ximage->width/2);
13756 window_info.y=(window_attributes.height/2)-
13757 (window_info.ximage->height/2);
13758 width=window_attributes.width;
13759 height=window_attributes.height;
13761 if ((resources.image_geometry != (char *) NULL) &&
13762 (*resources.image_geometry != '\0'))
13765 default_geometry[MaxTextExtent];
13775 User specified geometry.
13777 size_hints=XAllocSizeHints();
13778 if (size_hints == (XSizeHints *) NULL)
13779 ThrowXWindowFatalException(ResourceLimitFatalError,
13780 "MemoryAllocationFailed",image->filename);
13781 size_hints->flags=0L;
13782 (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
13784 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13785 default_geometry,window_info.border_width,size_hints,&window_info.x,
13786 &window_info.y,&width,&height,&gravity);
13787 if (flags & (XValue | YValue))
13789 width=window_attributes.width;
13790 height=window_attributes.height;
13792 (void) XFree((void *) size_hints);
13795 Create the X pixmap.
13797 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
13798 (unsigned int) height,window_info.depth);
13799 if (window_info.pixmap == (Pixmap) NULL)
13800 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
13803 Display pixmap on the window.
13805 if (((unsigned int) width > window_info.width) ||
13806 ((unsigned int) height > window_info.height))
13807 (void) XFillRectangle(display,window_info.pixmap,
13808 window_info.annotate_context,0,0,(unsigned int) width,
13809 (unsigned int) height);
13810 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
13811 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
13812 window_info.width,(unsigned int) window_info.height);
13813 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
13814 (void) XClearWindow(display,window_info.id);
13815 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
13816 XDelay(display,delay == 0UL ? 10UL : delay);
13817 (void) XSync(display,MagickFalse);
13818 return(window_info.id == root_window ? MagickTrue : MagickFalse);
13822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13826 + X D i s p l a y I m a g e %
13830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13832 % XDisplayImage() displays an image via X11. A new image is created and
13833 % returned if the user interactively transforms the displayed image.
13835 % The format of the XDisplayImage method is:
13837 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
13838 % char **argv,int argc,Image **image,size_t *state)
13840 % A description of each parameter follows:
13842 % o nexus: Method XDisplayImage returns an image when the
13843 % user chooses 'Open Image' from the command menu or picks a tile
13844 % from the image directory. Otherwise a null image is returned.
13846 % o display: Specifies a connection to an X server; returned from
13849 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13851 % o argv: Specifies the application's argument list.
13853 % o argc: Specifies the number of arguments.
13855 % o image: Specifies an address to an address of an Image structure;
13858 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
13859 char **argv,int argc,Image **image,size_t *state)
13861 #define MagnifySize 256 /* must be a power of 2 */
13862 #define MagickMenus 10
13863 #define MagickTitle "Commands"
13890 "Visual Directory...",
13936 "Contrast Stretch...",
13937 "Sigmoidal Contrast...",
13971 "Charcoal Draw...",
13985 "Region of Interest...",
13988 *MiscellanyMenu[] =
14003 "Browse Documentation",
14030 **Menus[MagickMenus] =
14068 VisualDirectoryCommand,
14082 OriginalSizeCommand,
14089 TransformCommands[] =
14095 RotateRightCommand,
14102 EnhanceCommands[] =
14110 ContrastStretchCommand,
14111 SigmoidalContrastCommand,
14119 EffectsCommands[] =
14123 ReduceNoiseCommand,
14143 CharcoalDrawCommand
14145 ImageEditCommands[] =
14156 RegionofInterestCommand
14158 MiscellanyCommands[] =
14162 ShowPreviewCommand,
14163 ShowHistogramCommand,
14172 BrowseDocumentationCommand,
14175 ShortCutsCommands[] =
14187 VirtualCommands[] =
14196 *Commands[MagickMenus] =
14206 MiscellanyCommands,
14211 command[MaxTextExtent],
14213 geometry[MaxTextExtent],
14214 resource_name[MaxTextExtent];
14241 working_directory[MaxTextExtent];
14247 *magick_windows[MaxXWindows];
14249 static unsigned int
14309 assert(image != (Image **) NULL);
14310 assert((*image)->signature == MagickSignature);
14311 if ((*image)->debug != MagickFalse)
14312 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14313 display_image=(*image);
14314 warning_handler=(WarningHandler) NULL;
14315 windows=XSetWindows((XWindows *) ~0);
14316 if (windows != (XWindows *) NULL)
14321 status=chdir(working_directory);
14323 (void) ThrowMagickException(&(*image)->exception,GetMagickModule(),
14324 FileOpenError,"UnableToOpenFile","%s",working_directory);
14325 warning_handler=resource_info->display_warnings ?
14326 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14327 warning_handler=resource_info->display_warnings ?
14328 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14333 Allocate windows structure.
14335 resource_info->colors=display_image->colors;
14336 windows=XSetWindows(XInitializeWindows(display,resource_info));
14337 if (windows == (XWindows *) NULL)
14338 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14339 (*image)->filename);
14341 Initialize window id's.
14344 magick_windows[number_windows++]=(&windows->icon);
14345 magick_windows[number_windows++]=(&windows->backdrop);
14346 magick_windows[number_windows++]=(&windows->image);
14347 magick_windows[number_windows++]=(&windows->info);
14348 magick_windows[number_windows++]=(&windows->command);
14349 magick_windows[number_windows++]=(&windows->widget);
14350 magick_windows[number_windows++]=(&windows->popup);
14351 magick_windows[number_windows++]=(&windows->magnify);
14352 magick_windows[number_windows++]=(&windows->pan);
14353 for (i=0; i < (int) number_windows; i++)
14354 magick_windows[i]->id=(Window) NULL;
14359 Initialize font info.
14361 if (windows->font_info != (XFontStruct *) NULL)
14362 (void) XFreeFont(display,windows->font_info);
14363 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14364 if (windows->font_info == (XFontStruct *) NULL)
14365 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14366 resource_info->font);
14368 Initialize Standard Colormap.
14370 map_info=windows->map_info;
14371 icon_map=windows->icon_map;
14372 visual_info=windows->visual_info;
14373 icon_visual=windows->icon_visual;
14374 pixel=windows->pixel_info;
14375 icon_pixel=windows->icon_pixel;
14376 font_info=windows->font_info;
14377 icon_resources=windows->icon_resources;
14378 class_hints=windows->class_hints;
14379 manager_hints=windows->manager_hints;
14380 root_window=XRootWindow(display,visual_info->screen);
14381 nexus=NewImageList();
14382 if (display_image->debug != MagickFalse)
14384 (void) LogMagickEvent(X11Event,GetMagickModule(),
14385 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14386 (double) display_image->scene,(double) display_image->columns,
14387 (double) display_image->rows);
14388 if (display_image->colors != 0)
14389 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14390 display_image->colors);
14391 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14392 display_image->magick);
14394 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14396 display_image->taint=MagickFalse;
14398 Initialize graphic context.
14400 windows->context.id=(Window) NULL;
14401 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14402 resource_info,&windows->context);
14403 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14404 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14405 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14406 manager_hints->flags=InputHint | StateHint;
14407 manager_hints->input=MagickFalse;
14408 manager_hints->initial_state=WithdrawnState;
14409 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14410 &windows->context);
14411 if (display_image->debug != MagickFalse)
14412 (void) LogMagickEvent(X11Event,GetMagickModule(),
14413 "Window id: 0x%lx (context)",windows->context.id);
14414 context_values.background=pixel->background_color.pixel;
14415 context_values.font=font_info->fid;
14416 context_values.foreground=pixel->foreground_color.pixel;
14417 context_values.graphics_exposures=MagickFalse;
14418 context_mask=(MagickStatusType)
14419 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14420 if (pixel->annotate_context != (GC) NULL)
14421 (void) XFreeGC(display,pixel->annotate_context);
14422 pixel->annotate_context=XCreateGC(display,windows->context.id,
14423 context_mask,&context_values);
14424 if (pixel->annotate_context == (GC) NULL)
14425 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14426 display_image->filename);
14427 context_values.background=pixel->depth_color.pixel;
14428 if (pixel->widget_context != (GC) NULL)
14429 (void) XFreeGC(display,pixel->widget_context);
14430 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14432 if (pixel->widget_context == (GC) NULL)
14433 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14434 display_image->filename);
14435 context_values.background=pixel->foreground_color.pixel;
14436 context_values.foreground=pixel->background_color.pixel;
14437 context_values.plane_mask=context_values.background ^
14438 context_values.foreground;
14439 if (pixel->highlight_context != (GC) NULL)
14440 (void) XFreeGC(display,pixel->highlight_context);
14441 pixel->highlight_context=XCreateGC(display,windows->context.id,
14442 (size_t) (context_mask | GCPlaneMask),&context_values);
14443 if (pixel->highlight_context == (GC) NULL)
14444 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14445 display_image->filename);
14446 (void) XDestroyWindow(display,windows->context.id);
14448 Initialize icon window.
14450 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14451 icon_resources,&windows->icon);
14452 windows->icon.geometry=resource_info->icon_geometry;
14453 XBestIconSize(display,&windows->icon,display_image);
14454 windows->icon.attributes.colormap=XDefaultColormap(display,
14455 icon_visual->screen);
14456 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14457 manager_hints->flags=InputHint | StateHint;
14458 manager_hints->input=MagickFalse;
14459 manager_hints->initial_state=IconicState;
14460 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14462 if (display_image->debug != MagickFalse)
14463 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14466 Initialize graphic context for icon window.
14468 if (icon_pixel->annotate_context != (GC) NULL)
14469 (void) XFreeGC(display,icon_pixel->annotate_context);
14470 context_values.background=icon_pixel->background_color.pixel;
14471 context_values.foreground=icon_pixel->foreground_color.pixel;
14472 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14473 (size_t) (GCBackground | GCForeground),&context_values);
14474 if (icon_pixel->annotate_context == (GC) NULL)
14475 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14476 display_image->filename);
14477 windows->icon.annotate_context=icon_pixel->annotate_context;
14479 Initialize Image window.
14481 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14483 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14484 if (resource_info->use_shared_memory == MagickFalse)
14485 windows->image.shared_memory=MagickFalse;
14486 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14491 title=InterpretImageProperties(resource_info->image_info,display_image,
14492 resource_info->title);
14493 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14494 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14495 title=DestroyString(title);
14500 filename[MaxTextExtent];
14503 Window name is the base of the filename.
14505 GetPathComponent(display_image->magick_filename,TailPath,filename);
14506 if (GetImageListLength(display_image) == 1)
14507 (void) FormatMagickString(windows->image.name,MaxTextExtent,
14508 "%s: %s",MagickPackageName,filename);
14510 (void) FormatMagickString(windows->image.name,MaxTextExtent,
14511 "%s: %s[%.20g of %.20g]",MagickPackageName,filename,(double)
14512 display_image->scene,(double) GetImageListLength(display_image));
14513 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14515 if (resource_info->immutable)
14516 windows->image.immutable=MagickTrue;
14517 windows->image.use_pixmap=resource_info->use_pixmap;
14518 windows->image.geometry=resource_info->image_geometry;
14519 (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14520 XDisplayWidth(display,visual_info->screen),
14521 XDisplayHeight(display,visual_info->screen));
14522 geometry_info.width=display_image->columns;
14523 geometry_info.height=display_image->rows;
14526 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14527 &geometry_info.width,&geometry_info.height);
14528 windows->image.width=(unsigned int) geometry_info.width;
14529 windows->image.height=(unsigned int) geometry_info.height;
14530 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14531 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14532 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14533 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14534 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14535 resource_info,&windows->backdrop);
14536 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14539 Initialize backdrop window.
14541 windows->backdrop.x=0;
14542 windows->backdrop.y=0;
14543 (void) CloneString(&windows->backdrop.name,"Backdrop");
14544 windows->backdrop.flags=(size_t) (USSize | USPosition);
14545 windows->backdrop.width=(unsigned int)
14546 XDisplayWidth(display,visual_info->screen);
14547 windows->backdrop.height=(unsigned int)
14548 XDisplayHeight(display,visual_info->screen);
14549 windows->backdrop.border_width=0;
14550 windows->backdrop.immutable=MagickTrue;
14551 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14553 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14554 StructureNotifyMask;
14555 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14556 manager_hints->icon_window=windows->icon.id;
14557 manager_hints->input=MagickTrue;
14558 manager_hints->initial_state=resource_info->iconic ? IconicState :
14560 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14561 &windows->backdrop);
14562 if (display_image->debug != MagickFalse)
14563 (void) LogMagickEvent(X11Event,GetMagickModule(),
14564 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14565 (void) XMapWindow(display,windows->backdrop.id);
14566 (void) XClearWindow(display,windows->backdrop.id);
14567 if (windows->image.id != (Window) NULL)
14569 (void) XDestroyWindow(display,windows->image.id);
14570 windows->image.id=(Window) NULL;
14573 Position image in the center the backdrop.
14575 windows->image.flags|=USPosition;
14576 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14577 (windows->image.width/2);
14578 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14579 (windows->image.height/2);
14581 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14582 manager_hints->icon_window=windows->icon.id;
14583 manager_hints->input=MagickTrue;
14584 manager_hints->initial_state=resource_info->iconic ? IconicState :
14586 if (windows->group_leader.id != (Window) NULL)
14591 manager_hints->flags|=WindowGroupHint;
14592 manager_hints->window_group=windows->group_leader.id;
14593 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14594 if (display_image->debug != MagickFalse)
14595 (void) LogMagickEvent(X11Event,GetMagickModule(),
14596 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14598 XMakeWindow(display,
14599 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14600 argv,argc,class_hints,manager_hints,&windows->image);
14601 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14602 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14603 if (windows->group_leader.id != (Window) NULL)
14604 (void) XSetTransientForHint(display,windows->image.id,
14605 windows->group_leader.id);
14606 if (display_image->debug != MagickFalse)
14607 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14608 windows->image.id);
14610 Initialize Info widget.
14612 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14614 (void) CloneString(&windows->info.name,"Info");
14615 (void) CloneString(&windows->info.icon_name,"Info");
14616 windows->info.border_width=1;
14619 windows->info.flags|=PPosition;
14620 windows->info.attributes.win_gravity=UnmapGravity;
14621 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14622 StructureNotifyMask;
14623 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14624 manager_hints->input=MagickFalse;
14625 manager_hints->initial_state=NormalState;
14626 manager_hints->window_group=windows->image.id;
14627 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14629 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14630 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14631 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14632 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14633 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14634 if (windows->image.mapped != MagickFalse)
14635 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14636 if (display_image->debug != MagickFalse)
14637 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14640 Initialize Command widget.
14642 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14643 resource_info,&windows->command);
14644 windows->command.data=MagickMenus;
14645 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14646 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.command",
14647 resource_info->client_name);
14648 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14649 resource_name,"geometry",(char *) NULL);
14650 (void) CloneString(&windows->command.name,MagickTitle);
14651 windows->command.border_width=0;
14652 windows->command.flags|=PPosition;
14653 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14654 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14655 OwnerGrabButtonMask | StructureNotifyMask;
14656 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14657 manager_hints->input=MagickTrue;
14658 manager_hints->initial_state=NormalState;
14659 manager_hints->window_group=windows->image.id;
14660 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14661 &windows->command);
14662 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14663 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14665 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14666 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14667 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14668 if (windows->command.mapped != MagickFalse)
14669 (void) XMapRaised(display,windows->command.id);
14670 if (display_image->debug != MagickFalse)
14671 (void) LogMagickEvent(X11Event,GetMagickModule(),
14672 "Window id: 0x%lx (command)",windows->command.id);
14674 Initialize Widget window.
14676 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14677 resource_info,&windows->widget);
14678 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.widget",
14679 resource_info->client_name);
14680 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14681 resource_name,"geometry",(char *) NULL);
14682 windows->widget.border_width=0;
14683 windows->widget.flags|=PPosition;
14684 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14685 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14686 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14687 StructureNotifyMask;
14688 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14689 manager_hints->input=MagickTrue;
14690 manager_hints->initial_state=NormalState;
14691 manager_hints->window_group=windows->image.id;
14692 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14694 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14695 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14696 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14697 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14698 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14699 if (display_image->debug != MagickFalse)
14700 (void) LogMagickEvent(X11Event,GetMagickModule(),
14701 "Window id: 0x%lx (widget)",windows->widget.id);
14703 Initialize popup window.
14705 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14706 resource_info,&windows->popup);
14707 windows->popup.border_width=0;
14708 windows->popup.flags|=PPosition;
14709 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14710 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14711 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14712 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14713 manager_hints->input=MagickTrue;
14714 manager_hints->initial_state=NormalState;
14715 manager_hints->window_group=windows->image.id;
14716 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14718 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14719 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14720 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14721 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14722 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14723 if (display_image->debug != MagickFalse)
14724 (void) LogMagickEvent(X11Event,GetMagickModule(),
14725 "Window id: 0x%lx (pop up)",windows->popup.id);
14727 Initialize Magnify window and cursor.
14729 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14730 resource_info,&windows->magnify);
14731 if (resource_info->use_shared_memory == MagickFalse)
14732 windows->magnify.shared_memory=MagickFalse;
14733 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.magnify",
14734 resource_info->client_name);
14735 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14736 resource_name,"geometry",(char *) NULL);
14737 (void) FormatMagickString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14738 resource_info->magnify);
14739 if (windows->magnify.cursor != (Cursor) NULL)
14740 (void) XFreeCursor(display,windows->magnify.cursor);
14741 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14742 map_info->colormap,resource_info->background_color,
14743 resource_info->foreground_color);
14744 if (windows->magnify.cursor == (Cursor) NULL)
14745 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14746 display_image->filename);
14747 windows->magnify.width=MagnifySize;
14748 windows->magnify.height=MagnifySize;
14749 windows->magnify.flags|=PPosition;
14750 windows->magnify.min_width=MagnifySize;
14751 windows->magnify.min_height=MagnifySize;
14752 windows->magnify.width_inc=MagnifySize;
14753 windows->magnify.height_inc=MagnifySize;
14754 windows->magnify.data=resource_info->magnify;
14755 windows->magnify.attributes.cursor=windows->magnify.cursor;
14756 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14757 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14758 StructureNotifyMask;
14759 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14760 manager_hints->input=MagickTrue;
14761 manager_hints->initial_state=NormalState;
14762 manager_hints->window_group=windows->image.id;
14763 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14764 &windows->magnify);
14765 if (display_image->debug != MagickFalse)
14766 (void) LogMagickEvent(X11Event,GetMagickModule(),
14767 "Window id: 0x%lx (magnify)",windows->magnify.id);
14768 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14770 Initialize panning window.
14772 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14773 resource_info,&windows->pan);
14774 (void) CloneString(&windows->pan.name,"Pan Icon");
14775 windows->pan.width=windows->icon.width;
14776 windows->pan.height=windows->icon.height;
14777 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.pan",
14778 resource_info->client_name);
14779 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14780 resource_name,"geometry",(char *) NULL);
14781 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14782 &windows->pan.width,&windows->pan.height);
14783 windows->pan.flags|=PPosition;
14784 windows->pan.immutable=MagickTrue;
14785 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14786 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
14787 StructureNotifyMask;
14788 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14789 manager_hints->input=MagickFalse;
14790 manager_hints->initial_state=NormalState;
14791 manager_hints->window_group=windows->image.id;
14792 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14794 if (display_image->debug != MagickFalse)
14795 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
14797 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
14798 if (windows->info.mapped != MagickFalse)
14799 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14800 if ((windows->image.mapped == MagickFalse) ||
14801 (windows->backdrop.id != (Window) NULL))
14802 (void) XMapWindow(display,windows->image.id);
14804 Set our progress monitor and warning handlers.
14806 if (warning_handler == (WarningHandler) NULL)
14808 warning_handler=resource_info->display_warnings ?
14809 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14810 warning_handler=resource_info->display_warnings ?
14811 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14814 Initialize Image and Magnify X images.
14816 windows->image.x=0;
14817 windows->image.y=0;
14818 windows->magnify.shape=MagickFalse;
14819 width=(unsigned int) display_image->columns;
14820 height=(unsigned int) display_image->rows;
14821 if ((display_image->columns != width) || (display_image->rows != height))
14822 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14823 display_image->filename);
14824 status=XMakeImage(display,resource_info,&windows->image,display_image,
14826 if (status == MagickFalse)
14827 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14828 display_image->filename);
14829 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
14830 windows->magnify.width,windows->magnify.height);
14831 if (status == MagickFalse)
14832 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14833 display_image->filename);
14834 if (windows->magnify.mapped != MagickFalse)
14835 (void) XMapRaised(display,windows->magnify.id);
14836 if (windows->pan.mapped != MagickFalse)
14837 (void) XMapRaised(display,windows->pan.id);
14838 windows->image.window_changes.width=(int) display_image->columns;
14839 windows->image.window_changes.height=(int) display_image->rows;
14840 (void) XConfigureImage(display,resource_info,windows,display_image);
14841 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14842 (void) XSync(display,MagickFalse);
14846 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
14847 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
14849 if (resource_info->update != MagickFalse)
14855 Determine when file data was last modified.
14857 status=GetPathAttributes(display_image->filename,&attributes);
14858 if (status != MagickFalse)
14859 update_time=attributes.st_mtime;
14861 *state&=(~FormerImageState);
14862 *state&=(~MontageImageState);
14863 *state&=(~NextImageState);
14867 Handle a window event.
14869 if (windows->image.mapped != MagickFalse)
14870 if ((display_image->delay != 0) || (resource_info->update != 0))
14872 if (timer < time((time_t *) NULL))
14874 if (resource_info->update == MagickFalse)
14875 *state|=NextImageState | ExitState;
14882 Determine if image file was modified.
14884 status=GetPathAttributes(display_image->filename,&attributes);
14885 if (status != MagickFalse)
14886 if (update_time != attributes.st_mtime)
14891 (void) FormatMagickString(
14892 resource_info->image_info->filename,MaxTextExtent,
14893 "%s:%s",display_image->magick,
14894 display_image->filename);
14895 nexus=ReadImage(resource_info->image_info,
14896 &display_image->exception);
14897 if (nexus != (Image *) NULL)
14899 nexus=DestroyImage(nexus);
14900 *state|=NextImageState | ExitState;
14903 delay=display_image->delay/MagickMax(
14904 display_image->ticks_per_second,1L);
14905 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
14908 if (XEventsQueued(display,QueuedAfterFlush) == 0)
14911 Do not block if delay > 0.
14913 XDelay(display,SuspendTime << 2);
14917 timestamp=time((time_t *) NULL);
14918 (void) XNextEvent(display,&event);
14919 if (windows->image.stasis == MagickFalse)
14920 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
14921 MagickTrue : MagickFalse;
14922 if (windows->magnify.stasis == MagickFalse)
14923 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
14924 MagickTrue : MagickFalse;
14925 if (event.xany.window == windows->command.id)
14928 Select a command from the Command widget.
14930 id=XCommandWidget(display,windows,CommandMenu,&event);
14933 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
14934 command_type=CommandMenus[id];
14935 if (id < MagickMenus)
14938 Select a command from a pop-up menu.
14940 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
14944 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
14945 command_type=Commands[id][entry];
14947 if (command_type != NullCommand)
14948 nexus=XMagickCommand(display,resource_info,windows,command_type,
14952 switch (event.type)
14956 if (display_image->debug != MagickFalse)
14957 (void) LogMagickEvent(X11Event,GetMagickModule(),
14958 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
14959 event.xbutton.button,event.xbutton.x,event.xbutton.y);
14960 if ((event.xbutton.button == Button3) &&
14961 (event.xbutton.state & Mod1Mask))
14964 Convert Alt-Button3 to Button2.
14966 event.xbutton.button=Button2;
14967 event.xbutton.state&=(~Mod1Mask);
14969 if (event.xbutton.window == windows->backdrop.id)
14971 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
14972 event.xbutton.time);
14975 if (event.xbutton.window == windows->image.id)
14977 switch (event.xbutton.button)
14981 if (resource_info->immutable)
14984 Select a command from the Virtual menu.
14986 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
14989 nexus=XMagickCommand(display,resource_info,windows,
14990 VirtualCommands[entry],&display_image);
14994 Map/unmap Command widget.
14996 if (windows->command.mapped != MagickFalse)
14997 (void) XWithdrawWindow(display,windows->command.id,
14998 windows->command.screen);
15001 (void) XCommandWidget(display,windows,CommandMenu,
15003 (void) XMapRaised(display,windows->command.id);
15010 User pressed the image magnify button.
15012 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15014 XMagnifyImage(display,windows,&event);
15019 if (resource_info->immutable)
15022 Select a command from the Virtual menu.
15024 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15027 nexus=XMagickCommand(display,resource_info,windows,
15028 VirtualCommands[entry],&display_image);
15031 if (display_image->montage != (char *) NULL)
15034 Open or delete a tile from a visual image directory.
15036 nexus=XTileImage(display,resource_info,windows,
15037 display_image,&event);
15038 if (nexus != (Image *) NULL)
15039 *state|=MontageImageState | NextImageState | ExitState;
15040 vid_info.x=windows->image.x;
15041 vid_info.y=windows->image.y;
15045 Select a command from the Short Cuts menu.
15047 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15050 nexus=XMagickCommand(display,resource_info,windows,
15051 ShortCutsCommands[entry],&display_image);
15059 XTranslateImage(display,windows,*image,XK_Up);
15067 XTranslateImage(display,windows,*image,XK_Down);
15075 if (event.xbutton.window == windows->magnify.id)
15095 MagnifyCommands[] =
15108 Select a magnify factor from the pop-up menu.
15110 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15112 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor]);
15115 if (event.xbutton.window == windows->pan.id)
15117 switch (event.xbutton.button)
15124 XTranslateImage(display,windows,*image,XK_Up);
15132 XTranslateImage(display,windows,*image,XK_Down);
15137 XPanImage(display,windows,&event);
15143 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15145 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15148 case ButtonRelease:
15150 if (display_image->debug != MagickFalse)
15151 (void) LogMagickEvent(X11Event,GetMagickModule(),
15152 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15153 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15156 case ClientMessage:
15158 if (display_image->debug != MagickFalse)
15159 (void) LogMagickEvent(X11Event,GetMagickModule(),
15160 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15161 event.xclient.message_type,event.xclient.format,(unsigned long)
15162 event.xclient.data.l[0]);
15163 if (event.xclient.message_type == windows->im_protocols)
15165 if (*event.xclient.data.l == (long) windows->im_update_widget)
15167 (void) CloneString(&windows->command.name,MagickTitle);
15168 windows->command.data=MagickMenus;
15169 (void) XCommandWidget(display,windows,CommandMenu,
15173 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15176 Update graphic context and window colormap.
15178 for (i=0; i < (int) number_windows; i++)
15180 if (magick_windows[i]->id == windows->icon.id)
15182 context_values.background=pixel->background_color.pixel;
15183 context_values.foreground=pixel->foreground_color.pixel;
15184 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15185 context_mask,&context_values);
15186 (void) XChangeGC(display,magick_windows[i]->widget_context,
15187 context_mask,&context_values);
15188 context_values.background=pixel->foreground_color.pixel;
15189 context_values.foreground=pixel->background_color.pixel;
15190 context_values.plane_mask=context_values.background ^
15191 context_values.foreground;
15192 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15193 (size_t) (context_mask | GCPlaneMask),
15195 magick_windows[i]->attributes.background_pixel=
15196 pixel->background_color.pixel;
15197 magick_windows[i]->attributes.border_pixel=
15198 pixel->border_color.pixel;
15199 magick_windows[i]->attributes.colormap=map_info->colormap;
15200 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15201 magick_windows[i]->mask,&magick_windows[i]->attributes);
15203 if (windows->pan.mapped != MagickFalse)
15205 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15206 windows->pan.pixmap);
15207 (void) XClearWindow(display,windows->pan.id);
15208 XDrawPanRectangle(display,windows);
15210 if (windows->backdrop.id != (Window) NULL)
15211 (void) XInstallColormap(display,map_info->colormap);
15214 if (*event.xclient.data.l == (long) windows->im_former_image)
15216 *state|=FormerImageState | ExitState;
15219 if (*event.xclient.data.l == (long) windows->im_next_image)
15221 *state|=NextImageState | ExitState;
15224 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15226 *state|=RetainColorsState;
15229 if (*event.xclient.data.l == (long) windows->im_exit)
15236 if (event.xclient.message_type == windows->dnd_protocols)
15254 Display image named by the Drag-and-Drop selection.
15256 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15258 selection=XInternAtom(display,"DndSelection",MagickFalse);
15259 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15260 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15261 &length,&after,&data);
15262 if ((status != Success) || (length == 0))
15264 if (*event.xclient.data.l == 2)
15269 (void) CopyMagickString(resource_info->image_info->filename,
15270 (char *) data,MaxTextExtent);
15277 if (strncmp((char *) data, "file:", 5) != 0)
15279 (void) XFree((void *) data);
15282 (void) CopyMagickString(resource_info->image_info->filename,
15283 ((char *) data)+5,MaxTextExtent);
15285 nexus=ReadImage(resource_info->image_info,
15286 &display_image->exception);
15287 CatchException(&display_image->exception);
15288 if (nexus != (Image *) NULL)
15289 *state|=NextImageState | ExitState;
15290 (void) XFree((void *) data);
15294 If client window delete message, exit.
15296 if (event.xclient.message_type != windows->wm_protocols)
15298 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15300 (void) XWithdrawWindow(display,event.xclient.window,
15301 visual_info->screen);
15302 if (event.xclient.window == windows->image.id)
15307 if (event.xclient.window == windows->pan.id)
15310 Restore original image size when pan window is deleted.
15312 windows->image.window_changes.width=windows->image.ximage->width;
15313 windows->image.window_changes.height=windows->image.ximage->height;
15314 (void) XConfigureImage(display,resource_info,windows,
15319 case ConfigureNotify:
15321 if (display_image->debug != MagickFalse)
15322 (void) LogMagickEvent(X11Event,GetMagickModule(),
15323 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15324 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15325 event.xconfigure.y,event.xconfigure.send_event);
15326 if (event.xconfigure.window == windows->image.id)
15329 Image window has a new configuration.
15331 if (event.xconfigure.send_event != 0)
15337 Position the transient windows relative of the Image window.
15339 if (windows->command.geometry == (char *) NULL)
15340 if (windows->command.mapped == MagickFalse)
15342 windows->command.x=event.xconfigure.x-
15343 windows->command.width-25;
15344 windows->command.y=event.xconfigure.y;
15345 XConstrainWindowPosition(display,&windows->command);
15346 window_changes.x=windows->command.x;
15347 window_changes.y=windows->command.y;
15348 (void) XReconfigureWMWindow(display,windows->command.id,
15349 windows->command.screen,(unsigned int) (CWX | CWY),
15352 if (windows->widget.geometry == (char *) NULL)
15353 if (windows->widget.mapped == MagickFalse)
15355 windows->widget.x=event.xconfigure.x+
15356 event.xconfigure.width/10;
15357 windows->widget.y=event.xconfigure.y+
15358 event.xconfigure.height/10;
15359 XConstrainWindowPosition(display,&windows->widget);
15360 window_changes.x=windows->widget.x;
15361 window_changes.y=windows->widget.y;
15362 (void) XReconfigureWMWindow(display,windows->widget.id,
15363 windows->widget.screen,(unsigned int) (CWX | CWY),
15366 if (windows->magnify.geometry == (char *) NULL)
15367 if (windows->magnify.mapped == MagickFalse)
15369 windows->magnify.x=event.xconfigure.x+
15370 event.xconfigure.width+25;
15371 windows->magnify.y=event.xconfigure.y;
15372 XConstrainWindowPosition(display,&windows->magnify);
15373 window_changes.x=windows->magnify.x;
15374 window_changes.y=windows->magnify.y;
15375 (void) XReconfigureWMWindow(display,windows->magnify.id,
15376 windows->magnify.screen,(unsigned int) (CWX | CWY),
15379 if (windows->pan.geometry == (char *) NULL)
15380 if (windows->pan.mapped == MagickFalse)
15382 windows->pan.x=event.xconfigure.x+
15383 event.xconfigure.width+25;
15384 windows->pan.y=event.xconfigure.y+
15385 windows->magnify.height+50;
15386 XConstrainWindowPosition(display,&windows->pan);
15387 window_changes.x=windows->pan.x;
15388 window_changes.y=windows->pan.y;
15389 (void) XReconfigureWMWindow(display,windows->pan.id,
15390 windows->pan.screen,(unsigned int) (CWX | CWY),
15394 if ((event.xconfigure.width == (int) windows->image.width) &&
15395 (event.xconfigure.height == (int) windows->image.height))
15397 windows->image.width=(unsigned int) event.xconfigure.width;
15398 windows->image.height=(unsigned int) event.xconfigure.height;
15399 windows->image.x=0;
15400 windows->image.y=0;
15401 if (display_image->montage != (char *) NULL)
15403 windows->image.x=vid_info.x;
15404 windows->image.y=vid_info.y;
15406 if ((windows->image.mapped != MagickFalse) &&
15407 (windows->image.stasis != MagickFalse))
15410 Update image window configuration.
15412 windows->image.window_changes.width=event.xconfigure.width;
15413 windows->image.window_changes.height=event.xconfigure.height;
15414 (void) XConfigureImage(display,resource_info,windows,
15418 Update pan window configuration.
15420 if ((event.xconfigure.width < windows->image.ximage->width) ||
15421 (event.xconfigure.height < windows->image.ximage->height))
15423 (void) XMapRaised(display,windows->pan.id);
15424 XDrawPanRectangle(display,windows);
15427 if (windows->pan.mapped != MagickFalse)
15428 (void) XWithdrawWindow(display,windows->pan.id,
15429 windows->pan.screen);
15432 if (event.xconfigure.window == windows->magnify.id)
15438 Magnify window has a new configuration.
15440 windows->magnify.width=(unsigned int) event.xconfigure.width;
15441 windows->magnify.height=(unsigned int) event.xconfigure.height;
15442 if (windows->magnify.mapped == MagickFalse)
15445 while ((int) magnify <= event.xconfigure.width)
15447 while ((int) magnify <= event.xconfigure.height)
15450 if (((int) magnify != event.xconfigure.width) ||
15451 ((int) magnify != event.xconfigure.height))
15453 window_changes.width=(int) magnify;
15454 window_changes.height=(int) magnify;
15455 (void) XReconfigureWMWindow(display,windows->magnify.id,
15456 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15460 if ((windows->magnify.mapped != MagickFalse) &&
15461 (windows->magnify.stasis != MagickFalse))
15463 status=XMakeImage(display,resource_info,&windows->magnify,
15464 display_image,windows->magnify.width,windows->magnify.height);
15465 XMakeMagnifyImage(display,windows);
15469 if ((windows->magnify.mapped != MagickFalse) &&
15470 (event.xconfigure.window == windows->pan.id))
15473 Pan icon window has a new configuration.
15475 if (event.xconfigure.send_event != 0)
15477 windows->pan.x=event.xconfigure.x;
15478 windows->pan.y=event.xconfigure.y;
15480 windows->pan.width=(unsigned int) event.xconfigure.width;
15481 windows->pan.height=(unsigned int) event.xconfigure.height;
15484 if (event.xconfigure.window == windows->icon.id)
15487 Icon window has a new configuration.
15489 windows->icon.width=(unsigned int) event.xconfigure.width;
15490 windows->icon.height=(unsigned int) event.xconfigure.height;
15495 case DestroyNotify:
15498 Group leader has exited.
15500 if (display_image->debug != MagickFalse)
15501 (void) LogMagickEvent(X11Event,GetMagickModule(),
15502 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15503 if (event.xdestroywindow.window == windows->group_leader.id)
15513 Selectively install colormap.
15515 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15516 if (event.xcrossing.mode != NotifyUngrab)
15517 XInstallColormap(display,map_info->colormap);
15522 if (display_image->debug != MagickFalse)
15523 (void) LogMagickEvent(X11Event,GetMagickModule(),
15524 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15525 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15528 Refresh windows that are now exposed.
15530 if ((event.xexpose.window == windows->image.id) &&
15531 (windows->image.mapped != MagickFalse))
15533 XRefreshWindow(display,&windows->image,&event);
15534 delay=display_image->delay/MagickMax(
15535 display_image->ticks_per_second,1L);
15536 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15539 if ((event.xexpose.window == windows->magnify.id) &&
15540 (windows->magnify.mapped != MagickFalse))
15542 XMakeMagnifyImage(display,windows);
15545 if (event.xexpose.window == windows->pan.id)
15547 XDrawPanRectangle(display,windows);
15550 if (event.xexpose.window == windows->icon.id)
15552 XRefreshWindow(display,&windows->icon,&event);
15563 Respond to a user key press.
15565 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15566 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15567 *(command+length)='\0';
15568 if (display_image->debug != MagickFalse)
15569 (void) LogMagickEvent(X11Event,GetMagickModule(),
15570 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15571 key_symbol,command);
15572 if (event.xkey.window == windows->image.id)
15574 command_type=XImageWindowCommand(display,resource_info,windows,
15575 event.xkey.state,key_symbol,&display_image);
15576 if (command_type != NullCommand)
15577 nexus=XMagickCommand(display,resource_info,windows,command_type,
15580 if (event.xkey.window == windows->magnify.id)
15581 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol);
15582 if (event.xkey.window == windows->pan.id)
15584 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15585 (void) XWithdrawWindow(display,windows->pan.id,
15586 windows->pan.screen);
15588 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15589 XTextViewWidget(display,resource_info,windows,MagickFalse,
15590 "Help Viewer - Image Pan",ImagePanHelp);
15592 XTranslateImage(display,windows,*image,key_symbol);
15594 delay=display_image->delay/MagickMax(
15595 display_image->ticks_per_second,1L);
15596 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15602 Respond to a user key release.
15604 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15605 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15606 if (display_image->debug != MagickFalse)
15607 (void) LogMagickEvent(X11Event,GetMagickModule(),
15608 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15614 Selectively uninstall colormap.
15616 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15617 if (event.xcrossing.mode != NotifyUngrab)
15618 XUninstallColormap(display,map_info->colormap);
15623 if (display_image->debug != MagickFalse)
15624 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15625 event.xmap.window);
15626 if (event.xmap.window == windows->backdrop.id)
15628 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15630 windows->backdrop.mapped=MagickTrue;
15633 if (event.xmap.window == windows->image.id)
15635 if (windows->backdrop.id != (Window) NULL)
15636 (void) XInstallColormap(display,map_info->colormap);
15637 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15639 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15640 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15642 if (((int) windows->image.width < windows->image.ximage->width) ||
15643 ((int) windows->image.height < windows->image.ximage->height))
15644 (void) XMapRaised(display,windows->pan.id);
15645 windows->image.mapped=MagickTrue;
15648 if (event.xmap.window == windows->magnify.id)
15650 XMakeMagnifyImage(display,windows);
15651 windows->magnify.mapped=MagickTrue;
15652 (void) XWithdrawWindow(display,windows->info.id,
15653 windows->info.screen);
15656 if (event.xmap.window == windows->pan.id)
15658 XMakePanImage(display,resource_info,windows,display_image);
15659 windows->pan.mapped=MagickTrue;
15662 if (event.xmap.window == windows->info.id)
15664 windows->info.mapped=MagickTrue;
15667 if (event.xmap.window == windows->icon.id)
15673 Create an icon image.
15675 taint=display_image->taint;
15676 XMakeStandardColormap(display,icon_visual,icon_resources,
15677 display_image,icon_map,icon_pixel);
15678 (void) XMakeImage(display,icon_resources,&windows->icon,
15679 display_image,windows->icon.width,windows->icon.height);
15680 display_image->taint=taint;
15681 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15682 windows->icon.pixmap);
15683 (void) XClearWindow(display,windows->icon.id);
15684 (void) XWithdrawWindow(display,windows->info.id,
15685 windows->info.screen);
15686 windows->icon.mapped=MagickTrue;
15689 if (event.xmap.window == windows->command.id)
15691 windows->command.mapped=MagickTrue;
15694 if (event.xmap.window == windows->popup.id)
15696 windows->popup.mapped=MagickTrue;
15699 if (event.xmap.window == windows->widget.id)
15701 windows->widget.mapped=MagickTrue;
15706 case MappingNotify:
15708 (void) XRefreshKeyboardMapping(&event.xmapping);
15713 case PropertyNotify:
15729 if (display_image->debug != MagickFalse)
15730 (void) LogMagickEvent(X11Event,GetMagickModule(),
15731 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15732 event.xproperty.atom,event.xproperty.state);
15733 if (event.xproperty.atom != windows->im_remote_command)
15736 Display image named by the remote command protocol.
15738 status=XGetWindowProperty(display,event.xproperty.window,
15739 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15740 AnyPropertyType,&type,&format,&length,&after,&data);
15741 if ((status != Success) || (length == 0))
15743 if (LocaleCompare((char *) data,"-quit") == 0)
15745 XClientMessage(display,windows->image.id,windows->im_protocols,
15746 windows->im_exit,CurrentTime);
15747 (void) XFree((void *) data);
15750 (void) CopyMagickString(resource_info->image_info->filename,
15751 (char *) data,MaxTextExtent);
15752 (void) XFree((void *) data);
15753 nexus=ReadImage(resource_info->image_info,&display_image->exception);
15754 CatchException(&display_image->exception);
15755 if (nexus != (Image *) NULL)
15756 *state|=NextImageState | ExitState;
15759 case ReparentNotify:
15761 if (display_image->debug != MagickFalse)
15762 (void) LogMagickEvent(X11Event,GetMagickModule(),
15763 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15764 event.xreparent.window);
15769 if (display_image->debug != MagickFalse)
15770 (void) LogMagickEvent(X11Event,GetMagickModule(),
15771 "Unmap Notify: 0x%lx",event.xunmap.window);
15772 if (event.xunmap.window == windows->backdrop.id)
15774 windows->backdrop.mapped=MagickFalse;
15777 if (event.xunmap.window == windows->image.id)
15779 windows->image.mapped=MagickFalse;
15782 if (event.xunmap.window == windows->magnify.id)
15784 windows->magnify.mapped=MagickFalse;
15787 if (event.xunmap.window == windows->pan.id)
15789 windows->pan.mapped=MagickFalse;
15792 if (event.xunmap.window == windows->info.id)
15794 windows->info.mapped=MagickFalse;
15797 if (event.xunmap.window == windows->icon.id)
15799 if (map_info->colormap == icon_map->colormap)
15800 XConfigureImageColormap(display,resource_info,windows,
15802 (void) XFreeStandardColormap(display,icon_visual,icon_map,
15804 windows->icon.mapped=MagickFalse;
15807 if (event.xunmap.window == windows->command.id)
15809 windows->command.mapped=MagickFalse;
15812 if (event.xunmap.window == windows->popup.id)
15814 if (windows->backdrop.id != (Window) NULL)
15815 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
15817 windows->popup.mapped=MagickFalse;
15820 if (event.xunmap.window == windows->widget.id)
15822 if (windows->backdrop.id != (Window) NULL)
15823 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
15825 windows->widget.mapped=MagickFalse;
15832 if (display_image->debug != MagickFalse)
15833 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
15838 } while (!(*state & ExitState));
15839 if ((*state & ExitState) == 0)
15840 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
15843 if (resource_info->confirm_edit != MagickFalse)
15846 Query user if image has changed.
15848 if ((resource_info->immutable == MagickFalse) &&
15849 (display_image->taint != MagickFalse))
15854 status=XConfirmWidget(display,windows,"Your image changed.",
15855 "Do you want to save it");
15857 *state&=(~ExitState);
15860 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
15864 if ((windows->visual_info->klass == GrayScale) ||
15865 (windows->visual_info->klass == PseudoColor) ||
15866 (windows->visual_info->klass == DirectColor))
15869 Withdraw pan and Magnify window.
15871 if (windows->info.mapped != MagickFalse)
15872 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15873 if (windows->magnify.mapped != MagickFalse)
15874 (void) XWithdrawWindow(display,windows->magnify.id,
15875 windows->magnify.screen);
15876 if (windows->command.mapped != MagickFalse)
15877 (void) XWithdrawWindow(display,windows->command.id,
15878 windows->command.screen);
15880 if (windows->pan.mapped != MagickFalse)
15881 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
15882 if (resource_info->backdrop == MagickFalse)
15883 if (windows->backdrop.mapped)
15885 (void) XWithdrawWindow(display,windows->backdrop.id,
15886 windows->backdrop.screen);
15887 (void) XDestroyWindow(display,windows->backdrop.id);
15888 windows->backdrop.id=(Window) NULL;
15889 (void) XWithdrawWindow(display,windows->image.id,
15890 windows->image.screen);
15891 (void) XDestroyWindow(display,windows->image.id);
15892 windows->image.id=(Window) NULL;
15894 XSetCursorState(display,windows,MagickTrue);
15895 XCheckRefreshWindows(display,windows);
15896 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
15897 *state&=(~ExitState);
15898 if (*state & ExitState)
15901 Free Standard Colormap.
15903 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
15904 if (resource_info->map_type == (char *) NULL)
15905 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
15909 if (resource_info->copy_image != (Image *) NULL)
15911 resource_info->copy_image=DestroyImage(resource_info->copy_image);
15912 resource_info->copy_image=NewImageList();
15914 DestroyXResources();
15916 (void) XSync(display,MagickFalse);
15918 Restore our progress monitor and warning handlers.
15920 (void) SetErrorHandler(warning_handler);
15921 (void) SetWarningHandler(warning_handler);
15923 Change to home directory.
15925 cwd=getcwd(working_directory,MaxTextExtent);
15930 status=chdir(resource_info->home_directory);
15932 (void) ThrowMagickException(&display_image->exception,GetMagickModule(),
15933 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
15935 *image=display_image;
15941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15945 + D i s p l a y I m a g e s %
15949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15951 % DisplayImages() displays an image sequence to any X window screen. It
15952 % returns a value other than 0 if successful. Check the exception member
15953 % of image to determine the reason for any failure.
15955 % The format of the DisplayImages method is:
15957 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
15960 % A description of each parameter follows:
15962 % o image_info: the image info.
15964 % o image: the image.
15967 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
15970 assert(image_info != (const ImageInfo *) NULL);
15971 assert(image_info->signature == MagickSignature);
15972 assert(image != (Image *) NULL);
15973 assert(image->signature == MagickSignature);
15974 if (image->debug != MagickFalse)
15975 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
15976 (void) ThrowMagickException(&image->exception,GetMagickModule(),
15977 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
15979 return(MagickFalse);
15983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15987 + R e m o t e D i s p l a y C o m m a n d %
15991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15993 % RemoteDisplayCommand() encourages a remote display program to display the
15994 % specified image filename.
15996 % The format of the RemoteDisplayCommand method is:
15998 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
15999 % const char *window,const char *filename,ExceptionInfo *exception)
16001 % A description of each parameter follows:
16003 % o image_info: the image info.
16005 % o window: Specifies the name or id of an X window.
16007 % o filename: the name of the image filename to display.
16009 % o exception: return any errors or warnings in this structure.
16012 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16013 const char *window,const char *filename,ExceptionInfo *exception)
16015 assert(image_info != (const ImageInfo *) NULL);
16016 assert(image_info->signature == MagickSignature);
16017 assert(filename != (char *) NULL);
16019 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16020 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16021 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename);
16022 return(MagickFalse);