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-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/artifact.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/cache-private.h"
47 #include "MagickCore/client.h"
48 #include "MagickCore/color.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/composite.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/decorate.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/display.h"
55 #include "MagickCore/display-private.h"
56 #include "MagickCore/draw.h"
57 #include "MagickCore/effect.h"
58 #include "MagickCore/enhance.h"
59 #include "MagickCore/exception.h"
60 #include "MagickCore/exception-private.h"
61 #include "MagickCore/fx.h"
62 #include "MagickCore/geometry.h"
63 #include "MagickCore/image.h"
64 #include "MagickCore/image-private.h"
65 #include "MagickCore/list.h"
66 #include "MagickCore/log.h"
67 #include "MagickCore/magick.h"
68 #include "MagickCore/memory_.h"
69 #include "MagickCore/monitor.h"
70 #include "MagickCore/monitor-private.h"
71 #include "MagickCore/montage.h"
72 #include "MagickCore/option.h"
73 #include "MagickCore/paint.h"
74 #include "MagickCore/pixel.h"
75 #include "MagickCore/pixel-accessor.h"
76 #include "MagickCore/PreRvIcccm.h"
77 #include "MagickCore/property.h"
78 #include "MagickCore/quantum.h"
79 #include "MagickCore/quantum-private.h"
80 #include "MagickCore/resize.h"
81 #include "MagickCore/resource_.h"
82 #include "MagickCore/shear.h"
83 #include "MagickCore/segment.h"
84 #include "MagickCore/string_.h"
85 #include "MagickCore/string-private.h"
86 #include "MagickCore/transform.h"
87 #include "MagickCore/threshold.h"
88 #include "MagickCore/utility.h"
89 #include "MagickCore/utility-private.h"
90 #include "MagickCore/version.h"
91 #include "MagickCore/widget.h"
92 #include "MagickCore/widget-private.h"
93 #include "MagickCore/xwindow.h"
94 #include "MagickCore/xwindow-private.h"
96 #if defined(MAGICKCORE_X11_DELEGATE)
100 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
103 Constant declarations.
105 static const unsigned char
108 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
112 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
140 Help widget declarations.
143 *ImageAnnotateHelp[] =
145 "In annotate mode, the Command widget has these options:",
195 "Choose a font name from the Font Name sub-menu. Additional",
196 "font names can be specified with the font browser. You can",
197 "change the menu names by setting the X resources font1",
200 "Choose a font color from the Font Color sub-menu.",
201 "Additional font colors can be specified with the color",
202 "browser. You can change the menu colors by setting the X",
203 "resources pen1 through pen9.",
205 "If you select the color browser and press Grab, you can",
206 "choose the font color by moving the pointer to the desired",
207 "color on the screen and press any button.",
209 "If you choose to rotate the text, choose Rotate Text from the",
210 "menu and select an angle. Typically you will only want to",
211 "rotate one line of text at a time. Depending on the angle you",
212 "choose, subsequent lines may end up overwriting each other.",
214 "Choosing a font and its color is optional. The default font",
215 "is fixed and the default color is black. However, you must",
216 "choose a location to begin entering text and press button 1.",
217 "An underscore character will appear at the location of the",
218 "pointer. The cursor changes to a pencil to indicate you are",
219 "in text mode. To exit immediately, press Dismiss.",
221 "In text mode, any key presses will display the character at",
222 "the location of the underscore and advance the underscore",
223 "cursor. Enter your text and once completed press Apply to",
224 "finish your image annotation. To correct errors press BACK",
225 "SPACE. To delete an entire line of text, press DELETE. Any",
226 "text that exceeds the boundaries of the image window is",
227 "automagically continued onto the next line.",
229 "The actual color you request for the font is saved in the",
230 "image. However, the color that appears in your image window",
231 "may be different. For example, on a monochrome screen the",
232 "text will appear black or white even if you choose the color",
233 "red as the font color. However, the image saved to a file",
234 "with -write is written with red lettering. To assure the",
235 "correct color text in the final image, any PseudoClass image",
236 "is promoted to DirectClass (see miff(5)). To force a",
237 "PseudoClass image to remain PseudoClass, use -colors.",
242 "In chop mode, the Command widget has these options:",
250 "If the you choose the horizontal direction (this the",
251 "default), the area of the image between the two horizontal",
252 "endpoints of the chop line is removed. Otherwise, the area",
253 "of the image between the two vertical endpoints of the chop",
256 "Select a location within the image window to begin your chop,",
257 "press and hold any button. Next, move the pointer to",
258 "another location in the image. As you move a line will",
259 "connect the initial location and the pointer. When you",
260 "release the button, the area within the image to chop is",
261 "determined by which direction you choose from the Command",
264 "To cancel the image chopping, move the pointer back to the",
265 "starting point of the line and release the button.",
268 *ImageColorEditHelp[] =
270 "In color edit mode, the Command widget has these options:",
311 "Choose a color editing method from the Method sub-menu",
312 "of the Command widget. The point method recolors any pixel",
313 "selected with the pointer until the button is released. The",
314 "replace method recolors any pixel that matches the color of",
315 "the pixel you select with a button press. Floodfill recolors",
316 "any pixel that matches the color of the pixel you select with",
317 "a button press and is a neighbor. Whereas filltoborder recolors",
318 "any neighbor pixel that is not the border color. Finally reset",
319 "changes the entire image to the designated color.",
321 "Next, choose a pixel color from the Pixel Color sub-menu.",
322 "Additional pixel colors can be specified with the color",
323 "browser. You can change the menu colors by setting the X",
324 "resources pen1 through pen9.",
326 "Now press button 1 to select a pixel within the image window",
327 "to change its color. Additional pixels may be recolored as",
328 "prescribed by the method you choose.",
330 "If the Magnify widget is mapped, it can be helpful in positioning",
331 "your pointer within the image (refer to button 2).",
333 "The actual color you request for the pixels is saved in the",
334 "image. However, the color that appears in your image window",
335 "may be different. For example, on a monochrome screen the",
336 "pixel will appear black or white even if you choose the",
337 "color red as the pixel color. However, the image saved to a",
338 "file with -write is written with red pixels. To assure the",
339 "correct color text in the final image, any PseudoClass image",
340 "is promoted to DirectClass (see miff(5)). To force a",
341 "PseudoClass image to remain PseudoClass, use -colors.",
344 *ImageCompositeHelp[] =
346 "First a widget window is displayed requesting you to enter an",
347 "image name. Press Composite, Grab or type a file name.",
348 "Press Cancel if you choose not to create a composite image.",
349 "When you choose Grab, move the pointer to the desired window",
350 "and press any button.",
352 "If the Composite image does not have any matte information,",
353 "you are informed and the file browser is displayed again.",
354 "Enter the name of a mask image. The image is typically",
355 "grayscale and the same size as the composite image. If the",
356 "image is not grayscale, it is converted to grayscale and the",
357 "resulting intensities are used as matte information.",
359 "A small window appears showing the location of the cursor in",
360 "the image window. You are now in composite mode. To exit",
361 "immediately, press Dismiss. In composite mode, the Command",
362 "widget has these options:",
388 "Choose a composite operation from the Operators sub-menu of",
389 "the Command widget. How each operator behaves is described",
390 "below. Image window is the image currently displayed on",
391 "your X server and image is the image obtained with the File",
394 "Over The result is the union of the two image shapes,",
395 " with image obscuring image window in the region of",
398 "In The result is simply image cut by the shape of",
399 " image window. None of the image data of image",
400 " window is in the result.",
402 "Out The resulting image is image with the shape of",
403 " image window cut out.",
405 "Atop The result is the same shape as image image window,",
406 " with image obscuring image window where the image",
407 " shapes overlap. Note this differs from over",
408 " because the portion of image outside image window's",
409 " shape does not appear in the result.",
411 "Xor The result is the image data from both image and",
412 " image window that is outside the overlap region.",
413 " The overlap region is blank.",
415 "Plus The result is just the sum of the image data.",
416 " Output values are cropped to QuantumRange (no overflow).",
418 "Minus The result of image - image window, with underflow",
421 "Add The result of image + image window, with overflow",
422 " wrapping around (mod 256).",
424 "Subtract The result of image - image window, with underflow",
425 " wrapping around (mod 256). The add and subtract",
426 " operators can be used to perform reversible",
430 " The result of abs(image - image window). This",
431 " useful for comparing two very similar images.",
434 " The result of image * image window. This",
435 " useful for the creation of drop-shadows.",
437 "Bumpmap The result of surface normals from image * image",
440 "Copy The resulting image is image window replaced with",
441 " image. Here the matte information is ignored.",
443 "CopyRed The red layer of the image window is replace with",
444 " the red layer of the image. The other layers are",
448 " The green layer of the image window is replace with",
449 " the green layer of the image. The other layers are",
452 "CopyBlue The blue layer of the image window is replace with",
453 " the blue layer of the image. The other layers are",
457 " The matte layer of the image window is replace with",
458 " the matte layer of the image. The other layers are",
461 "The image compositor requires a matte, or alpha channel in",
462 "the image for some operations. This extra channel usually",
463 "defines a mask which represents a sort of a cookie-cutter",
464 "for the image. This the case when matte is opaque (full",
465 "coverage) for pixels inside the shape, zero outside, and",
466 "between 0 and QuantumRange on the boundary. If image does not",
467 "have a matte channel, it is initialized with 0 for any pixel",
468 "matching in color to pixel location (0,0), otherwise QuantumRange.",
470 "If you choose Dissolve, the composite operator becomes Over. The",
471 "image matte channel percent transparency is initialized to factor.",
472 "The image window is initialized to (100-factor). Where factor is the",
473 "value you specify in the Dialog widget.",
475 "Displace shifts the image pixels as defined by a displacement",
476 "map. With this option, image is used as a displacement map.",
477 "Black, within the displacement map, is a maximum positive",
478 "displacement. White is a maximum negative displacement and",
479 "middle gray is neutral. The displacement is scaled to determine",
480 "the pixel shift. By default, the displacement applies in both the",
481 "horizontal and vertical directions. However, if you specify a mask,",
482 "image is the horizontal X displacement and mask the vertical Y",
485 "Note that matte information for image window is not retained",
486 "for colormapped X server visuals (e.g. StaticColor,",
487 "StaticColor, GrayScale, PseudoColor). Correct compositing",
488 "behavior may require a TrueColor or DirectColor visual or a",
489 "Standard Colormap.",
491 "Choosing a composite operator is optional. The default",
492 "operator is replace. However, you must choose a location to",
493 "composite your image and press button 1. Press and hold the",
494 "button before releasing and an outline of the image will",
495 "appear to help you identify your location.",
497 "The actual colors of the composite image is saved. However,",
498 "the color that appears in image window may be different.",
499 "For example, on a monochrome screen image window will appear",
500 "black or white even though your composited image may have",
501 "many colors. If the image is saved to a file it is written",
502 "with the correct colors. To assure the correct colors are",
503 "saved in the final image, any PseudoClass image is promoted",
504 "to DirectClass (see miff(5)). To force a PseudoClass image",
505 "to remain PseudoClass, use -colors.",
510 "In cut mode, the Command widget has these options:",
515 "To define a cut region, press button 1 and drag. The",
516 "cut region is defined by a highlighted rectangle that",
517 "expands or contracts as it follows the pointer. Once you",
518 "are satisfied with the cut region, release the button.",
519 "You are now in rectify mode. In rectify mode, the Command",
520 "widget has these options:",
526 "You can make adjustments by moving the pointer to one of the",
527 "cut rectangle corners, pressing a button, and dragging.",
528 "Finally, press Cut to commit your copy region. To",
529 "exit without cutting the image, press Dismiss.",
534 "In copy mode, the Command widget has these options:",
539 "To define a copy region, press button 1 and drag. The",
540 "copy region is defined by a highlighted rectangle that",
541 "expands or contracts as it follows the pointer. Once you",
542 "are satisfied with the copy region, release the button.",
543 "You are now in rectify mode. In rectify mode, the Command",
544 "widget has these options:",
550 "You can make adjustments by moving the pointer to one of the",
551 "copy rectangle corners, pressing a button, and dragging.",
552 "Finally, press Copy to commit your copy region. To",
553 "exit without copying the image, press Dismiss.",
558 "In crop mode, the Command widget has these options:",
563 "To define a cropping region, press button 1 and drag. The",
564 "cropping region is defined by a highlighted rectangle that",
565 "expands or contracts as it follows the pointer. Once you",
566 "are satisfied with the cropping region, release the button.",
567 "You are now in rectify mode. In rectify mode, the Command",
568 "widget has these options:",
574 "You can make adjustments by moving the pointer to one of the",
575 "cropping rectangle corners, pressing a button, and dragging.",
576 "Finally, press Crop to commit your cropping region. To",
577 "exit without cropping the image, press Dismiss.",
582 "The cursor changes to a crosshair to indicate you are in",
583 "draw mode. To exit immediately, press Dismiss. In draw mode,",
584 "the Command widget has these options:",
629 "Choose a drawing primitive from the Element sub-menu.",
631 "Choose a color from the Color sub-menu. Additional",
632 "colors can be specified with the color browser.",
634 "If you choose the color browser and press Grab, you can",
635 "select the color by moving the pointer to the desired",
636 "color on the screen and press any button. The transparent",
637 "color updates the image matte channel and is useful for",
638 "image compositing.",
640 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
641 "Additional stipples can be specified with the file browser.",
642 "Stipples obtained from the file browser must be on disk in the",
643 "X11 bitmap format.",
645 "Choose a width, if appropriate, from the Width sub-menu. To",
646 "choose a specific width select the Dialog widget.",
648 "Choose a point in the Image window and press button 1 and",
649 "hold. Next, move the pointer to another location in the",
650 "image. As you move, a line connects the initial location and",
651 "the pointer. When you release the button, the image is",
652 "updated with the primitive you just drew. For polygons, the",
653 "image is updated when you press and release the button without",
654 "moving the pointer.",
656 "To cancel image drawing, move the pointer back to the",
657 "starting point of the line and release the button.",
663 " The effects of each button press is described below. Three",
664 " buttons are required. If you have a two button mouse,",
665 " button 1 and 3 are returned. Press ALT and button 3 to",
666 " simulate button 2.",
668 " 1 Press this button to map or unmap the Command widget.",
670 " 2 Press and drag to define a region of the image to",
673 " 3 Press and drag to choose from a select set of commands.",
674 " This button behaves differently if the image being",
675 " displayed is a visual image directory. Here, choose a",
676 " particular tile of the directory and press this button and",
677 " drag to select a command from a pop-up menu. Choose from",
678 " these menu items:",
686 " If you choose Open, the image represented by the tile is",
687 " displayed. To return to the visual image directory, choose",
688 " Next from the Command widget. Next and Former moves to the",
689 " next or former image respectively. Choose Delete to delete",
690 " a particular image tile. Finally, choose Update to",
691 " synchronize all the image tiles with their respective",
695 " The Command widget lists a number of sub-menus and commands.",
707 " Visual Directory...",
741 " Contrast Stretch...",
742 " Sigmoidal Contrast...",
770 " Charcoal Drawing...",
781 " Region of Interest...",
793 " Browse Documentation",
796 " Menu items with a indented triangle have a sub-menu. They",
797 " are represented above as the indented items. To access a",
798 " sub-menu item, move the pointer to the appropriate menu and",
799 " press a button and drag. When you find the desired sub-menu",
800 " item, release the button and the command is executed. Move",
801 " the pointer away from the sub-menu if you decide not to",
802 " execute a particular command.",
804 "KEYBOARD ACCELERATORS",
805 " Accelerators are one or two key presses that effect a",
806 " particular command. The keyboard accelerators that",
807 " display(1) understands is:",
809 " Ctl+O Press to open an image from a file.",
811 " space Press to display the next image.",
813 " If the image is a multi-paged document such as a Postscript",
814 " document, you can skip ahead several pages by preceding",
815 " this command with a number. For example to display the",
816 " third page beyond the current page, press 3<space>.",
818 " backspace Press to display the former image.",
820 " If the image is a multi-paged document such as a Postscript",
821 " document, you can skip behind several pages by preceding",
822 " this command with a number. For example to display the",
823 " third page preceding the current page, press 3<backspace>.",
825 " Ctl+S Press to write the image to a file.",
827 " Ctl+P Press to print the image to a Postscript printer.",
829 " Ctl+D Press to delete an image file.",
831 " Ctl+N Press to create a blank canvas.",
833 " Ctl+Q Press to discard all images and exit program.",
835 " Ctl+Z Press to undo last image transformation.",
837 " Ctl+R Press to redo last image transformation.",
839 " Ctl+X Press to cut a region of the image.",
841 " Ctl+C Press to copy a region of the image.",
843 " Ctl+V Press to paste a region to the image.",
845 " < Press to half the image size.",
847 " - Press to return to the original image size.",
849 " > Press to double the image size.",
851 " % Press to resize the image to a width and height you",
854 "Cmd-A Press to make any image transformations permanent."
856 " By default, any image size transformations are applied",
857 " to the original image to create the image displayed on",
858 " the X server. However, the transformations are not",
859 " permanent (i.e. the original image does not change",
860 " size only the X image does). For example, if you",
861 " press > the X image will appear to double in size,",
862 " but the original image will in fact remain the same size.",
863 " To force the original image to double in size, press >",
864 " followed by Cmd-A.",
866 " @ Press to refresh the image window.",
868 " C Press to cut out a rectangular region of the image.",
870 " [ Press to chop the image.",
872 " H Press to flop image in the horizontal direction.",
874 " V Press to flip image in the vertical direction.",
876 " / Press to rotate the image 90 degrees clockwise.",
878 " \\ Press to rotate the image 90 degrees counter-clockwise.",
880 " * Press to rotate the image the number of degrees you",
883 " S Press to shear the image the number of degrees you",
886 " R Press to roll the image.",
888 " T Press to trim the image edges.",
890 " Shft-H Press to vary the image hue.",
892 " Shft-S Press to vary the color saturation.",
894 " Shft-L Press to vary the color brightness.",
896 " Shft-G Press to gamma correct the image.",
898 " Shft-C Press to sharpen the image contrast.",
900 " Shft-Z Press to dull the image contrast.",
902 " = Press to perform histogram equalization on the image.",
904 " Shft-N Press to perform histogram normalization on the image.",
906 " Shft-~ Press to negate the colors of the image.",
908 " . Press to convert the image colors to gray.",
910 " Shft-# Press to set the maximum number of unique colors in the",
913 " F2 Press to reduce the speckles in an image.",
915 " F3 Press to eliminate peak noise from an image.",
917 " F4 Press to add noise to an image.",
919 " F5 Press to sharpen an image.",
921 " F6 Press to delete an image file.",
923 " F7 Press to threshold the image.",
925 " F8 Press to detect edges within an image.",
927 " F9 Press to emboss an image.",
929 " F10 Press to displace pixels by a random amount.",
931 " F11 Press to negate all pixels above the threshold level.",
933 " F12 Press to shade the image using a distant light source.",
935 " F13 Press to lighten or darken image edges to create a 3-D effect.",
937 " F14 Press to segment the image by color.",
939 " Meta-S Press to swirl image pixels about the center.",
941 " Meta-I Press to implode image pixels about the center.",
943 " Meta-W Press to alter an image along a sine wave.",
945 " Meta-P Press to simulate an oil painting.",
947 " Meta-C Press to simulate a charcoal drawing.",
949 " Alt-A Press to annotate the image with text.",
951 " Alt-D Press to draw on an image.",
953 " Alt-P Press to edit an image pixel color.",
955 " Alt-M Press to edit the image matte information.",
957 " Alt-V Press to composite the image with another.",
959 " Alt-B Press to add a border to the image.",
961 " Alt-F Press to add an ornamental border to the image.",
964 " Press to add an image comment.",
966 " Ctl-A Press to apply image processing techniques to a region",
969 " Shft-? Press to display information about the image.",
971 " Shft-+ Press to map the zoom image window.",
973 " Shft-P Press to preview an image enhancement, effect, or f/x.",
975 " F1 Press to display helpful information about display(1).",
977 " Find Press to browse documentation about ImageMagick.",
979 " 1-9 Press to change the level of magnification.",
981 " Use the arrow keys to move the image one pixel up, down,",
982 " left, or right within the magnify window. Be sure to first",
983 " map the magnify window by pressing button 2.",
985 " Press ALT and one of the arrow keys to trim off one pixel",
986 " from any side of the image.",
989 *ImageMatteEditHelp[] =
991 "Matte information within an image is useful for some",
992 "operations such as image compositing (See IMAGE",
993 "COMPOSITING). This extra channel usually defines a mask",
994 "which represents a sort of a cookie-cutter for the image.",
995 "This the case when matte is opaque (full coverage) for",
996 "pixels inside the shape, zero outside, and between 0 and",
997 "QuantumRange on the boundary.",
999 "A small window appears showing the location of the cursor in",
1000 "the image window. You are now in matte edit mode. To exit",
1001 "immediately, press Dismiss. In matte edit mode, the Command",
1002 "widget has these options:",
1036 "Choose a matte editing method from the Method sub-menu of",
1037 "the Command widget. The point method changes the matte value",
1038 "of any pixel selected with the pointer until the button is",
1039 "is released. The replace method changes the matte value of",
1040 "any pixel that matches the color of the pixel you select with",
1041 "a button press. Floodfill changes the matte value of any pixel",
1042 "that matches the color of the pixel you select with a button",
1043 "press and is a neighbor. Whereas filltoborder changes the matte",
1044 "value any neighbor pixel that is not the border color. Finally",
1045 "reset changes the entire image to the designated matte value.",
1047 "Choose Matte Value and pick Opaque or Transarent. For other values",
1048 "select the Dialog entry. Here a dialog appears requesting a matte",
1049 "value. The value you select is assigned as the opacity value of the",
1050 "selected pixel or pixels.",
1052 "Now, press any button to select a pixel within the image",
1053 "window to change its matte value.",
1055 "If the Magnify widget is mapped, it can be helpful in positioning",
1056 "your pointer within the image (refer to button 2).",
1058 "Matte information is only valid in a DirectClass image.",
1059 "Therefore, any PseudoClass image is promoted to DirectClass",
1060 "(see miff(5)). Note that matte information for PseudoClass",
1061 "is not retained for colormapped X server visuals (e.g.",
1062 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1063 "immediately save your image to a file (refer to Write).",
1064 "Correct matte editing behavior may require a TrueColor or",
1065 "DirectColor visual or a Standard Colormap.",
1070 "When an image exceeds the width or height of the X server",
1071 "screen, display maps a small panning icon. The rectangle",
1072 "within the panning icon shows the area that is currently",
1073 "displayed in the image window. To pan about the image,",
1074 "press any button and drag the pointer within the panning",
1075 "icon. The pan rectangle moves with the pointer and the",
1076 "image window is updated to reflect the location of the",
1077 "rectangle within the panning icon. When you have selected",
1078 "the area of the image you wish to view, release the button.",
1080 "Use the arrow keys to pan the image one pixel up, down,",
1081 "left, or right within the image window.",
1083 "The panning icon is withdrawn if the image becomes smaller",
1084 "than the dimensions of the X server screen.",
1089 "A small window appears showing the location of the cursor in",
1090 "the image window. You are now in paste mode. To exit",
1091 "immediately, press Dismiss. In paste mode, the Command",
1092 "widget has these options:",
1109 "Choose a composite operation from the Operators sub-menu of",
1110 "the Command widget. How each operator behaves is described",
1111 "below. Image window is the image currently displayed on",
1112 "your X server and image is the image obtained with the File",
1115 "Over The result is the union of the two image shapes,",
1116 " with image obscuring image window in the region of",
1119 "In The result is simply image cut by the shape of",
1120 " image window. None of the image data of image",
1121 " window is in the result.",
1123 "Out The resulting image is image with the shape of",
1124 " image window cut out.",
1126 "Atop The result is the same shape as image image window,",
1127 " with image obscuring image window where the image",
1128 " shapes overlap. Note this differs from over",
1129 " because the portion of image outside image window's",
1130 " shape does not appear in the result.",
1132 "Xor The result is the image data from both image and",
1133 " image window that is outside the overlap region.",
1134 " The overlap region is blank.",
1136 "Plus The result is just the sum of the image data.",
1137 " Output values are cropped to QuantumRange (no overflow).",
1138 " This operation is independent of the matte",
1141 "Minus The result of image - image window, with underflow",
1142 " cropped to zero.",
1144 "Add The result of image + image window, with overflow",
1145 " wrapping around (mod 256).",
1147 "Subtract The result of image - image window, with underflow",
1148 " wrapping around (mod 256). The add and subtract",
1149 " operators can be used to perform reversible",
1150 " transformations.",
1153 " The result of abs(image - image window). This",
1154 " useful for comparing two very similar images.",
1156 "Copy The resulting image is image window replaced with",
1157 " image. Here the matte information is ignored.",
1159 "CopyRed The red layer of the image window is replace with",
1160 " the red layer of the image. The other layers are",
1164 " The green layer of the image window is replace with",
1165 " the green layer of the image. The other layers are",
1168 "CopyBlue The blue layer of the image window is replace with",
1169 " the blue layer of the image. The other layers are",
1173 " The matte layer of the image window is replace with",
1174 " the matte layer of the image. The other layers are",
1177 "The image compositor requires a matte, or alpha channel in",
1178 "the image for some operations. This extra channel usually",
1179 "defines a mask which represents a sort of a cookie-cutter",
1180 "for the image. This the case when matte is opaque (full",
1181 "coverage) for pixels inside the shape, zero outside, and",
1182 "between 0 and QuantumRange on the boundary. If image does not",
1183 "have a matte channel, it is initialized with 0 for any pixel",
1184 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1186 "Note that matte information for image window is not retained",
1187 "for colormapped X server visuals (e.g. StaticColor,",
1188 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1189 "behavior may require a TrueColor or DirectColor visual or a",
1190 "Standard Colormap.",
1192 "Choosing a composite operator is optional. The default",
1193 "operator is replace. However, you must choose a location to",
1194 "paste your image and press button 1. Press and hold the",
1195 "button before releasing and an outline of the image will",
1196 "appear to help you identify your location.",
1198 "The actual colors of the pasted image is saved. However,",
1199 "the color that appears in image window may be different.",
1200 "For example, on a monochrome screen image window will appear",
1201 "black or white even though your pasted image may have",
1202 "many colors. If the image is saved to a file it is written",
1203 "with the correct colors. To assure the correct colors are",
1204 "saved in the final image, any PseudoClass image is promoted",
1205 "to DirectClass (see miff(5)). To force a PseudoClass image",
1206 "to remain PseudoClass, use -colors.",
1211 "In region of interest mode, the Command widget has these",
1217 "To define a region of interest, press button 1 and drag.",
1218 "The region of interest is defined by a highlighted rectangle",
1219 "that expands or contracts as it follows the pointer. Once",
1220 "you are satisfied with the region of interest, release the",
1221 "button. You are now in apply mode. In apply mode the",
1222 "Command widget has these options:",
1242 " Contrast Stretch",
1243 " Sigmoidal Contrast...",
1270 " Charcoal Drawing...",
1280 "You can make adjustments to the region of interest by moving",
1281 "the pointer to one of the rectangle corners, pressing a",
1282 "button, and dragging. Finally, choose an image processing",
1283 "technique from the Command widget. You can choose more than",
1284 "one image processing technique to apply to an area.",
1285 "Alternatively, you can move the region of interest before",
1286 "applying another image processing technique. To exit, press",
1290 *ImageRotateHelp[] =
1292 "In rotate mode, the Command widget has these options:",
1311 "Choose a background color from the Pixel Color sub-menu.",
1312 "Additional background colors can be specified with the color",
1313 "browser. You can change the menu colors by setting the X",
1314 "resources pen1 through pen9.",
1316 "If you choose the color browser and press Grab, you can",
1317 "select the background color by moving the pointer to the",
1318 "desired color on the screen and press any button.",
1320 "Choose a point in the image window and press this button and",
1321 "hold. Next, move the pointer to another location in the",
1322 "image. As you move a line connects the initial location and",
1323 "the pointer. When you release the button, the degree of",
1324 "image rotation is determined by the slope of the line you",
1325 "just drew. The slope is relative to the direction you",
1326 "choose from the Direction sub-menu of the Command widget.",
1328 "To cancel the image rotation, move the pointer back to the",
1329 "starting point of the line and release the button.",
1334 Enumeration declarations.
1353 VisualDirectoryCommand,
1361 OriginalSizeCommand,
1383 ContrastStretchCommand,
1384 SigmoidalContrastCommand,
1410 CharcoalDrawCommand,
1420 RegionofInterestCommand,
1426 ShowHistogramCommand,
1432 BrowseDocumentationCommand,
1434 SaveToUndoBufferCommand,
1441 AnnotateNameCommand,
1442 AnnotateFontColorCommand,
1443 AnnotateBackgroundColorCommand,
1444 AnnotateRotateCommand,
1445 AnnotateHelpCommand,
1446 AnnotateDismissCommand,
1449 ChopDirectionCommand,
1452 HorizontalChopCommand,
1453 VerticalChopCommand,
1454 ColorEditMethodCommand,
1455 ColorEditColorCommand,
1456 ColorEditBorderCommand,
1457 ColorEditFuzzCommand,
1458 ColorEditUndoCommand,
1459 ColorEditHelpCommand,
1460 ColorEditDismissCommand,
1461 CompositeOperatorsCommand,
1462 CompositeDissolveCommand,
1463 CompositeDisplaceCommand,
1464 CompositeHelpCommand,
1465 CompositeDismissCommand,
1470 RectifyDismissCommand,
1479 MatteEditBorderCommand,
1480 MatteEditFuzzCommand,
1481 MatteEditValueCommand,
1482 MatteEditUndoCommand,
1483 MatteEditHelpCommand,
1484 MatteEditDismissCommand,
1485 PasteOperatorsCommand,
1487 PasteDismissCommand,
1489 RotateDirectionCommand,
1491 RotateSharpenCommand,
1493 RotateDismissCommand,
1494 HorizontalRotateCommand,
1495 VerticalRotateCommand,
1506 #define BricksWidth 20
1507 #define BricksHeight 20
1508 #define DiagonalWidth 16
1509 #define DiagonalHeight 16
1510 #define HighlightWidth 8
1511 #define HighlightHeight 8
1512 #define OpaqueWidth 8
1513 #define OpaqueHeight 8
1514 #define ScalesWidth 16
1515 #define ScalesHeight 16
1516 #define ShadowWidth 8
1517 #define ShadowHeight 8
1518 #define VerticalWidth 16
1519 #define VerticalHeight 16
1520 #define WavyWidth 16
1521 #define WavyHeight 16
1524 Constant declaration.
1529 static const unsigned char
1532 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1533 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1534 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1535 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1536 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1540 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1541 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1542 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1546 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1547 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1548 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1552 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1553 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1554 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1558 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1559 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1560 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1564 Function prototypes.
1567 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1568 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1571 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1572 Image **,ExceptionInfo *),
1573 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1574 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1576 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1579 static MagickBooleanType
1580 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1582 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1584 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1586 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1588 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1590 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1592 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1593 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1595 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1597 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1598 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1599 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1601 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1602 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1603 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1606 XDrawPanRectangle(Display *,XWindows *),
1607 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1609 XMagnifyImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1610 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1611 XPanImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1612 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1613 const KeySym,ExceptionInfo *),
1614 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1615 XScreenEvent(Display *,XWindows *,XEvent *,ExceptionInfo *),
1616 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1623 % D i s p l a y I m a g e s %
1627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1629 % DisplayImages() displays an image sequence to any X window screen. It
1630 % returns a value other than 0 if successful. Check the exception member
1631 % of image to determine the reason for any failure.
1633 % The format of the DisplayImages method is:
1635 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1636 % Image *images,ExceptionInfo *exception)
1638 % A description of each parameter follows:
1640 % o image_info: the image info.
1642 % o image: the image.
1644 % o exception: return any errors or warnings in this structure.
1647 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1648 Image *images,ExceptionInfo *exception)
1671 assert(image_info != (const ImageInfo *) NULL);
1672 assert(image_info->signature == MagickSignature);
1673 assert(images != (Image *) NULL);
1674 assert(images->signature == MagickSignature);
1675 if (images->debug != MagickFalse)
1676 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1677 display=XOpenDisplay(image_info->server_name);
1678 if (display == (Display *) NULL)
1680 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1681 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1682 return(MagickFalse);
1684 if (exception->severity != UndefinedException)
1685 CatchException(exception);
1686 (void) XSetErrorHandler(XError);
1687 resource_database=XGetResourceDatabase(display,GetClientName());
1688 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1689 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1690 if (image_info->page != (char *) NULL)
1691 resource_info.image_geometry=AcquireString(image_info->page);
1692 resource_info.immutable=MagickTrue;
1693 argv[0]=AcquireString(GetClientName());
1695 for (i=0; (state & ExitState) == 0; i++)
1697 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1699 image=GetImageFromList(images,i % GetImageListLength(images));
1700 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1702 SetErrorHandler((ErrorHandler) NULL);
1703 SetWarningHandler((WarningHandler) NULL);
1704 argv[0]=DestroyString(argv[0]);
1705 (void) XCloseDisplay(display);
1706 XDestroyResourceInfo(&resource_info);
1707 if (exception->severity != UndefinedException)
1708 return(MagickFalse);
1713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717 % R e m o t e D i s p l a y C o m m a n d %
1721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1723 % RemoteDisplayCommand() encourages a remote display program to display the
1724 % specified image filename.
1726 % The format of the RemoteDisplayCommand method is:
1728 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1729 % const char *window,const char *filename,ExceptionInfo *exception)
1731 % A description of each parameter follows:
1733 % o image_info: the image info.
1735 % o window: Specifies the name or id of an X window.
1737 % o filename: the name of the image filename to display.
1739 % o exception: return any errors or warnings in this structure.
1742 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1743 const char *window,const char *filename,ExceptionInfo *exception)
1751 assert(image_info != (const ImageInfo *) NULL);
1752 assert(image_info->signature == MagickSignature);
1753 assert(filename != (char *) NULL);
1754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1755 display=XOpenDisplay(image_info->server_name);
1756 if (display == (Display *) NULL)
1758 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1759 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1760 return(MagickFalse);
1762 (void) XSetErrorHandler(XError);
1763 status=XRemoteCommand(display,window,filename);
1764 (void) XCloseDisplay(display);
1765 return(status != 0 ? MagickTrue : MagickFalse);
1769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1773 + X A n n o t a t e E d i t I m a g e %
1777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1779 % XAnnotateEditImage() annotates the image with text.
1781 % The format of the XAnnotateEditImage method is:
1783 % MagickBooleanType XAnnotateEditImage(Display *display,
1784 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1785 % ExceptionInfo *exception)
1787 % A description of each parameter follows:
1789 % o display: Specifies a connection to an X server; returned from
1792 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1794 % o windows: Specifies a pointer to a XWindows structure.
1796 % o image: the image; returned from ReadImage.
1800 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
1807 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
1814 static MagickBooleanType XAnnotateEditImage(Display *display,
1815 XResourceInfo *resource_info,XWindows *windows,Image *image,
1816 ExceptionInfo *exception)
1836 static const ModeType
1837 AnnotateCommands[] =
1839 AnnotateNameCommand,
1840 AnnotateFontColorCommand,
1841 AnnotateBackgroundColorCommand,
1842 AnnotateRotateCommand,
1843 AnnotateHelpCommand,
1844 AnnotateDismissCommand
1852 static MagickBooleanType
1853 transparent_box = MagickTrue,
1854 transparent_pen = MagickFalse;
1856 static MagickRealType
1860 box_id = MaxNumberPens-2,
1865 command[MaxTextExtent],
1866 text[MaxTextExtent];
1869 *ColorMenu[MaxNumberPens+1];
1917 (void) CloneString(&windows->command.name,"Annotate");
1918 windows->command.data=4;
1919 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1920 (void) XMapRaised(display,windows->command.id);
1921 XClientMessage(display,windows->image.id,windows->im_protocols,
1922 windows->im_update_widget,CurrentTime);
1924 Track pointer until button 1 is pressed.
1926 XQueryPosition(display,windows->image.id,&x,&y);
1927 (void) XSelectInput(display,windows->image.id,
1928 windows->image.attributes.event_mask | PointerMotionMask);
1929 cursor=XCreateFontCursor(display,XC_left_side);
1930 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1934 if (windows->info.mapped != MagickFalse)
1937 Display pointer position.
1939 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
1940 x+windows->image.x,y+windows->image.y);
1941 XInfoWidget(display,windows,text);
1944 Wait for next event.
1946 XScreenEvent(display,windows,&event,exception);
1947 if (event.xany.window == windows->command.id)
1950 Select a command from the Command widget.
1952 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1953 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1956 switch (AnnotateCommands[id])
1958 case AnnotateNameCommand:
1961 *FontMenu[MaxNumberFonts];
1967 Initialize menu selections.
1969 for (i=0; i < MaxNumberFonts; i++)
1970 FontMenu[i]=resource_info->font_name[i];
1971 FontMenu[MaxNumberFonts-2]="Browser...";
1972 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1974 Select a font name from the pop-up menu.
1976 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1977 (const char **) FontMenu,command);
1978 if (font_number < 0)
1980 if (font_number == (MaxNumberFonts-2))
1983 font_name[MaxTextExtent] = "fixed";
1986 Select a font name from a browser.
1988 resource_info->font_name[font_number]=font_name;
1989 XFontBrowserWidget(display,windows,"Select",font_name);
1990 if (*font_name == '\0')
1994 Initialize font info.
1996 font_info=XLoadQueryFont(display,resource_info->font_name[
1998 if (font_info == (XFontStruct *) NULL)
2000 XNoticeWidget(display,windows,"Unable to load font:",
2001 resource_info->font_name[font_number]);
2004 font_id=(unsigned int) font_number;
2005 (void) XFreeFont(display,font_info);
2008 case AnnotateFontColorCommand:
2011 Initialize menu selections.
2013 for (i=0; i < (int) (MaxNumberPens-2); i++)
2014 ColorMenu[i]=resource_info->pen_colors[i];
2015 ColorMenu[MaxNumberPens-2]="transparent";
2016 ColorMenu[MaxNumberPens-1]="Browser...";
2017 ColorMenu[MaxNumberPens]=(const char *) NULL;
2019 Select a pen color from the pop-up menu.
2021 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2022 (const char **) ColorMenu,command);
2025 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2027 if (transparent_pen != MagickFalse)
2029 if (pen_number == (MaxNumberPens-1))
2032 color_name[MaxTextExtent] = "gray";
2035 Select a pen color from a dialog.
2037 resource_info->pen_colors[pen_number]=color_name;
2038 XColorBrowserWidget(display,windows,"Select",color_name);
2039 if (*color_name == '\0')
2045 (void) XParseColor(display,windows->map_info->colormap,
2046 resource_info->pen_colors[pen_number],&color);
2047 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2048 (unsigned int) MaxColors,&color);
2049 windows->pixel_info->pen_colors[pen_number]=color;
2050 pen_id=(unsigned int) pen_number;
2053 case AnnotateBackgroundColorCommand:
2056 Initialize menu selections.
2058 for (i=0; i < (int) (MaxNumberPens-2); i++)
2059 ColorMenu[i]=resource_info->pen_colors[i];
2060 ColorMenu[MaxNumberPens-2]="transparent";
2061 ColorMenu[MaxNumberPens-1]="Browser...";
2062 ColorMenu[MaxNumberPens]=(const char *) NULL;
2064 Select a pen color from the pop-up menu.
2066 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2067 (const char **) ColorMenu,command);
2070 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2072 if (transparent_box != MagickFalse)
2074 if (pen_number == (MaxNumberPens-1))
2077 color_name[MaxTextExtent] = "gray";
2080 Select a pen color from a dialog.
2082 resource_info->pen_colors[pen_number]=color_name;
2083 XColorBrowserWidget(display,windows,"Select",color_name);
2084 if (*color_name == '\0')
2090 (void) XParseColor(display,windows->map_info->colormap,
2091 resource_info->pen_colors[pen_number],&color);
2092 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2093 (unsigned int) MaxColors,&color);
2094 windows->pixel_info->pen_colors[pen_number]=color;
2095 box_id=(unsigned int) pen_number;
2098 case AnnotateRotateCommand:
2104 angle[MaxTextExtent] = "30.0";
2122 Select a command from the pop-up menu.
2124 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2130 degrees=InterpretLocaleValue(RotateMenu[entry],(char **) NULL);
2133 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2137 degrees=InterpretLocaleValue(angle,(char **) NULL);
2140 case AnnotateHelpCommand:
2142 XTextViewWidget(display,resource_info,windows,MagickFalse,
2143 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2146 case AnnotateDismissCommand:
2164 if (event.xbutton.button != Button1)
2166 if (event.xbutton.window != windows->image.id)
2169 Change to text entering mode.
2182 if (event.xkey.window != windows->image.id)
2185 Respond to a user key press.
2187 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2188 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2189 switch ((int) key_symbol)
2204 XTextViewWidget(display,resource_info,windows,MagickFalse,
2205 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2210 (void) XBell(display,0);
2219 Map and unmap Info widget as cursor crosses its boundaries.
2223 if (windows->info.mapped != MagickFalse)
2225 if ((x < (int) (windows->info.x+windows->info.width)) &&
2226 (y < (int) (windows->info.y+windows->info.height)))
2227 (void) XWithdrawWindow(display,windows->info.id,
2228 windows->info.screen);
2231 if ((x > (int) (windows->info.x+windows->info.width)) ||
2232 (y > (int) (windows->info.y+windows->info.height)))
2233 (void) XMapWindow(display,windows->info.id);
2239 } while ((state & ExitState) == 0);
2240 (void) XSelectInput(display,windows->image.id,
2241 windows->image.attributes.event_mask);
2242 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2243 if ((state & EscapeState) != 0)
2246 Set font info and check boundary conditions.
2248 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2249 if (font_info == (XFontStruct *) NULL)
2251 XNoticeWidget(display,windows,"Unable to load font:",
2252 resource_info->font_name[font_id]);
2253 font_info=windows->font_info;
2255 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2256 x=(int) windows->image.width-font_info->max_bounds.width;
2257 if (y < (int) (font_info->ascent+font_info->descent))
2258 y=(int) font_info->ascent+font_info->descent;
2259 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2260 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2261 return(MagickFalse);
2263 Initialize annotate structure.
2265 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2266 if (annotate_info == (XAnnotateInfo *) NULL)
2267 return(MagickFalse);
2268 XGetAnnotateInfo(annotate_info);
2271 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
2272 annotate_info->stencil=OpaqueStencil;
2274 if (transparent_box == MagickFalse)
2275 annotate_info->stencil=BackgroundStencil;
2277 annotate_info->stencil=ForegroundStencil;
2278 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2279 annotate_info->degrees=degrees;
2280 annotate_info->font_info=font_info;
2281 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2282 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2283 sizeof(*annotate_info->text));
2284 if (annotate_info->text == (char *) NULL)
2285 return(MagickFalse);
2287 Create cursor and set graphic context.
2289 cursor=XCreateFontCursor(display,XC_pencil);
2290 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2291 annotate_context=windows->image.annotate_context;
2292 (void) XSetFont(display,annotate_context,font_info->fid);
2293 (void) XSetBackground(display,annotate_context,
2294 windows->pixel_info->pen_colors[box_id].pixel);
2295 (void) XSetForeground(display,annotate_context,
2296 windows->pixel_info->pen_colors[pen_id].pixel);
2298 Begin annotating the image with text.
2300 (void) CloneString(&windows->command.name,"Text");
2301 windows->command.data=0;
2302 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2304 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2305 text_event.xexpose.width=(int) font_info->max_bounds.width;
2306 text_event.xexpose.height=font_info->max_bounds.ascent+
2307 font_info->max_bounds.descent;
2308 p=annotate_info->text;
2312 Display text cursor.
2315 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2317 Wait for next event.
2319 XScreenEvent(display,windows,&event,exception);
2320 if (event.xany.window == windows->command.id)
2323 Select a command from the Command widget.
2325 (void) XSetBackground(display,annotate_context,
2326 windows->pixel_info->background_color.pixel);
2327 (void) XSetForeground(display,annotate_context,
2328 windows->pixel_info->foreground_color.pixel);
2329 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2330 (void) XSetBackground(display,annotate_context,
2331 windows->pixel_info->pen_colors[box_id].pixel);
2332 (void) XSetForeground(display,annotate_context,
2333 windows->pixel_info->pen_colors[pen_id].pixel);
2336 switch (TextCommands[id])
2338 case TextHelpCommand:
2340 XTextViewWidget(display,resource_info,windows,MagickFalse,
2341 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2342 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2345 case TextApplyCommand:
2348 Finished annotating.
2350 annotate_info->width=(unsigned int) XTextWidth(font_info,
2351 annotate_info->text,(int) strlen(annotate_info->text));
2352 XRefreshWindow(display,&windows->image,&text_event);
2364 text_event.xexpose.x=x;
2365 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2366 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2367 (unsigned int) text_event.xexpose.width,(unsigned int)
2368 text_event.xexpose.height,MagickFalse);
2369 XRefreshWindow(display,&windows->image,&text_event);
2374 if (event.xbutton.window != windows->image.id)
2376 if (event.xbutton.button == Button2)
2379 Request primary selection.
2381 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2382 windows->image.id,CurrentTime);
2389 if (event.xexpose.count == 0)
2395 Refresh Image window.
2397 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2398 text_info=annotate_info;
2399 while (text_info != (XAnnotateInfo *) NULL)
2401 if (annotate_info->stencil == ForegroundStencil)
2402 (void) XDrawString(display,windows->image.id,annotate_context,
2403 text_info->x,text_info->y,text_info->text,
2404 (int) strlen(text_info->text));
2406 (void) XDrawImageString(display,windows->image.id,
2407 annotate_context,text_info->x,text_info->y,text_info->text,
2408 (int) strlen(text_info->text));
2409 text_info=text_info->previous;
2411 (void) XDrawString(display,windows->image.id,annotate_context,
2421 if (event.xkey.window != windows->image.id)
2424 Respond to a user key press.
2426 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2427 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2428 *(command+length)='\0';
2429 if (((event.xkey.state & ControlMask) != 0) ||
2430 ((event.xkey.state & Mod1Mask) != 0))
2431 state|=ModifierState;
2432 if ((state & ModifierState) != 0)
2433 switch ((int) key_symbol)
2438 key_symbol=DeleteCommand;
2444 switch ((int) key_symbol)
2449 Erase one character.
2451 if (p == annotate_info->text)
2453 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2458 Go to end of the previous line of text.
2460 annotate_info=annotate_info->previous;
2461 p=annotate_info->text;
2462 x=annotate_info->x+annotate_info->width;
2464 if (annotate_info->width != 0)
2465 p+=strlen(annotate_info->text);
2470 x-=XTextWidth(font_info,p,1);
2471 text_event.xexpose.x=x;
2472 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2473 XRefreshWindow(display,&windows->image,&text_event);
2476 case XK_bracketleft:
2478 key_symbol=XK_Escape;
2484 Erase the entire line of text.
2486 while (p != annotate_info->text)
2489 x-=XTextWidth(font_info,p,1);
2490 text_event.xexpose.x=x;
2491 XRefreshWindow(display,&windows->image,&text_event);
2499 Finished annotating.
2501 annotate_info->width=(unsigned int) XTextWidth(font_info,
2502 annotate_info->text,(int) strlen(annotate_info->text));
2503 XRefreshWindow(display,&windows->image,&text_event);
2510 Draw a single character on the Image window.
2512 if ((state & ModifierState) != 0)
2514 if (*command == '\0')
2517 if (annotate_info->stencil == ForegroundStencil)
2518 (void) XDrawString(display,windows->image.id,annotate_context,
2521 (void) XDrawImageString(display,windows->image.id,
2522 annotate_context,x,y,p,1);
2523 x+=XTextWidth(font_info,p,1);
2525 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2532 Advance to the next line of text.
2535 annotate_info->width=(unsigned int) XTextWidth(font_info,
2536 annotate_info->text,(int) strlen(annotate_info->text));
2537 if (annotate_info->next != (XAnnotateInfo *) NULL)
2540 Line of text already exists.
2542 annotate_info=annotate_info->next;
2545 p=annotate_info->text;
2548 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2549 sizeof(*annotate_info->next));
2550 if (annotate_info->next == (XAnnotateInfo *) NULL)
2551 return(MagickFalse);
2552 *annotate_info->next=(*annotate_info);
2553 annotate_info->next->previous=annotate_info;
2554 annotate_info=annotate_info->next;
2555 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2556 windows->image.width/MagickMax((ssize_t)
2557 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2558 if (annotate_info->text == (char *) NULL)
2559 return(MagickFalse);
2560 annotate_info->y+=annotate_info->height;
2561 if (annotate_info->y > (int) windows->image.height)
2562 annotate_info->y=(int) annotate_info->height;
2563 annotate_info->next=(XAnnotateInfo *) NULL;
2566 p=annotate_info->text;
2575 Respond to a user key release.
2577 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2578 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2579 state&=(~ModifierState);
2582 case SelectionNotify:
2598 Obtain response from primary selection.
2600 if (event.xselection.property == (Atom) None)
2602 status=XGetWindowProperty(display,event.xselection.requestor,
2603 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2604 &type,&format,&length,&after,&data);
2605 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2609 Annotate Image window with primary selection.
2611 for (i=0; i < (ssize_t) length; i++)
2613 if ((char) data[i] != '\n')
2616 Draw a single character on the Image window.
2619 (void) XDrawString(display,windows->image.id,annotate_context,
2621 x+=XTextWidth(font_info,p,1);
2623 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2627 Advance to the next line of text.
2630 annotate_info->width=(unsigned int) XTextWidth(font_info,
2631 annotate_info->text,(int) strlen(annotate_info->text));
2632 if (annotate_info->next != (XAnnotateInfo *) NULL)
2635 Line of text already exists.
2637 annotate_info=annotate_info->next;
2640 p=annotate_info->text;
2643 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2644 sizeof(*annotate_info->next));
2645 if (annotate_info->next == (XAnnotateInfo *) NULL)
2646 return(MagickFalse);
2647 *annotate_info->next=(*annotate_info);
2648 annotate_info->next->previous=annotate_info;
2649 annotate_info=annotate_info->next;
2650 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2651 windows->image.width/MagickMax((ssize_t)
2652 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2653 if (annotate_info->text == (char *) NULL)
2654 return(MagickFalse);
2655 annotate_info->y+=annotate_info->height;
2656 if (annotate_info->y > (int) windows->image.height)
2657 annotate_info->y=(int) annotate_info->height;
2658 annotate_info->next=(XAnnotateInfo *) NULL;
2661 p=annotate_info->text;
2663 (void) XFree((void *) data);
2669 } while ((state & ExitState) == 0);
2670 (void) XFreeCursor(display,cursor);
2672 Annotation is relative to image configuration.
2674 width=(unsigned int) image->columns;
2675 height=(unsigned int) image->rows;
2678 if (windows->image.crop_geometry != (char *) NULL)
2679 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2681 Initialize annotated image.
2683 XSetCursorState(display,windows,MagickTrue);
2684 XCheckRefreshWindows(display,windows);
2685 while (annotate_info != (XAnnotateInfo *) NULL)
2687 if (annotate_info->width == 0)
2690 No text on this line-- go to the next line of text.
2692 previous_info=annotate_info->previous;
2693 annotate_info->text=(char *)
2694 RelinquishMagickMemory(annotate_info->text);
2695 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2696 annotate_info=previous_info;
2700 Determine pixel index for box and pen color.
2702 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2703 if (windows->pixel_info->colors != 0)
2704 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2705 if (windows->pixel_info->pixels[i] ==
2706 windows->pixel_info->pen_colors[box_id].pixel)
2708 windows->pixel_info->box_index=(unsigned short) i;
2711 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2712 if (windows->pixel_info->colors != 0)
2713 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2714 if (windows->pixel_info->pixels[i] ==
2715 windows->pixel_info->pen_colors[pen_id].pixel)
2717 windows->pixel_info->pen_index=(unsigned short) i;
2721 Define the annotate geometry string.
2723 annotate_info->x=(int)
2724 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2725 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2726 windows->image.y)/windows->image.ximage->height;
2727 (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent,
2728 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2729 height*annotate_info->height/windows->image.ximage->height,
2730 annotate_info->x+x,annotate_info->y+y);
2732 Annotate image with text.
2734 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image,
2737 return(MagickFalse);
2741 previous_info=annotate_info->previous;
2742 annotate_info->text=DestroyString(annotate_info->text);
2743 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2744 annotate_info=previous_info;
2746 (void) XSetForeground(display,annotate_context,
2747 windows->pixel_info->foreground_color.pixel);
2748 (void) XSetBackground(display,annotate_context,
2749 windows->pixel_info->background_color.pixel);
2750 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2751 XSetCursorState(display,windows,MagickFalse);
2752 (void) XFreeFont(display,font_info);
2754 Update image configuration.
2756 XConfigureImageColormap(display,resource_info,windows,image,exception);
2757 (void) XConfigureImage(display,resource_info,windows,image,exception);
2762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2766 + X B a c k g r o u n d I m a g e %
2770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2772 % XBackgroundImage() displays the image in the background of a window.
2774 % The format of the XBackgroundImage method is:
2776 % MagickBooleanType XBackgroundImage(Display *display,
2777 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2778 % ExceptionInfo *exception)
2780 % A description of each parameter follows:
2782 % o display: Specifies a connection to an X server; returned from
2785 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2787 % o windows: Specifies a pointer to a XWindows structure.
2789 % o image: the image.
2791 % o exception: return any errors or warnings in this structure.
2794 static MagickBooleanType XBackgroundImage(Display *display,
2795 XResourceInfo *resource_info,XWindows *windows,Image **image,
2796 ExceptionInfo *exception)
2798 #define BackgroundImageTag "Background/Image"
2804 window_id[MaxTextExtent] = "root";
2807 background_resources;
2810 Put image in background.
2812 status=XDialogWidget(display,windows,"Background",
2813 "Enter window id (id 0x00 selects window with pointer):",window_id);
2814 if (*window_id == '\0')
2815 return(MagickFalse);
2816 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2818 XInfoWidget(display,windows,BackgroundImageTag);
2819 XSetCursorState(display,windows,MagickTrue);
2820 XCheckRefreshWindows(display,windows);
2821 background_resources=(*resource_info);
2822 background_resources.window_id=window_id;
2823 background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse;
2824 status=XDisplayBackgroundImage(display,&background_resources,*image,
2826 if (status != MagickFalse)
2827 XClientMessage(display,windows->image.id,windows->im_protocols,
2828 windows->im_retain_colors,CurrentTime);
2829 XSetCursorState(display,windows,MagickFalse);
2830 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2840 + X C h o p I m a g e %
2844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2846 % XChopImage() chops the X image.
2848 % The format of the XChopImage method is:
2850 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2851 % XWindows *windows,Image **image,ExceptionInfo *exception)
2853 % A description of each parameter follows:
2855 % o display: Specifies a connection to an X server; returned from
2858 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2860 % o windows: Specifies a pointer to a XWindows structure.
2862 % o image: the image.
2864 % o exception: return any errors or warnings in this structure.
2867 static MagickBooleanType XChopImage(Display *display,
2868 XResourceInfo *resource_info,XWindows *windows,Image **image,
2869 ExceptionInfo *exception)
2881 direction = HorizontalChopCommand;
2883 static const ModeType
2886 ChopDirectionCommand,
2890 DirectionCommands[] =
2892 HorizontalChopCommand,
2897 text[MaxTextExtent];
2930 (void) CloneString(&windows->command.name,"Chop");
2931 windows->command.data=1;
2932 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2933 (void) XMapRaised(display,windows->command.id);
2934 XClientMessage(display,windows->image.id,windows->im_protocols,
2935 windows->im_update_widget,CurrentTime);
2937 Track pointer until button 1 is pressed.
2939 XQueryPosition(display,windows->image.id,&x,&y);
2940 (void) XSelectInput(display,windows->image.id,
2941 windows->image.attributes.event_mask | PointerMotionMask);
2945 if (windows->info.mapped != MagickFalse)
2948 Display pointer position.
2950 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
2951 x+windows->image.x,y+windows->image.y);
2952 XInfoWidget(display,windows,text);
2955 Wait for next event.
2957 XScreenEvent(display,windows,&event,exception);
2958 if (event.xany.window == windows->command.id)
2961 Select a command from the Command widget.
2963 id=XCommandWidget(display,windows,ChopMenu,&event);
2966 switch (ChopCommands[id])
2968 case ChopDirectionCommand:
2971 command[MaxTextExtent];
2982 Select a command from the pop-up menu.
2984 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2986 direction=DirectionCommands[id];
2989 case ChopHelpCommand:
2991 XTextViewWidget(display,resource_info,windows,MagickFalse,
2992 "Help Viewer - Image Chop",ImageChopHelp);
2995 case ChopDismissCommand:
3013 if (event.xbutton.button != Button1)
3015 if (event.xbutton.window != windows->image.id)
3018 User has committed to start point of chopping line.
3020 segment_info.x1=(short int) event.xbutton.x;
3021 segment_info.x2=(short int) event.xbutton.x;
3022 segment_info.y1=(short int) event.xbutton.y;
3023 segment_info.y2=(short int) event.xbutton.y;
3034 command[MaxTextExtent];
3039 if (event.xkey.window != windows->image.id)
3042 Respond to a user key press.
3044 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3045 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3046 switch ((int) key_symbol)
3061 (void) XSetFunction(display,windows->image.highlight_context,
3063 XTextViewWidget(display,resource_info,windows,MagickFalse,
3064 "Help Viewer - Image Chop",ImageChopHelp);
3065 (void) XSetFunction(display,windows->image.highlight_context,
3071 (void) XBell(display,0);
3080 Map and unmap Info widget as text cursor crosses its boundaries.
3084 if (windows->info.mapped != MagickFalse)
3086 if ((x < (int) (windows->info.x+windows->info.width)) &&
3087 (y < (int) (windows->info.y+windows->info.height)))
3088 (void) XWithdrawWindow(display,windows->info.id,
3089 windows->info.screen);
3092 if ((x > (int) (windows->info.x+windows->info.width)) ||
3093 (y > (int) (windows->info.y+windows->info.height)))
3094 (void) XMapWindow(display,windows->info.id);
3097 } while ((state & ExitState) == 0);
3098 (void) XSelectInput(display,windows->image.id,
3099 windows->image.attributes.event_mask);
3100 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3101 if ((state & EscapeState) != 0)
3104 Draw line as pointer moves until the mouse button is released.
3111 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3118 Display info and draw chopping line.
3120 if (windows->info.mapped == MagickFalse)
3121 (void) XMapWindow(display,windows->info.id);
3122 (void) FormatLocaleString(text,MaxTextExtent,
3123 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3124 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3125 XInfoWidget(display,windows,text);
3126 XHighlightLine(display,windows->image.id,
3127 windows->image.highlight_context,&segment_info);
3130 if (windows->info.mapped != MagickFalse)
3131 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3133 Wait for next event.
3135 XScreenEvent(display,windows,&event,exception);
3137 XHighlightLine(display,windows->image.id,
3138 windows->image.highlight_context,&segment_info);
3143 segment_info.x2=(short int) event.xmotion.x;
3144 segment_info.y2=(short int) event.xmotion.y;
3150 User has committed to chopping line.
3152 segment_info.x2=(short int) event.xbutton.x;
3153 segment_info.y2=(short int) event.xbutton.y;
3161 segment_info.x2=(short int) event.xmotion.x;
3162 segment_info.y2=(short int) event.xmotion.y;
3168 Check boundary conditions.
3170 if (segment_info.x2 < 0)
3173 if (segment_info.x2 > windows->image.ximage->width)
3174 segment_info.x2=windows->image.ximage->width;
3175 if (segment_info.y2 < 0)
3178 if (segment_info.y2 > windows->image.ximage->height)
3179 segment_info.y2=windows->image.ximage->height;
3180 distance=(unsigned int)
3181 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3182 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3184 Compute chopping geometry.
3186 if (direction == HorizontalChopCommand)
3188 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3189 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3192 if (segment_info.x1 > (int) segment_info.x2)
3194 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3195 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3201 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3203 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3204 if (segment_info.y1 > segment_info.y2)
3206 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3207 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3210 } while ((state & ExitState) == 0);
3211 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3212 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3216 Image chopping is relative to image configuration.
3218 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3220 XSetCursorState(display,windows,MagickTrue);
3221 XCheckRefreshWindows(display,windows);
3222 windows->image.window_changes.width=windows->image.ximage->width-
3223 (unsigned int) chop_info.width;
3224 windows->image.window_changes.height=windows->image.ximage->height-
3225 (unsigned int) chop_info.height;
3226 width=(unsigned int) (*image)->columns;
3227 height=(unsigned int) (*image)->rows;
3230 if (windows->image.crop_geometry != (char *) NULL)
3231 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3232 scale_factor=(MagickRealType) width/windows->image.ximage->width;
3234 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3235 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3236 scale_factor=(MagickRealType) height/windows->image.ximage->height;
3238 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3239 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3243 chop_image=ChopImage(*image,&chop_info,exception);
3244 XSetCursorState(display,windows,MagickFalse);
3245 if (chop_image == (Image *) NULL)
3246 return(MagickFalse);
3247 *image=DestroyImage(*image);
3250 Update image configuration.
3252 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3253 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3262 + X C o l o r E d i t I m a g e %
3266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3268 % XColorEditImage() allows the user to interactively change the color of one
3269 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3271 % The format of the XColorEditImage method is:
3273 % MagickBooleanType XColorEditImage(Display *display,
3274 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3275 % ExceptionInfo *exception)
3277 % A description of each parameter follows:
3279 % o display: Specifies a connection to an X server; returned from
3282 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3284 % o windows: Specifies a pointer to a XWindows structure.
3286 % o image: the image; returned from ReadImage.
3288 % o exception: return any errors or warnings in this structure.
3291 static MagickBooleanType XColorEditImage(Display *display,
3292 XResourceInfo *resource_info,XWindows *windows,Image **image,
3293 ExceptionInfo *exception)
3308 static const ModeType
3309 ColorEditCommands[] =
3311 ColorEditMethodCommand,
3312 ColorEditColorCommand,
3313 ColorEditBorderCommand,
3314 ColorEditFuzzCommand,
3315 ColorEditUndoCommand,
3316 ColorEditHelpCommand,
3317 ColorEditDismissCommand
3321 method = PointMethod;
3327 border_color = { 0, 0, 0, 0, 0, 0 };
3330 command[MaxTextExtent],
3331 text[MaxTextExtent];
3366 (void) CloneString(&windows->command.name,"Color Edit");
3367 windows->command.data=4;
3368 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3369 (void) XMapRaised(display,windows->command.id);
3370 XClientMessage(display,windows->image.id,windows->im_protocols,
3371 windows->im_update_widget,CurrentTime);
3375 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3376 resource_info->background_color,resource_info->foreground_color);
3377 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3379 Track pointer until button 1 is pressed.
3381 XQueryPosition(display,windows->image.id,&x,&y);
3382 (void) XSelectInput(display,windows->image.id,
3383 windows->image.attributes.event_mask | PointerMotionMask);
3387 if (windows->info.mapped != MagickFalse)
3390 Display pointer position.
3392 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
3393 x+windows->image.x,y+windows->image.y);
3394 XInfoWidget(display,windows,text);
3397 Wait for next event.
3399 XScreenEvent(display,windows,&event,exception);
3400 if (event.xany.window == windows->command.id)
3403 Select a command from the Command widget.
3405 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3408 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3411 switch (ColorEditCommands[id])
3413 case ColorEditMethodCommand:
3419 Select a method from the pop-up menu.
3421 methods=(char **) GetCommandOptions(MagickMethodOptions);
3422 if (methods == (char **) NULL)
3424 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3425 (const char **) methods,command);
3427 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3428 MagickFalse,methods[entry]);
3429 methods=DestroyStringList(methods);
3432 case ColorEditColorCommand:
3435 *ColorMenu[MaxNumberPens];
3441 Initialize menu selections.
3443 for (i=0; i < (int) (MaxNumberPens-2); i++)
3444 ColorMenu[i]=resource_info->pen_colors[i];
3445 ColorMenu[MaxNumberPens-2]="Browser...";
3446 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3448 Select a pen color from the pop-up menu.
3450 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3451 (const char **) ColorMenu,command);
3454 if (pen_number == (MaxNumberPens-2))
3457 color_name[MaxTextExtent] = "gray";
3460 Select a pen color from a dialog.
3462 resource_info->pen_colors[pen_number]=color_name;
3463 XColorBrowserWidget(display,windows,"Select",color_name);
3464 if (*color_name == '\0')
3470 (void) XParseColor(display,windows->map_info->colormap,
3471 resource_info->pen_colors[pen_number],&color);
3472 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3473 (unsigned int) MaxColors,&color);
3474 windows->pixel_info->pen_colors[pen_number]=color;
3475 pen_id=(unsigned int) pen_number;
3478 case ColorEditBorderCommand:
3481 *ColorMenu[MaxNumberPens];
3487 Initialize menu selections.
3489 for (i=0; i < (int) (MaxNumberPens-2); i++)
3490 ColorMenu[i]=resource_info->pen_colors[i];
3491 ColorMenu[MaxNumberPens-2]="Browser...";
3492 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3494 Select a pen color from the pop-up menu.
3496 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3497 (const char **) ColorMenu,command);
3500 if (pen_number == (MaxNumberPens-2))
3503 color_name[MaxTextExtent] = "gray";
3506 Select a pen color from a dialog.
3508 resource_info->pen_colors[pen_number]=color_name;
3509 XColorBrowserWidget(display,windows,"Select",color_name);
3510 if (*color_name == '\0')
3516 (void) XParseColor(display,windows->map_info->colormap,
3517 resource_info->pen_colors[pen_number],&border_color);
3520 case ColorEditFuzzCommand:
3523 fuzz[MaxTextExtent];
3538 Select a command from the pop-up menu.
3540 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3546 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],(double)
3550 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3551 (void) XDialogWidget(display,windows,"Ok",
3552 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3555 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3556 (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0);
3559 case ColorEditUndoCommand:
3561 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3565 case ColorEditHelpCommand:
3568 XTextViewWidget(display,resource_info,windows,MagickFalse,
3569 "Help Viewer - Image Annotation",ImageColorEditHelp);
3572 case ColorEditDismissCommand:
3582 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3589 if (event.xbutton.button != Button1)
3591 if ((event.xbutton.window != windows->image.id) &&
3592 (event.xbutton.window != windows->magnify.id))
3599 (void) XMagickCommand(display,resource_info,windows,
3600 SaveToUndoBufferCommand,image,exception);
3601 state|=UpdateConfigurationState;
3606 if (event.xbutton.button != Button1)
3608 if ((event.xbutton.window != windows->image.id) &&
3609 (event.xbutton.window != windows->magnify.id))
3612 Update colormap information.
3616 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3617 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3618 XInfoWidget(display,windows,text);
3619 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3620 state&=(~UpdateConfigurationState);
3630 if (event.xkey.window == windows->magnify.id)
3635 window=windows->magnify.id;
3636 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3638 if (event.xkey.window != windows->image.id)
3641 Respond to a user key press.
3643 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3644 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3645 switch ((int) key_symbol)
3659 XTextViewWidget(display,resource_info,windows,MagickFalse,
3660 "Help Viewer - Image Annotation",ImageColorEditHelp);
3665 (void) XBell(display,0);
3674 Map and unmap Info widget as cursor crosses its boundaries.
3678 if (windows->info.mapped != MagickFalse)
3680 if ((x < (int) (windows->info.x+windows->info.width)) &&
3681 (y < (int) (windows->info.y+windows->info.height)))
3682 (void) XWithdrawWindow(display,windows->info.id,
3683 windows->info.screen);
3686 if ((x > (int) (windows->info.x+windows->info.width)) ||
3687 (y > (int) (windows->info.y+windows->info.height)))
3688 (void) XMapWindow(display,windows->info.id);
3694 if (event.xany.window == windows->magnify.id)
3696 x=windows->magnify.x-windows->image.x;
3697 y=windows->magnify.y-windows->image.y;
3701 if ((state & UpdateConfigurationState) != 0)
3711 Pixel edit is relative to image configuration.
3713 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3715 color=windows->pixel_info->pen_colors[pen_id];
3716 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3717 width=(unsigned int) (*image)->columns;
3718 height=(unsigned int) (*image)->rows;
3721 if (windows->image.crop_geometry != (char *) NULL)
3722 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3725 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3727 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3728 if ((x_offset < 0) || (y_offset < 0))
3730 if ((x_offset >= (int) (*image)->columns) ||
3731 (y_offset >= (int) (*image)->rows))
3733 image_view=AcquireCacheView(*image);
3740 Update color information using point algorithm.
3742 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3743 return(MagickFalse);
3744 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3745 (ssize_t) y_offset,1,1,exception);
3746 if (q == (Quantum *) NULL)
3748 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3749 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3750 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3751 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3761 virtual_pixel[CompositePixelChannel];
3764 Update color information using replace algorithm.
3766 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
3767 (ssize_t) y_offset,virtual_pixel,exception);
3768 target.red=virtual_pixel[RedPixelChannel];
3769 target.green=virtual_pixel[GreenPixelChannel];
3770 target.blue=virtual_pixel[BluePixelChannel];
3771 target.alpha=virtual_pixel[AlphaPixelChannel];
3772 if ((*image)->storage_class == DirectClass)
3774 for (y=0; y < (int) (*image)->rows; y++)
3776 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3777 (*image)->columns,1,exception);
3778 if (q == (Quantum *) NULL)
3780 for (x=0; x < (int) (*image)->columns; x++)
3782 GetPixelInfoPixel(*image,q,&pixel);
3783 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3785 SetPixelRed(*image,ScaleShortToQuantum(
3787 SetPixelGreen(*image,ScaleShortToQuantum(
3789 SetPixelBlue(*image,ScaleShortToQuantum(
3792 q+=GetPixelChannels(*image);
3794 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3800 for (i=0; i < (ssize_t) (*image)->colors; i++)
3801 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3803 (*image)->colormap[i].red=ScaleShortToQuantum(
3805 (*image)->colormap[i].green=ScaleShortToQuantum(
3807 (*image)->colormap[i].blue=ScaleShortToQuantum(
3810 (void) SyncImage(*image,exception);
3814 case FloodfillMethod:
3815 case FillToBorderMethod:
3824 Update color information using floodfill algorithm.
3826 (void) GetOneVirtualMagickPixel(*image,
3827 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3828 y_offset,&target,exception);
3829 if (method == FillToBorderMethod)
3831 target.red=(MagickRealType)
3832 ScaleShortToQuantum(border_color.red);
3833 target.green=(MagickRealType)
3834 ScaleShortToQuantum(border_color.green);
3835 target.blue=(MagickRealType)
3836 ScaleShortToQuantum(border_color.blue);
3838 draw_info=CloneDrawInfo(resource_info->image_info,
3840 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3841 AllCompliance,&draw_info->fill,exception);
3842 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
3843 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
3844 MagickFalse : MagickTrue,exception);
3845 draw_info=DestroyDrawInfo(draw_info);
3851 Update color information using reset algorithm.
3853 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3854 return(MagickFalse);
3855 for (y=0; y < (int) (*image)->rows; y++)
3857 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3858 (*image)->columns,1,exception);
3859 if (q == (Quantum *) NULL)
3861 for (x=0; x < (int) (*image)->columns; x++)
3863 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3864 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3865 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3866 q+=GetPixelChannels(*image);
3868 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3874 image_view=DestroyCacheView(image_view);
3875 state&=(~UpdateConfigurationState);
3877 } while ((state & ExitState) == 0);
3878 (void) XSelectInput(display,windows->image.id,
3879 windows->image.attributes.event_mask);
3880 XSetCursorState(display,windows,MagickFalse);
3881 (void) XFreeCursor(display,cursor);
3886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3890 + X C o m p o s i t e I m a g e %
3894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3896 % XCompositeImage() requests an image name from the user, reads the image and
3897 % composites it with the X window image at a location the user chooses with
3900 % The format of the XCompositeImage method is:
3902 % MagickBooleanType XCompositeImage(Display *display,
3903 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3904 % ExceptionInfo *exception)
3906 % A description of each parameter follows:
3908 % o display: Specifies a connection to an X server; returned from
3911 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3913 % o windows: Specifies a pointer to a XWindows structure.
3915 % o image: the image; returned from ReadImage.
3917 % o exception: return any errors or warnings in this structure.
3920 static MagickBooleanType XCompositeImage(Display *display,
3921 XResourceInfo *resource_info,XWindows *windows,Image *image,
3922 ExceptionInfo *exception)
3925 displacement_geometry[MaxTextExtent] = "30x30",
3926 filename[MaxTextExtent] = "\0";
3939 static CompositeOperator
3940 compose = CopyCompositeOp;
3942 static const ModeType
3943 CompositeCommands[] =
3945 CompositeOperatorsCommand,
3946 CompositeDissolveCommand,
3947 CompositeDisplaceCommand,
3948 CompositeHelpCommand,
3949 CompositeDismissCommand
3953 text[MaxTextExtent];
3986 Request image file name from user.
3988 XFileBrowserWidget(display,windows,"Composite",filename);
3989 if (*filename == '\0')
3994 XSetCursorState(display,windows,MagickTrue);
3995 XCheckRefreshWindows(display,windows);
3996 (void) CopyMagickString(resource_info->image_info->filename,filename,
3998 composite_image=ReadImage(resource_info->image_info,exception);
3999 CatchException(exception);
4000 XSetCursorState(display,windows,MagickFalse);
4001 if (composite_image == (Image *) NULL)
4002 return(MagickFalse);
4006 (void) CloneString(&windows->command.name,"Composite");
4007 windows->command.data=1;
4008 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
4009 (void) XMapRaised(display,windows->command.id);
4010 XClientMessage(display,windows->image.id,windows->im_protocols,
4011 windows->im_update_widget,CurrentTime);
4013 Track pointer until button 1 is pressed.
4015 XQueryPosition(display,windows->image.id,&x,&y);
4016 (void) XSelectInput(display,windows->image.id,
4017 windows->image.attributes.event_mask | PointerMotionMask);
4018 composite_info.x=(ssize_t) windows->image.x+x;
4019 composite_info.y=(ssize_t) windows->image.y+y;
4020 composite_info.width=0;
4021 composite_info.height=0;
4022 cursor=XCreateFontCursor(display,XC_ul_angle);
4023 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4028 if (windows->info.mapped != MagickFalse)
4031 Display pointer position.
4033 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4034 (long) composite_info.x,(long) composite_info.y);
4035 XInfoWidget(display,windows,text);
4037 highlight_info=composite_info;
4038 highlight_info.x=composite_info.x-windows->image.x;
4039 highlight_info.y=composite_info.y-windows->image.y;
4040 XHighlightRectangle(display,windows->image.id,
4041 windows->image.highlight_context,&highlight_info);
4043 Wait for next event.
4045 XScreenEvent(display,windows,&event,exception);
4046 XHighlightRectangle(display,windows->image.id,
4047 windows->image.highlight_context,&highlight_info);
4048 if (event.xany.window == windows->command.id)
4051 Select a command from the Command widget.
4053 id=XCommandWidget(display,windows,CompositeMenu,&event);
4056 switch (CompositeCommands[id])
4058 case CompositeOperatorsCommand:
4061 command[MaxTextExtent],
4065 Select a command from the pop-up menu.
4067 operators=GetCommandOptions(MagickComposeOptions);
4068 if (operators == (char **) NULL)
4070 entry=XMenuWidget(display,windows,CompositeMenu[id],
4071 (const char **) operators,command);
4073 compose=(CompositeOperator) ParseCommandOption(
4074 MagickComposeOptions,MagickFalse,operators[entry]);
4075 operators=DestroyStringList(operators);
4078 case CompositeDissolveCommand:
4081 factor[MaxTextExtent] = "20.0";
4084 Dissolve the two images a given percent.
4086 (void) XSetFunction(display,windows->image.highlight_context,
4088 (void) XDialogWidget(display,windows,"Dissolve",
4089 "Enter the blend factor (0.0 - 99.9%):",factor);
4090 (void) XSetFunction(display,windows->image.highlight_context,
4092 if (*factor == '\0')
4094 blend=InterpretLocaleValue(factor,(char **) NULL);
4095 compose=DissolveCompositeOp;
4098 case CompositeDisplaceCommand:
4101 Get horizontal and vertical scale displacement geometry.
4103 (void) XSetFunction(display,windows->image.highlight_context,
4105 (void) XDialogWidget(display,windows,"Displace",
4106 "Enter the horizontal and vertical scale:",displacement_geometry);
4107 (void) XSetFunction(display,windows->image.highlight_context,
4109 if (*displacement_geometry == '\0')
4111 compose=DisplaceCompositeOp;
4114 case CompositeHelpCommand:
4116 (void) XSetFunction(display,windows->image.highlight_context,
4118 XTextViewWidget(display,resource_info,windows,MagickFalse,
4119 "Help Viewer - Image Composite",ImageCompositeHelp);
4120 (void) XSetFunction(display,windows->image.highlight_context,
4124 case CompositeDismissCommand:
4142 if (image->debug != MagickFalse)
4143 (void) LogMagickEvent(X11Event,GetMagickModule(),
4144 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4145 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4146 if (event.xbutton.button != Button1)
4148 if (event.xbutton.window != windows->image.id)
4153 composite_info.width=composite_image->columns;
4154 composite_info.height=composite_image->rows;
4155 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4156 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4157 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4162 if (image->debug != MagickFalse)
4163 (void) LogMagickEvent(X11Event,GetMagickModule(),
4164 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4165 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4166 if (event.xbutton.button != Button1)
4168 if (event.xbutton.window != windows->image.id)
4170 if ((composite_info.width != 0) && (composite_info.height != 0))
4173 User has selected the location of the composite image.
4175 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4176 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4186 command[MaxTextExtent];
4194 if (event.xkey.window != windows->image.id)
4197 Respond to a user key press.
4199 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4200 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4201 *(command+length)='\0';
4202 if (image->debug != MagickFalse)
4203 (void) LogMagickEvent(X11Event,GetMagickModule(),
4204 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4205 switch ((int) key_symbol)
4213 composite_image=DestroyImage(composite_image);
4221 (void) XSetFunction(display,windows->image.highlight_context,
4223 XTextViewWidget(display,resource_info,windows,MagickFalse,
4224 "Help Viewer - Image Composite",ImageCompositeHelp);
4225 (void) XSetFunction(display,windows->image.highlight_context,
4231 (void) XBell(display,0);
4240 Map and unmap Info widget as text cursor crosses its boundaries.
4244 if (windows->info.mapped != MagickFalse)
4246 if ((x < (int) (windows->info.x+windows->info.width)) &&
4247 (y < (int) (windows->info.y+windows->info.height)))
4248 (void) XWithdrawWindow(display,windows->info.id,
4249 windows->info.screen);
4252 if ((x > (int) (windows->info.x+windows->info.width)) ||
4253 (y > (int) (windows->info.y+windows->info.height)))
4254 (void) XMapWindow(display,windows->info.id);
4255 composite_info.x=(ssize_t) windows->image.x+x;
4256 composite_info.y=(ssize_t) windows->image.y+y;
4261 if (image->debug != MagickFalse)
4262 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4267 } while ((state & ExitState) == 0);
4268 (void) XSelectInput(display,windows->image.id,
4269 windows->image.attributes.event_mask);
4270 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4271 XSetCursorState(display,windows,MagickFalse);
4272 (void) XFreeCursor(display,cursor);
4273 if ((state & EscapeState) != 0)
4276 Image compositing is relative to image configuration.
4278 XSetCursorState(display,windows,MagickTrue);
4279 XCheckRefreshWindows(display,windows);
4280 width=(unsigned int) image->columns;
4281 height=(unsigned int) image->rows;
4284 if (windows->image.crop_geometry != (char *) NULL)
4285 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4286 scale_factor=(MagickRealType) width/windows->image.ximage->width;
4287 composite_info.x+=x;
4288 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4289 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4290 scale_factor=(MagickRealType) height/windows->image.ximage->height;
4291 composite_info.y+=y;
4292 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4293 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4294 if ((composite_info.width != composite_image->columns) ||
4295 (composite_info.height != composite_image->rows))
4301 Scale composite image.
4303 resize_image=ResizeImage(composite_image,composite_info.width,
4304 composite_info.height,composite_image->filter,composite_image->blur,
4306 composite_image=DestroyImage(composite_image);
4307 if (resize_image == (Image *) NULL)
4309 XSetCursorState(display,windows,MagickFalse);
4310 return(MagickFalse);
4312 composite_image=resize_image;
4314 if (compose == DisplaceCompositeOp)
4315 (void) SetImageArtifact(composite_image,"compose:args",
4316 displacement_geometry);
4335 Create mattes for blending.
4337 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4338 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
4339 ((ssize_t) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
4340 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4341 return(MagickFalse);
4342 image->matte=MagickTrue;
4343 image_view=AcquireCacheView(image);
4344 for (y=0; y < (int) image->rows; y++)
4346 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4348 if (q == (Quantum *) NULL)
4350 for (x=0; x < (int) image->columns; x++)
4352 SetPixelAlpha(image,opacity,q);
4353 q+=GetPixelChannels(image);
4355 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4358 image_view=DestroyCacheView(image_view);
4361 Composite image with X Image window.
4363 (void) CompositeImage(image,compose,composite_image,composite_info.x,
4364 composite_info.y,exception);
4365 composite_image=DestroyImage(composite_image);
4366 XSetCursorState(display,windows,MagickFalse);
4368 Update image configuration.
4370 XConfigureImageColormap(display,resource_info,windows,image,exception);
4371 (void) XConfigureImage(display,resource_info,windows,image,exception);
4376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4380 + X C o n f i g u r e I m a g e %
4384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4386 % XConfigureImage() creates a new X image. It also notifies the window
4387 % manager of the new image size and configures the transient widows.
4389 % The format of the XConfigureImage method is:
4391 % MagickBooleanType XConfigureImage(Display *display,
4392 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4393 % ExceptionInfo *exception)
4395 % A description of each parameter follows:
4397 % o display: Specifies a connection to an X server; returned from
4400 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4402 % o windows: Specifies a pointer to a XWindows structure.
4404 % o image: the image.
4406 % o exception: return any errors or warnings in this structure.
4408 % o exception: return any errors or warnings in this structure.
4411 static MagickBooleanType XConfigureImage(Display *display,
4412 XResourceInfo *resource_info,XWindows *windows,Image *image,
4413 ExceptionInfo *exception)
4416 geometry[MaxTextExtent];
4437 Dismiss if window dimensions are zero.
4439 width=(unsigned int) windows->image.window_changes.width;
4440 height=(unsigned int) windows->image.window_changes.height;
4441 if (image->debug != MagickFalse)
4442 (void) LogMagickEvent(X11Event,GetMagickModule(),
4443 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4444 windows->image.ximage->height,(double) width,(double) height);
4445 if ((width*height) == 0)
4450 Resize image to fit Image window dimensions.
4452 XSetCursorState(display,windows,MagickTrue);
4453 (void) XFlush(display);
4454 if (((int) width != windows->image.ximage->width) ||
4455 ((int) height != windows->image.ximage->height))
4456 image->taint=MagickTrue;
4457 windows->magnify.x=(int)
4458 width*windows->magnify.x/windows->image.ximage->width;
4459 windows->magnify.y=(int)
4460 height*windows->magnify.y/windows->image.ximage->height;
4461 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4462 windows->image.y=(int)
4463 (height*windows->image.y/windows->image.ximage->height);
4464 status=XMakeImage(display,resource_info,&windows->image,image,
4465 (unsigned int) width,(unsigned int) height,exception);
4466 if (status == MagickFalse)
4467 XNoticeWidget(display,windows,"Unable to configure X image:",
4468 windows->image.name);
4470 Notify window manager of the new configuration.
4472 if (resource_info->image_geometry != (char *) NULL)
4473 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4474 resource_info->image_geometry);
4476 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4477 XDisplayWidth(display,windows->image.screen),
4478 XDisplayHeight(display,windows->image.screen));
4479 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4480 window_changes.width=(int) width;
4481 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4482 window_changes.width=XDisplayWidth(display,windows->image.screen);
4483 window_changes.height=(int) height;
4484 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4485 window_changes.height=XDisplayHeight(display,windows->image.screen);
4486 mask=(size_t) (CWWidth | CWHeight);
4487 if (resource_info->backdrop)
4490 window_changes.x=(int)
4491 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4492 window_changes.y=(int)
4493 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4495 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4496 (unsigned int) mask,&window_changes);
4497 (void) XClearWindow(display,windows->image.id);
4498 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4500 Update Magnify window configuration.
4502 if (windows->magnify.mapped != MagickFalse)
4503 XMakeMagnifyImage(display,windows,exception);
4504 windows->pan.crop_geometry=windows->image.crop_geometry;
4505 XBestIconSize(display,&windows->pan,image);
4506 while (((windows->pan.width << 1) < MaxIconSize) &&
4507 ((windows->pan.height << 1) < MaxIconSize))
4509 windows->pan.width<<=1;
4510 windows->pan.height<<=1;
4512 if (windows->pan.geometry != (char *) NULL)
4513 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4514 &windows->pan.width,&windows->pan.height);
4515 window_changes.width=(int) windows->pan.width;
4516 window_changes.height=(int) windows->pan.height;
4517 size_hints=XAllocSizeHints();
4518 if (size_hints != (XSizeHints *) NULL)
4523 size_hints->flags=PSize | PMinSize | PMaxSize;
4524 size_hints->width=window_changes.width;
4525 size_hints->height=window_changes.height;
4526 size_hints->min_width=size_hints->width;
4527 size_hints->min_height=size_hints->height;
4528 size_hints->max_width=size_hints->width;
4529 size_hints->max_height=size_hints->height;
4530 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4531 (void) XFree((void *) size_hints);
4533 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4534 (unsigned int) (CWWidth | CWHeight),&window_changes);
4536 Update icon window configuration.
4538 windows->icon.crop_geometry=windows->image.crop_geometry;
4539 XBestIconSize(display,&windows->icon,image);
4540 window_changes.width=(int) windows->icon.width;
4541 window_changes.height=(int) windows->icon.height;
4542 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4543 (unsigned int) (CWWidth | CWHeight),&window_changes);
4544 XSetCursorState(display,windows,MagickFalse);
4545 return(status != 0 ? MagickTrue : MagickFalse);
4549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4553 + X C r o p I m a g e %
4557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4559 % XCropImage() allows the user to select a region of the image and crop, copy,
4560 % or cut it. For copy or cut, the image can subsequently be composited onto
4561 % the image with XPasteImage.
4563 % The format of the XCropImage method is:
4565 % MagickBooleanType XCropImage(Display *display,
4566 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4567 % const ClipboardMode mode,ExceptionInfo *exception)
4569 % A description of each parameter follows:
4571 % o display: Specifies a connection to an X server; returned from
4574 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4576 % o windows: Specifies a pointer to a XWindows structure.
4578 % o image: the image; returned from ReadImage.
4580 % o mode: This unsigned value specified whether the image should be
4581 % cropped, copied, or cut.
4583 % o exception: return any errors or warnings in this structure.
4586 static MagickBooleanType XCropImage(Display *display,
4587 XResourceInfo *resource_info,XWindows *windows,Image *image,
4588 const ClipboardMode mode,ExceptionInfo *exception)
4597 *RectifyModeMenu[] =
4605 static const ModeType
4615 RectifyDismissCommand
4622 command[MaxTextExtent],
4623 text[MaxTextExtent];
4666 (void) CloneString(&windows->command.name,"Copy");
4671 (void) CloneString(&windows->command.name,"Crop");
4676 (void) CloneString(&windows->command.name,"Cut");
4680 RectifyModeMenu[0]=windows->command.name;
4681 windows->command.data=0;
4682 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4683 (void) XMapRaised(display,windows->command.id);
4684 XClientMessage(display,windows->image.id,windows->im_protocols,
4685 windows->im_update_widget,CurrentTime);
4687 Track pointer until button 1 is pressed.
4689 XQueryPosition(display,windows->image.id,&x,&y);
4690 (void) XSelectInput(display,windows->image.id,
4691 windows->image.attributes.event_mask | PointerMotionMask);
4692 crop_info.x=(ssize_t) windows->image.x+x;
4693 crop_info.y=(ssize_t) windows->image.y+y;
4696 cursor=XCreateFontCursor(display,XC_fleur);
4700 if (windows->info.mapped != MagickFalse)
4703 Display pointer position.
4705 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4706 (long) crop_info.x,(long) crop_info.y);
4707 XInfoWidget(display,windows,text);
4710 Wait for next event.
4712 XScreenEvent(display,windows,&event,exception);
4713 if (event.xany.window == windows->command.id)
4716 Select a command from the Command widget.
4718 id=XCommandWidget(display,windows,CropModeMenu,&event);
4721 switch (CropCommands[id])
4723 case CropHelpCommand:
4729 XTextViewWidget(display,resource_info,windows,MagickFalse,
4730 "Help Viewer - Image Copy",ImageCopyHelp);
4735 XTextViewWidget(display,resource_info,windows,MagickFalse,
4736 "Help Viewer - Image Crop",ImageCropHelp);
4741 XTextViewWidget(display,resource_info,windows,MagickFalse,
4742 "Help Viewer - Image Cut",ImageCutHelp);
4748 case CropDismissCommand:
4766 if (event.xbutton.button != Button1)
4768 if (event.xbutton.window != windows->image.id)
4771 Note first corner of cropping rectangle-- exit loop.
4773 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4774 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4775 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4785 if (event.xkey.window != windows->image.id)
4788 Respond to a user key press.
4790 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4791 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4792 switch ((int) key_symbol)
4811 XTextViewWidget(display,resource_info,windows,MagickFalse,
4812 "Help Viewer - Image Copy",ImageCopyHelp);
4817 XTextViewWidget(display,resource_info,windows,MagickFalse,
4818 "Help Viewer - Image Crop",ImageCropHelp);
4823 XTextViewWidget(display,resource_info,windows,MagickFalse,
4824 "Help Viewer - Image Cut",ImageCutHelp);
4832 (void) XBell(display,0);
4840 if (event.xmotion.window != windows->image.id)
4843 Map and unmap Info widget as text cursor crosses its boundaries.
4847 if (windows->info.mapped != MagickFalse)
4849 if ((x < (int) (windows->info.x+windows->info.width)) &&
4850 (y < (int) (windows->info.y+windows->info.height)))
4851 (void) XWithdrawWindow(display,windows->info.id,
4852 windows->info.screen);
4855 if ((x > (int) (windows->info.x+windows->info.width)) ||
4856 (y > (int) (windows->info.y+windows->info.height)))
4857 (void) XMapWindow(display,windows->info.id);
4858 crop_info.x=(ssize_t) windows->image.x+x;
4859 crop_info.y=(ssize_t) windows->image.y+y;
4865 } while ((state & ExitState) == 0);
4866 (void) XSelectInput(display,windows->image.id,
4867 windows->image.attributes.event_mask);
4868 if ((state & EscapeState) != 0)
4871 User want to exit without cropping.
4873 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4874 (void) XFreeCursor(display,cursor);
4877 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4881 Size rectangle as pointer moves until the mouse button is released.
4883 x=(int) crop_info.x;
4884 y=(int) crop_info.y;
4890 highlight_info=crop_info;
4891 highlight_info.x=crop_info.x-windows->image.x;
4892 highlight_info.y=crop_info.y-windows->image.y;
4893 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4896 Display info and draw cropping rectangle.
4898 if (windows->info.mapped == MagickFalse)
4899 (void) XMapWindow(display,windows->info.id);
4900 (void) FormatLocaleString(text,MaxTextExtent,
4901 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4902 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4903 XInfoWidget(display,windows,text);
4904 XHighlightRectangle(display,windows->image.id,
4905 windows->image.highlight_context,&highlight_info);
4908 if (windows->info.mapped != MagickFalse)
4909 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4911 Wait for next event.
4913 XScreenEvent(display,windows,&event,exception);
4914 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4915 XHighlightRectangle(display,windows->image.id,
4916 windows->image.highlight_context,&highlight_info);
4921 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4922 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4928 User has committed to cropping rectangle.
4930 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4931 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4932 XSetCursorState(display,windows,MagickFalse);
4934 windows->command.data=0;
4935 (void) XCommandWidget(display,windows,RectifyModeMenu,
4943 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4944 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4949 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4950 ((state & ExitState) != 0))
4953 Check boundary conditions.
4955 if (crop_info.x < 0)
4958 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4959 crop_info.x=(ssize_t) windows->image.ximage->width;
4960 if ((int) crop_info.x < x)
4961 crop_info.width=(unsigned int) (x-crop_info.x);
4964 crop_info.width=(unsigned int) (crop_info.x-x);
4965 crop_info.x=(ssize_t) x;
4967 if (crop_info.y < 0)
4970 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4971 crop_info.y=(ssize_t) windows->image.ximage->height;
4972 if ((int) crop_info.y < y)
4973 crop_info.height=(unsigned int) (y-crop_info.y);
4976 crop_info.height=(unsigned int) (crop_info.y-y);
4977 crop_info.y=(ssize_t) y;
4980 } while ((state & ExitState) == 0);
4982 Wait for user to grab a corner of the rectangle or press return.
4985 (void) XMapWindow(display,windows->info.id);
4988 if (windows->info.mapped != MagickFalse)
4991 Display pointer position.
4993 (void) FormatLocaleString(text,MaxTextExtent,
4994 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4995 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4996 XInfoWidget(display,windows,text);
4998 highlight_info=crop_info;
4999 highlight_info.x=crop_info.x-windows->image.x;
5000 highlight_info.y=crop_info.y-windows->image.y;
5001 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
5007 XHighlightRectangle(display,windows->image.id,
5008 windows->image.highlight_context,&highlight_info);
5009 XScreenEvent(display,windows,&event,exception);
5010 if (event.xany.window == windows->command.id)
5013 Select a command from the Command widget.
5015 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5016 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5017 (void) XSetFunction(display,windows->image.highlight_context,
5019 XHighlightRectangle(display,windows->image.id,
5020 windows->image.highlight_context,&highlight_info);
5022 switch (RectifyCommands[id])
5024 case RectifyCopyCommand:
5029 case RectifyHelpCommand:
5031 (void) XSetFunction(display,windows->image.highlight_context,
5037 XTextViewWidget(display,resource_info,windows,MagickFalse,
5038 "Help Viewer - Image Copy",ImageCopyHelp);
5043 XTextViewWidget(display,resource_info,windows,MagickFalse,
5044 "Help Viewer - Image Crop",ImageCropHelp);
5049 XTextViewWidget(display,resource_info,windows,MagickFalse,
5050 "Help Viewer - Image Cut",ImageCutHelp);
5054 (void) XSetFunction(display,windows->image.highlight_context,
5058 case RectifyDismissCommand:
5072 XHighlightRectangle(display,windows->image.id,
5073 windows->image.highlight_context,&highlight_info);
5078 if (event.xbutton.button != Button1)
5080 if (event.xbutton.window != windows->image.id)
5082 x=windows->image.x+event.xbutton.x;
5083 y=windows->image.y+event.xbutton.y;
5084 if ((x < (int) (crop_info.x+RoiDelta)) &&
5085 (x > (int) (crop_info.x-RoiDelta)) &&
5086 (y < (int) (crop_info.y+RoiDelta)) &&
5087 (y > (int) (crop_info.y-RoiDelta)))
5089 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5090 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5091 state|=UpdateConfigurationState;
5094 if ((x < (int) (crop_info.x+RoiDelta)) &&
5095 (x > (int) (crop_info.x-RoiDelta)) &&
5096 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5097 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5099 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5100 state|=UpdateConfigurationState;
5103 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5104 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5105 (y < (int) (crop_info.y+RoiDelta)) &&
5106 (y > (int) (crop_info.y-RoiDelta)))
5108 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5109 state|=UpdateConfigurationState;
5112 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5113 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5114 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5115 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5117 state|=UpdateConfigurationState;
5123 if (event.xbutton.window == windows->pan.id)
5124 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5125 (highlight_info.y != crop_info.y-windows->image.y))
5126 XHighlightRectangle(display,windows->image.id,
5127 windows->image.highlight_context,&highlight_info);
5128 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5129 event.xbutton.time);
5134 if (event.xexpose.window == windows->image.id)
5135 if (event.xexpose.count == 0)
5137 event.xexpose.x=(int) highlight_info.x;
5138 event.xexpose.y=(int) highlight_info.y;
5139 event.xexpose.width=(int) highlight_info.width;
5140 event.xexpose.height=(int) highlight_info.height;
5141 XRefreshWindow(display,&windows->image,&event);
5143 if (event.xexpose.window == windows->info.id)
5144 if (event.xexpose.count == 0)
5145 XInfoWidget(display,windows,text);
5150 if (event.xkey.window != windows->image.id)
5153 Respond to a user key press.
5155 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5156 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5157 switch ((int) key_symbol)
5170 crop_info.x=(ssize_t) (windows->image.width/2L-
5171 crop_info.width/2L);
5172 crop_info.y=(ssize_t) (windows->image.height/2L-
5173 crop_info.height/2L);
5205 (void) XSetFunction(display,windows->image.highlight_context,
5211 XTextViewWidget(display,resource_info,windows,MagickFalse,
5212 "Help Viewer - Image Copy",ImageCopyHelp);
5217 XTextViewWidget(display,resource_info,windows,MagickFalse,
5218 "Help Viewer - Image Cropg",ImageCropHelp);
5223 XTextViewWidget(display,resource_info,windows,MagickFalse,
5224 "Help Viewer - Image Cutg",ImageCutHelp);
5228 (void) XSetFunction(display,windows->image.highlight_context,
5234 (void) XBell(display,0);
5238 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5246 if (event.xmotion.window != windows->image.id)
5249 Map and unmap Info widget as text cursor crosses its boundaries.
5253 if (windows->info.mapped != MagickFalse)
5255 if ((x < (int) (windows->info.x+windows->info.width)) &&
5256 (y < (int) (windows->info.y+windows->info.height)))
5257 (void) XWithdrawWindow(display,windows->info.id,
5258 windows->info.screen);
5261 if ((x > (int) (windows->info.x+windows->info.width)) ||
5262 (y > (int) (windows->info.y+windows->info.height)))
5263 (void) XMapWindow(display,windows->info.id);
5264 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5265 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5268 case SelectionRequest:
5273 XSelectionRequestEvent
5277 Set primary selection.
5279 (void) FormatLocaleString(text,MaxTextExtent,
5280 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5281 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5282 request=(&(event.xselectionrequest));
5283 (void) XChangeProperty(request->display,request->requestor,
5284 request->property,request->target,8,PropModeReplace,
5285 (unsigned char *) text,(int) strlen(text));
5286 notify.type=SelectionNotify;
5287 notify.display=request->display;
5288 notify.requestor=request->requestor;
5289 notify.selection=request->selection;
5290 notify.target=request->target;
5291 notify.time=request->time;
5292 if (request->property == None)
5293 notify.property=request->target;
5295 notify.property=request->property;
5296 (void) XSendEvent(request->display,request->requestor,False,0,
5297 (XEvent *) ¬ify);
5302 if ((state & UpdateConfigurationState) != 0)
5304 (void) XPutBackEvent(display,&event);
5305 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5308 } while ((state & ExitState) == 0);
5309 } while ((state & ExitState) == 0);
5310 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5311 XSetCursorState(display,windows,MagickFalse);
5312 if ((state & EscapeState) != 0)
5314 if (mode == CropMode)
5315 if (((int) crop_info.width != windows->image.ximage->width) ||
5316 ((int) crop_info.height != windows->image.ximage->height))
5319 Reconfigure Image window as defined by cropping rectangle.
5321 XSetCropGeometry(display,windows,&crop_info,image);
5322 windows->image.window_changes.width=(int) crop_info.width;
5323 windows->image.window_changes.height=(int) crop_info.height;
5324 (void) XConfigureImage(display,resource_info,windows,image,exception);
5328 Copy image before applying image transforms.
5330 XSetCursorState(display,windows,MagickTrue);
5331 XCheckRefreshWindows(display,windows);
5332 width=(unsigned int) image->columns;
5333 height=(unsigned int) image->rows;
5336 if (windows->image.crop_geometry != (char *) NULL)
5337 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5338 scale_factor=(MagickRealType) width/windows->image.ximage->width;
5340 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5341 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5342 scale_factor=(MagickRealType) height/windows->image.ximage->height;
5344 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5345 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5346 crop_image=CropImage(image,&crop_info,exception);
5347 XSetCursorState(display,windows,MagickFalse);
5348 if (crop_image == (Image *) NULL)
5349 return(MagickFalse);
5350 if (resource_info->copy_image != (Image *) NULL)
5351 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5352 resource_info->copy_image=crop_image;
5353 if (mode == CopyMode)
5355 (void) XConfigureImage(display,resource_info,windows,image,exception);
5361 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
5362 return(MagickFalse);
5363 image->matte=MagickTrue;
5364 image_view=AcquireCacheView(image);
5365 for (y=0; y < (int) crop_info.height; y++)
5367 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5368 crop_info.width,1,exception);
5369 if (q == (Quantum *) NULL)
5371 for (x=0; x < (int) crop_info.width; x++)
5373 SetPixelAlpha(image,TransparentAlpha,q);
5374 q+=GetPixelChannels(image);
5376 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
5379 image_view=DestroyCacheView(image_view);
5381 Update image configuration.
5383 XConfigureImageColormap(display,resource_info,windows,image,exception);
5384 (void) XConfigureImage(display,resource_info,windows,image,exception);
5389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5393 + X D r a w I m a g e %
5397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5399 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5402 % The format of the XDrawEditImage method is:
5404 % MagickBooleanType XDrawEditImage(Display *display,
5405 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5406 % ExceptionInfo *exception)
5408 % A description of each parameter follows:
5410 % o display: Specifies a connection to an X server; returned from
5413 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5415 % o windows: Specifies a pointer to a XWindows structure.
5417 % o image: the image.
5419 % o exception: return any errors or warnings in this structure.
5422 static MagickBooleanType XDrawEditImage(Display *display,
5423 XResourceInfo *resource_info,XWindows *windows,Image **image,
5424 ExceptionInfo *exception)
5440 element = PointElement;
5442 static const ModeType
5455 stipple = (Pixmap) NULL;
5462 command[MaxTextExtent],
5463 text[MaxTextExtent];
5512 Allocate polygon info.
5514 max_coordinates=2048;
5515 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5516 sizeof(*coordinate_info));
5517 if (coordinate_info == (XPoint *) NULL)
5519 (void) ThrowMagickException(exception,GetMagickModule(),
5520 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5521 return(MagickFalse);
5526 (void) CloneString(&windows->command.name,"Draw");
5527 windows->command.data=4;
5528 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5529 (void) XMapRaised(display,windows->command.id);
5530 XClientMessage(display,windows->image.id,windows->im_protocols,
5531 windows->im_update_widget,CurrentTime);
5533 Wait for first button press.
5535 root_window=XRootWindow(display,XDefaultScreen(display));
5536 draw_info.stencil=OpaqueStencil;
5538 cursor=XCreateFontCursor(display,XC_tcross);
5541 XQueryPosition(display,windows->image.id,&x,&y);
5542 (void) XSelectInput(display,windows->image.id,
5543 windows->image.attributes.event_mask | PointerMotionMask);
5544 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5548 if (windows->info.mapped != MagickFalse)
5551 Display pointer position.
5553 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5554 x+windows->image.x,y+windows->image.y);
5555 XInfoWidget(display,windows,text);
5558 Wait for next event.
5560 XScreenEvent(display,windows,&event,exception);
5561 if (event.xany.window == windows->command.id)
5564 Select a command from the Command widget.
5566 id=XCommandWidget(display,windows,DrawMenu,&event);
5569 switch (DrawCommands[id])
5571 case DrawElementCommand:
5590 Select a command from the pop-up menu.
5592 element=(ElementType) (XMenuWidget(display,windows,
5593 DrawMenu[id],Elements,command)+1);
5596 case DrawColorCommand:
5599 *ColorMenu[MaxNumberPens+1];
5611 Initialize menu selections.
5613 for (i=0; i < (int) (MaxNumberPens-2); i++)
5614 ColorMenu[i]=resource_info->pen_colors[i];
5615 ColorMenu[MaxNumberPens-2]="transparent";
5616 ColorMenu[MaxNumberPens-1]="Browser...";
5617 ColorMenu[MaxNumberPens]=(char *) NULL;
5619 Select a pen color from the pop-up menu.
5621 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5622 (const char **) ColorMenu,command);
5625 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5627 if (transparent != MagickFalse)
5629 draw_info.stencil=TransparentStencil;
5632 if (pen_number == (MaxNumberPens-1))
5635 color_name[MaxTextExtent] = "gray";
5638 Select a pen color from a dialog.
5640 resource_info->pen_colors[pen_number]=color_name;
5641 XColorBrowserWidget(display,windows,"Select",color_name);
5642 if (*color_name == '\0')
5648 (void) XParseColor(display,windows->map_info->colormap,
5649 resource_info->pen_colors[pen_number],&color);
5650 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5651 (unsigned int) MaxColors,&color);
5652 windows->pixel_info->pen_colors[pen_number]=color;
5653 pen_id=(unsigned int) pen_number;
5654 draw_info.stencil=OpaqueStencil;
5657 case DrawStippleCommand:
5669 filename[MaxTextExtent] = "\0";
5686 Select a command from the pop-up menu.
5688 StipplesMenu[7]="Open...";
5689 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5693 if (stipple != (Pixmap) NULL)
5694 (void) XFreePixmap(display,stipple);
5695 stipple=(Pixmap) NULL;
5702 stipple=XCreateBitmapFromData(display,root_window,
5703 (char *) BricksBitmap,BricksWidth,BricksHeight);
5708 stipple=XCreateBitmapFromData(display,root_window,
5709 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5714 stipple=XCreateBitmapFromData(display,root_window,
5715 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5720 stipple=XCreateBitmapFromData(display,root_window,
5721 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5726 stipple=XCreateBitmapFromData(display,root_window,
5727 (char *) WavyBitmap,WavyWidth,WavyHeight);
5732 stipple=XCreateBitmapFromData(display,root_window,
5733 (char *) HighlightBitmap,HighlightWidth,
5740 stipple=XCreateBitmapFromData(display,root_window,
5741 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5747 XFileBrowserWidget(display,windows,"Stipple",filename);
5748 if (*filename == '\0')
5753 XSetCursorState(display,windows,MagickTrue);
5754 XCheckRefreshWindows(display,windows);
5755 image_info=AcquireImageInfo();
5756 (void) CopyMagickString(image_info->filename,filename,
5758 stipple_image=ReadImage(image_info,exception);
5759 CatchException(exception);
5760 XSetCursorState(display,windows,MagickFalse);
5761 if (stipple_image == (Image *) NULL)
5763 (void) AcquireUniqueFileResource(filename);
5764 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5766 (void) WriteImage(image_info,stipple_image,exception);
5767 stipple_image=DestroyImage(stipple_image);
5768 image_info=DestroyImageInfo(image_info);
5769 status=XReadBitmapFile(display,root_window,filename,&width,
5770 &height,&stipple,&x,&y);
5771 (void) RelinquishUniqueFileResource(filename);
5772 if ((status != BitmapSuccess) != 0)
5773 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5777 case DrawWidthCommand:
5780 width[MaxTextExtent] = "0";
5795 Select a command from the pop-up menu.
5797 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5803 line_width=(unsigned int) StringToUnsignedLong(
5807 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5811 line_width=(unsigned int) StringToUnsignedLong(width);
5814 case DrawUndoCommand:
5816 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5820 case DrawHelpCommand:
5822 XTextViewWidget(display,resource_info,windows,MagickFalse,
5823 "Help Viewer - Image Rotation",ImageDrawHelp);
5824 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5827 case DrawDismissCommand:
5839 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5846 if (event.xbutton.button != Button1)
5848 if (event.xbutton.window != windows->image.id)
5867 if (event.xkey.window != windows->image.id)
5870 Respond to a user key press.
5872 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5873 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5874 switch ((int) key_symbol)
5889 XTextViewWidget(display,resource_info,windows,MagickFalse,
5890 "Help Viewer - Image Rotation",ImageDrawHelp);
5895 (void) XBell(display,0);
5904 Map and unmap Info widget as text cursor crosses its boundaries.
5908 if (windows->info.mapped != MagickFalse)
5910 if ((x < (int) (windows->info.x+windows->info.width)) &&
5911 (y < (int) (windows->info.y+windows->info.height)))
5912 (void) XWithdrawWindow(display,windows->info.id,
5913 windows->info.screen);
5916 if ((x > (int) (windows->info.x+windows->info.width)) ||
5917 (y > (int) (windows->info.y+windows->info.height)))
5918 (void) XMapWindow(display,windows->info.id);
5922 } while ((state & ExitState) == 0);
5923 (void) XSelectInput(display,windows->image.id,
5924 windows->image.attributes.event_mask);
5925 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5926 if ((state & EscapeState) != 0)
5929 Draw element as pointer moves until the button is released.
5937 rectangle_info.x=(ssize_t) x;
5938 rectangle_info.y=(ssize_t) y;
5939 rectangle_info.width=0;
5940 rectangle_info.height=0;
5941 number_coordinates=1;
5942 coordinate_info->x=x;
5943 coordinate_info->y=y;
5944 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5953 if (number_coordinates > 1)
5955 (void) XDrawLines(display,windows->image.id,
5956 windows->image.highlight_context,coordinate_info,
5957 number_coordinates,CoordModeOrigin);
5958 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5959 coordinate_info[number_coordinates-1].x,
5960 coordinate_info[number_coordinates-1].y);
5961 XInfoWidget(display,windows,text);
5970 Display angle of the line.
5972 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5973 line_info.y1),(double) (line_info.x2-line_info.x1)));
5974 (void) FormatLocaleString(text,MaxTextExtent," %g",
5976 XInfoWidget(display,windows,text);
5977 XHighlightLine(display,windows->image.id,
5978 windows->image.highlight_context,&line_info);
5981 if (windows->info.mapped != MagickFalse)
5982 (void) XWithdrawWindow(display,windows->info.id,
5983 windows->info.screen);
5986 case RectangleElement:
5987 case FillRectangleElement:
5989 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5992 Display info and draw drawing rectangle.
5994 (void) FormatLocaleString(text,MaxTextExtent,
5995 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5996 (double) rectangle_info.height,(double) rectangle_info.x,
5997 (double) rectangle_info.y);
5998 XInfoWidget(display,windows,text);
5999 XHighlightRectangle(display,windows->image.id,
6000 windows->image.highlight_context,&rectangle_info);
6003 if (windows->info.mapped != MagickFalse)
6004 (void) XWithdrawWindow(display,windows->info.id,
6005 windows->info.screen);
6009 case FillCircleElement:
6010 case EllipseElement:
6011 case FillEllipseElement:
6013 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6016 Display info and draw drawing rectangle.
6018 (void) FormatLocaleString(text,MaxTextExtent,
6019 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6020 (double) rectangle_info.height,(double) rectangle_info.x,
6021 (double) rectangle_info.y);
6022 XInfoWidget(display,windows,text);
6023 XHighlightEllipse(display,windows->image.id,
6024 windows->image.highlight_context,&rectangle_info);
6027 if (windows->info.mapped != MagickFalse)
6028 (void) XWithdrawWindow(display,windows->info.id,
6029 windows->info.screen);
6032 case PolygonElement:
6033 case FillPolygonElement:
6035 if (number_coordinates > 1)
6036 (void) XDrawLines(display,windows->image.id,
6037 windows->image.highlight_context,coordinate_info,
6038 number_coordinates,CoordModeOrigin);
6042 Display angle of the line.
6044 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6045 line_info.y1),(double) (line_info.x2-line_info.x1)));
6046 (void) FormatLocaleString(text,MaxTextExtent," %g",
6048 XInfoWidget(display,windows,text);
6049 XHighlightLine(display,windows->image.id,
6050 windows->image.highlight_context,&line_info);
6053 if (windows->info.mapped != MagickFalse)
6054 (void) XWithdrawWindow(display,windows->info.id,
6055 windows->info.screen);
6060 Wait for next event.
6062 XScreenEvent(display,windows,&event,exception);
6068 if (number_coordinates > 1)
6069 (void) XDrawLines(display,windows->image.id,
6070 windows->image.highlight_context,coordinate_info,
6071 number_coordinates,CoordModeOrigin);
6077 XHighlightLine(display,windows->image.id,
6078 windows->image.highlight_context,&line_info);
6081 case RectangleElement:
6082 case FillRectangleElement:
6084 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6085 XHighlightRectangle(display,windows->image.id,
6086 windows->image.highlight_context,&rectangle_info);
6090 case FillCircleElement:
6091 case EllipseElement:
6092 case FillEllipseElement:
6094 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6095 XHighlightEllipse(display,windows->image.id,
6096 windows->image.highlight_context,&rectangle_info);
6099 case PolygonElement:
6100 case FillPolygonElement:
6102 if (number_coordinates > 1)
6103 (void) XDrawLines(display,windows->image.id,
6104 windows->image.highlight_context,coordinate_info,
6105 number_coordinates,CoordModeOrigin);
6107 XHighlightLine(display,windows->image.id,
6108 windows->image.highlight_context,&line_info);
6119 User has committed to element.
6121 line_info.x2=event.xbutton.x;
6122 line_info.y2=event.xbutton.y;
6123 rectangle_info.x=(ssize_t) event.xbutton.x;
6124 rectangle_info.y=(ssize_t) event.xbutton.y;
6125 coordinate_info[number_coordinates].x=event.xbutton.x;
6126 coordinate_info[number_coordinates].y=event.xbutton.y;
6127 if (((element != PolygonElement) &&
6128 (element != FillPolygonElement)) || (distance <= 9))
6133 number_coordinates++;
6134 if (number_coordinates < (int) max_coordinates)
6136 line_info.x1=event.xbutton.x;
6137 line_info.y1=event.xbutton.y;
6140 max_coordinates<<=1;
6141 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6142 max_coordinates,sizeof(*coordinate_info));
6143 if (coordinate_info == (XPoint *) NULL)
6144 (void) ThrowMagickException(exception,GetMagickModule(),
6145 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6152 if (event.xmotion.window != windows->image.id)
6154 if (element != PointElement)
6156 line_info.x2=event.xmotion.x;
6157 line_info.y2=event.xmotion.y;
6158 rectangle_info.x=(ssize_t) event.xmotion.x;
6159 rectangle_info.y=(ssize_t) event.xmotion.y;
6162 coordinate_info[number_coordinates].x=event.xbutton.x;
6163 coordinate_info[number_coordinates].y=event.xbutton.y;
6164 number_coordinates++;
6165 if (number_coordinates < (int) max_coordinates)
6167 max_coordinates<<=1;
6168 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6169 max_coordinates,sizeof(*coordinate_info));
6170 if (coordinate_info == (XPoint *) NULL)
6171 (void) ThrowMagickException(exception,GetMagickModule(),
6172 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6179 Check boundary conditions.
6181 if (line_info.x2 < 0)
6184 if (line_info.x2 > (int) windows->image.width)
6185 line_info.x2=(short) windows->image.width;
6186 if (line_info.y2 < 0)
6189 if (line_info.y2 > (int) windows->image.height)
6190 line_info.y2=(short) windows->image.height;
6191 distance=(unsigned int)
6192 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6193 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6194 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6195 ((state & ExitState) != 0))
6197 if (rectangle_info.x < 0)
6200 if (rectangle_info.x > (ssize_t) windows->image.width)
6201 rectangle_info.x=(ssize_t) windows->image.width;
6202 if ((int) rectangle_info.x < x)
6203 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6206 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6207 rectangle_info.x=(ssize_t) x;
6209 if (rectangle_info.y < 0)
6212 if (rectangle_info.y > (ssize_t) windows->image.height)
6213 rectangle_info.y=(ssize_t) windows->image.height;
6214 if ((int) rectangle_info.y < y)
6215 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6218 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6219 rectangle_info.y=(ssize_t) y;
6222 } while ((state & ExitState) == 0);
6223 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6224 if ((element == PointElement) || (element == PolygonElement) ||
6225 (element == FillPolygonElement))
6228 Determine polygon bounding box.
6230 rectangle_info.x=(ssize_t) coordinate_info->x;
6231 rectangle_info.y=(ssize_t) coordinate_info->y;
6232 x=coordinate_info->x;
6233 y=coordinate_info->y;
6234 for (i=1; i < number_coordinates; i++)
6236 if (coordinate_info[i].x > x)
6237 x=coordinate_info[i].x;
6238 if (coordinate_info[i].y > y)
6239 y=coordinate_info[i].y;
6240 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6241 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6242 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6243 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6245 rectangle_info.width=(size_t) (x-rectangle_info.x);
6246 rectangle_info.height=(size_t) (y-rectangle_info.y);
6247 for (i=0; i < number_coordinates; i++)
6249 coordinate_info[i].x-=rectangle_info.x;
6250 coordinate_info[i].y-=rectangle_info.y;
6257 if ((element == RectangleElement) ||
6258 (element == CircleElement) || (element == EllipseElement))
6260 rectangle_info.width--;
6261 rectangle_info.height--;
6264 Drawing is relative to image configuration.
6266 draw_info.x=(int) rectangle_info.x;
6267 draw_info.y=(int) rectangle_info.y;
6268 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6270 width=(unsigned int) (*image)->columns;
6271 height=(unsigned int) (*image)->rows;
6274 if (windows->image.crop_geometry != (char *) NULL)
6275 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6276 draw_info.x+=windows->image.x-(line_width/2);
6277 if (draw_info.x < 0)
6279 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6280 draw_info.y+=windows->image.y-(line_width/2);
6281 if (draw_info.y < 0)
6283 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6284 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6285 if (draw_info.width > (unsigned int) (*image)->columns)
6286 draw_info.width=(unsigned int) (*image)->columns;
6287 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6288 if (draw_info.height > (unsigned int) (*image)->rows)
6289 draw_info.height=(unsigned int) (*image)->rows;
6290 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6291 width*draw_info.width/windows->image.ximage->width,
6292 height*draw_info.height/windows->image.ximage->height,
6293 draw_info.x+x,draw_info.y+y);
6295 Initialize drawing attributes.
6297 draw_info.degrees=0.0;
6298 draw_info.element=element;
6299 draw_info.stipple=stipple;
6300 draw_info.line_width=line_width;
6301 draw_info.line_info=line_info;
6302 if (line_info.x1 > (int) (line_width/2))
6303 draw_info.line_info.x1=(short) line_width/2;
6304 if (line_info.y1 > (int) (line_width/2))
6305 draw_info.line_info.y1=(short) line_width/2;
6306 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6307 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6308 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6310 draw_info.line_info.x2=(-draw_info.line_info.x2);
6311 draw_info.line_info.y2=(-draw_info.line_info.y2);
6313 if (draw_info.line_info.x2 < 0)
6315 draw_info.line_info.x2=(-draw_info.line_info.x2);
6316 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6318 if (draw_info.line_info.y2 < 0)
6320 draw_info.line_info.y2=(-draw_info.line_info.y2);
6321 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6323 draw_info.rectangle_info=rectangle_info;
6324 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6325 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6326 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6327 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6328 draw_info.number_coordinates=(unsigned int) number_coordinates;
6329 draw_info.coordinate_info=coordinate_info;
6330 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6332 Draw element on image.
6334 XSetCursorState(display,windows,MagickTrue);
6335 XCheckRefreshWindows(display,windows);
6336 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6337 XSetCursorState(display,windows,MagickFalse);
6339 Update image colormap and return to image drawing.
6341 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6342 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6344 XSetCursorState(display,windows,MagickFalse);
6345 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6346 return(status != 0 ? MagickTrue : MagickFalse);
6350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6354 + X D r a w P a n R e c t a n g l e %
6358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6360 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6361 % displays a zoom image and the rectangle shows which portion of the image is
6362 % displayed in the Image window.
6364 % The format of the XDrawPanRectangle method is:
6366 % XDrawPanRectangle(Display *display,XWindows *windows)
6368 % A description of each parameter follows:
6370 % o display: Specifies a connection to an X server; returned from
6373 % o windows: Specifies a pointer to a XWindows structure.
6376 static void XDrawPanRectangle(Display *display,XWindows *windows)
6385 Determine dimensions of the panning rectangle.
6387 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
6388 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6389 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6390 scale_factor=(MagickRealType)
6391 windows->pan.height/windows->image.ximage->height;
6392 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6393 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6395 Display the panning rectangle.
6397 (void) XClearWindow(display,windows->pan.id);
6398 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6407 + X I m a g e C a c h e %
6411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6413 % XImageCache() handles the creation, manipulation, and destruction of the
6414 % image cache (undo and redo buffers).
6416 % The format of the XImageCache method is:
6418 % void XImageCache(Display *display,XResourceInfo *resource_info,
6419 % XWindows *windows,const CommandType command,Image **image,
6420 % ExceptionInfo *exception)
6422 % A description of each parameter follows:
6424 % o display: Specifies a connection to an X server; returned from
6427 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6429 % o windows: Specifies a pointer to a XWindows structure.
6431 % o command: Specifies a command to perform.
6433 % o image: the image; XImageCache may transform the image and return a new
6436 % o exception: return any errors or warnings in this structure.
6439 static void XImageCache(Display *display,XResourceInfo *resource_info,
6440 XWindows *windows,const CommandType command,Image **image,
6441 ExceptionInfo *exception)
6447 *redo_image = (Image *) NULL,
6448 *undo_image = (Image *) NULL;
6452 case FreeBuffersCommand:
6455 Free memory from the undo and redo cache.
6457 while (undo_image != (Image *) NULL)
6459 cache_image=undo_image;
6460 undo_image=GetPreviousImageInList(undo_image);
6461 cache_image->list=DestroyImage(cache_image->list);
6462 cache_image=DestroyImage(cache_image);
6464 undo_image=NewImageList();
6465 if (redo_image != (Image *) NULL)
6466 redo_image=DestroyImage(redo_image);
6467 redo_image=NewImageList();
6473 image_geometry[MaxTextExtent];
6476 Undo the last image transformation.
6478 if (undo_image == (Image *) NULL)
6480 (void) XBell(display,0);
6483 cache_image=undo_image;
6484 undo_image=GetPreviousImageInList(undo_image);
6485 windows->image.window_changes.width=(int) cache_image->columns;
6486 windows->image.window_changes.height=(int) cache_image->rows;
6487 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6488 windows->image.ximage->width,windows->image.ximage->height);
6489 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6491 if (windows->image.crop_geometry != (char *) NULL)
6492 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6493 windows->image.crop_geometry);
6494 windows->image.crop_geometry=cache_image->geometry;
6495 if (redo_image != (Image *) NULL)
6496 redo_image=DestroyImage(redo_image);
6497 redo_image=(*image);
6498 *image=cache_image->list;
6499 cache_image=DestroyImage(cache_image);
6500 if (windows->image.orphan != MagickFalse)
6502 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6503 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6509 case HalfSizeCommand:
6510 case OriginalSizeCommand:
6511 case DoubleSizeCommand:
6518 case RotateRightCommand:
6519 case RotateLeftCommand:
6524 case ContrastStretchCommand:
6525 case SigmoidalContrastCommand:
6526 case NormalizeCommand:
6527 case EqualizeCommand:
6529 case SaturationCommand:
6530 case BrightnessCommand:
6534 case GrayscaleCommand:
6536 case QuantizeCommand:
6537 case DespeckleCommand:
6539 case ReduceNoiseCommand:
6540 case AddNoiseCommand:
6541 case SharpenCommand:
6543 case ThresholdCommand:
6544 case EdgeDetectCommand:
6548 case SegmentCommand:
6549 case SolarizeCommand:
6550 case SepiaToneCommand:
6552 case ImplodeCommand:
6553 case VignetteCommand:
6555 case OilPaintCommand:
6556 case CharcoalDrawCommand:
6557 case AnnotateCommand:
6558 case AddBorderCommand:
6559 case AddFrameCommand:
6560 case CompositeCommand:
6561 case CommentCommand:
6563 case RegionofInterestCommand:
6564 case SaveToUndoBufferCommand:
6573 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6574 if (undo_image != (Image *) NULL)
6577 Ensure the undo cache has enough memory available.
6579 previous_image=undo_image;
6580 while (previous_image != (Image *) NULL)
6582 bytes+=previous_image->list->columns*previous_image->list->rows*
6584 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6586 previous_image=GetPreviousImageInList(previous_image);
6589 bytes-=previous_image->list->columns*previous_image->list->rows*
6591 if (previous_image == undo_image)
6592 undo_image=NewImageList();
6594 previous_image->next->previous=NewImageList();
6597 while (previous_image != (Image *) NULL)
6600 Delete any excess memory from undo cache.
6602 cache_image=previous_image;
6603 previous_image=GetPreviousImageInList(previous_image);
6604 cache_image->list=DestroyImage(cache_image->list);
6605 cache_image=DestroyImage(cache_image);
6608 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6611 Save image before transformations are applied.
6613 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6614 if (cache_image == (Image *) NULL)
6616 XSetCursorState(display,windows,MagickTrue);
6617 XCheckRefreshWindows(display,windows);
6618 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6619 XSetCursorState(display,windows,MagickFalse);
6620 if (cache_image->list == (Image *) NULL)
6622 cache_image=DestroyImage(cache_image);
6625 cache_image->columns=(size_t) windows->image.ximage->width;
6626 cache_image->rows=(size_t) windows->image.ximage->height;
6627 cache_image->geometry=windows->image.crop_geometry;
6628 if (windows->image.crop_geometry != (char *) NULL)
6630 cache_image->geometry=AcquireString((char *) NULL);
6631 (void) CopyMagickString(cache_image->geometry,
6632 windows->image.crop_geometry,MaxTextExtent);
6634 if (undo_image == (Image *) NULL)
6636 undo_image=cache_image;
6639 undo_image->next=cache_image;
6640 undo_image->next->previous=undo_image;
6641 undo_image=undo_image->next;
6647 if (command == RedoCommand)
6650 Redo the last image transformation.
6652 if (redo_image == (Image *) NULL)
6654 (void) XBell(display,0);
6657 windows->image.window_changes.width=(int) redo_image->columns;
6658 windows->image.window_changes.height=(int) redo_image->rows;
6659 if (windows->image.crop_geometry != (char *) NULL)
6660 windows->image.crop_geometry=(char *)
6661 RelinquishMagickMemory(windows->image.crop_geometry);
6662 windows->image.crop_geometry=redo_image->geometry;
6663 *image=DestroyImage(*image);
6665 redo_image=NewImageList();
6666 if (windows->image.orphan != MagickFalse)
6668 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6669 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6672 if (command != InfoCommand)
6677 XSetCursorState(display,windows,MagickTrue);
6678 XCheckRefreshWindows(display,windows);
6679 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6680 XSetCursorState(display,windows,MagickFalse);
6684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6688 + X I m a g e W i n d o w C o m m a n d %
6692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6694 % XImageWindowCommand() makes a transform to the image or Image window as
6695 % specified by a user menu button or keyboard command.
6697 % The format of the XImageWindowCommand method is:
6699 % CommandType XImageWindowCommand(Display *display,
6700 % XResourceInfo *resource_info,XWindows *windows,
6701 % const MagickStatusType state,KeySym key_symbol,Image **image,
6702 % ExceptionInfo *exception)
6704 % A description of each parameter follows:
6706 % o nexus: Method XImageWindowCommand returns an image when the
6707 % user chooses 'Open Image' from the command menu. Otherwise a null
6708 % image is returned.
6710 % o display: Specifies a connection to an X server; returned from
6713 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6715 % o windows: Specifies a pointer to a XWindows structure.
6717 % o state: key mask.
6719 % o key_symbol: Specifies a command to perform.
6721 % o image: the image; XImageWIndowCommand may transform the image and
6722 % return a new image pointer.
6724 % o exception: return any errors or warnings in this structure.
6727 static CommandType XImageWindowCommand(Display *display,
6728 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6729 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6732 delta[MaxTextExtent] = "";
6735 Digits[] = "01234567890";
6740 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6742 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6745 resource_info->quantum=1;
6747 last_symbol=key_symbol;
6748 delta[strlen(delta)+1]='\0';
6749 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6750 resource_info->quantum=StringToLong(delta);
6751 return(NullCommand);
6753 last_symbol=key_symbol;
6754 if (resource_info->immutable)
6757 Virtual image window has a restricted command set.
6762 return(InfoCommand);
6765 return(PrintCommand);
6767 return(NextCommand);
6770 return(QuitCommand);
6774 return(NullCommand);
6776 switch ((int) key_symbol)
6780 if ((state & ControlMask) == 0)
6782 return(OpenCommand);
6785 return(NextCommand);
6787 return(FormerCommand);
6790 if ((state & Mod1Mask) != 0)
6791 return(SwirlCommand);
6792 if ((state & ControlMask) == 0)
6793 return(ShearCommand);
6794 return(SaveCommand);
6799 if ((state & Mod1Mask) != 0)
6800 return(OilPaintCommand);
6801 if ((state & Mod4Mask) != 0)
6802 return(ColorCommand);
6803 if ((state & ControlMask) == 0)
6804 return(NullCommand);
6805 return(PrintCommand);
6809 if ((state & Mod4Mask) != 0)
6810 return(DrawCommand);
6811 if ((state & ControlMask) == 0)
6812 return(NullCommand);
6813 return(DeleteCommand);
6817 if ((state & ControlMask) == 0)
6818 return(NullCommand);
6819 return(SelectCommand);
6823 if ((state & ControlMask) == 0)
6824 return(NullCommand);
6829 return(QuitCommand);
6833 if ((state & ControlMask) == 0)
6834 return(NullCommand);
6835 return(UndoCommand);
6840 if ((state & ControlMask) == 0)
6841 return(RollCommand);
6842 return(RedoCommand);
6846 if ((state & ControlMask) == 0)
6847 return(NullCommand);
6852 if ((state & Mod1Mask) != 0)
6853 return(CharcoalDrawCommand);
6854 if ((state & ControlMask) == 0)
6855 return(CropCommand);
6856 return(CopyCommand);
6861 if ((state & Mod4Mask) != 0)
6862 return(CompositeCommand);
6863 if ((state & ControlMask) == 0)
6864 return(FlipCommand);
6865 return(PasteCommand);
6868 return(HalfSizeCommand);
6870 return(OriginalSizeCommand);
6872 return(DoubleSizeCommand);
6874 return(ResizeCommand);
6876 return(RefreshCommand);
6877 case XK_bracketleft:
6878 return(ChopCommand);
6880 return(FlopCommand);
6882 return(RotateRightCommand);
6884 return(RotateLeftCommand);
6886 return(RotateCommand);
6888 return(TrimCommand);
6892 return(SaturationCommand);
6894 return(BrightnessCommand);
6896 return(GammaCommand);
6898 return(SpiffCommand);
6900 return(DullCommand);
6902 return(NormalizeCommand);
6904 return(EqualizeCommand);
6906 return(NegateCommand);
6908 return(GrayscaleCommand);
6910 return(QuantizeCommand);
6912 return(DespeckleCommand);
6914 return(EmbossCommand);
6916 return(ReduceNoiseCommand);
6918 return(AddNoiseCommand);
6920 return(SharpenCommand);
6922 return(BlurCommand);
6924 return(ThresholdCommand);
6926 return(EdgeDetectCommand);
6928 return(SpreadCommand);
6930 return(ShadeCommand);
6932 return(RaiseCommand);
6934 return(SegmentCommand);
6937 if ((state & Mod1Mask) == 0)
6938 return(NullCommand);
6939 return(ImplodeCommand);
6943 if ((state & Mod1Mask) == 0)
6944 return(NullCommand);
6945 return(WaveCommand);
6949 if ((state & Mod4Mask) == 0)
6950 return(NullCommand);
6951 return(MatteCommand);
6955 if ((state & Mod4Mask) == 0)
6956 return(NullCommand);
6957 return(AddBorderCommand);
6961 if ((state & Mod4Mask) == 0)
6962 return(NullCommand);
6963 return(AddFrameCommand);
6967 if ((state & Mod4Mask) == 0)
6968 return(NullCommand);
6969 return(CommentCommand);
6973 if ((state & Mod1Mask) != 0)
6974 return(ApplyCommand);
6975 if ((state & Mod4Mask) != 0)
6976 return(AnnotateCommand);
6977 if ((state & ControlMask) == 0)
6978 return(NullCommand);
6979 return(RegionofInterestCommand);
6982 return(InfoCommand);
6984 return(ZoomCommand);
6987 if ((state & ShiftMask) == 0)
6988 return(NullCommand);
6989 return(ShowPreviewCommand);
6992 return(LaunchCommand);
6994 return(HelpCommand);
6996 return(BrowseDocumentationCommand);
6999 (void) XMapRaised(display,windows->command.id);
7000 return(NullCommand);
7007 XTranslateImage(display,windows,*image,key_symbol);
7008 return(NullCommand);
7019 if ((state & Mod1Mask) != 0)
7025 Trim one pixel from edge of image.
7029 crop_info.width=(size_t) windows->image.ximage->width;
7030 crop_info.height=(size_t) windows->image.ximage->height;
7031 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7033 if (resource_info->quantum >= (int) crop_info.height)
7034 resource_info->quantum=(int) crop_info.height-1;
7035 crop_info.height-=resource_info->quantum;
7037 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7039 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7040 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7041 crop_info.y+=resource_info->quantum;
7042 crop_info.height-=resource_info->quantum;
7044 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7046 if (resource_info->quantum >= (int) crop_info.width)
7047 resource_info->quantum=(int) crop_info.width-1;
7048 crop_info.width-=resource_info->quantum;
7050 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7052 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7053 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7054 crop_info.x+=resource_info->quantum;
7055 crop_info.width-=resource_info->quantum;
7057 if ((int) (windows->image.x+windows->image.width) >
7058 (int) crop_info.width)
7059 windows->image.x=(int) (crop_info.width-windows->image.width);
7060 if ((int) (windows->image.y+windows->image.height) >
7061 (int) crop_info.height)
7062 windows->image.y=(int) (crop_info.height-windows->image.height);
7063 XSetCropGeometry(display,windows,&crop_info,*image);
7064 windows->image.window_changes.width=(int) crop_info.width;
7065 windows->image.window_changes.height=(int) crop_info.height;
7066 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7067 (void) XConfigureImage(display,resource_info,windows,*image,
7069 return(NullCommand);
7071 XTranslateImage(display,windows,*image,key_symbol);
7072 return(NullCommand);
7075 return(NullCommand);
7077 return(NullCommand);
7081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7085 + X M a g i c k C o m m a n d %
7089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7091 % XMagickCommand() makes a transform to the image or Image window as
7092 % specified by a user menu button or keyboard command.
7094 % The format of the XMagickCommand method is:
7096 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7097 % XWindows *windows,const CommandType command,Image **image,
7098 % ExceptionInfo *exception)
7100 % A description of each parameter follows:
7102 % o display: Specifies a connection to an X server; returned from
7105 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7107 % o windows: Specifies a pointer to a XWindows structure.
7109 % o command: Specifies a command to perform.
7111 % o image: the image; XMagickCommand may transform the image and return a
7112 % new image pointer.
7114 % o exception: return any errors or warnings in this structure.
7117 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7118 XWindows *windows,const CommandType command,Image **image,
7119 ExceptionInfo *exception)
7122 filename[MaxTextExtent],
7123 geometry[MaxTextExtent],
7124 modulate_factors[MaxTextExtent];
7153 color[MaxTextExtent] = "gray";
7160 Process user command.
7162 XCheckRefreshWindows(display,windows);
7163 XImageCache(display,resource_info,windows,command,image,exception);
7164 nexus=NewImageList();
7165 windows->image.window_changes.width=windows->image.ximage->width;
7166 windows->image.window_changes.height=windows->image.ximage->height;
7167 image_info=CloneImageInfo(resource_info->image_info);
7168 SetGeometryInfo(&geometry_info);
7169 GetQuantizeInfo(&quantize_info);
7177 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7185 for (i=0; i < resource_info->quantum; i++)
7186 XClientMessage(display,windows->image.id,windows->im_protocols,
7187 windows->im_next_image,CurrentTime);
7193 Display former image.
7195 for (i=0; i < resource_info->quantum; i++)
7196 XClientMessage(display,windows->image.id,windows->im_protocols,
7197 windows->im_former_image,CurrentTime);
7208 status=chdir(resource_info->home_directory);
7210 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7211 "UnableToOpenFile","%s",resource_info->home_directory);
7212 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7220 status=XSaveImage(display,resource_info,windows,*image,exception);
7221 if (status == MagickFalse)
7224 message[MaxTextExtent];
7226 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7227 exception->reason != (char *) NULL ? exception->reason : "",
7228 exception->description != (char *) NULL ? exception->description :
7230 XNoticeWidget(display,windows,"Unable to save file:",message);
7240 status=XPrintImage(display,resource_info,windows,*image,exception);
7241 if (status == MagickFalse)
7244 message[MaxTextExtent];
7246 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7247 exception->reason != (char *) NULL ? exception->reason : "",
7248 exception->description != (char *) NULL ? exception->description :
7250 XNoticeWidget(display,windows,"Unable to print file:",message);
7258 filename[MaxTextExtent] = "\0";
7263 XFileBrowserWidget(display,windows,"Delete",filename);
7264 if (*filename == '\0')
7266 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
7267 if (status != MagickFalse)
7268 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7277 color[MaxTextExtent] = "gray",
7278 geometry[MaxTextExtent] = "640x480";
7281 *format = "gradient";
7284 Query user for canvas geometry.
7286 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7288 if (*geometry == '\0')
7292 XColorBrowserWidget(display,windows,"Select",color);
7298 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7299 "%s:%s",format,color);
7300 (void) CloneString(&image_info->size,geometry);
7301 nexus=ReadImage(image_info,exception);
7302 CatchException(exception);
7303 XClientMessage(display,windows->image.id,windows->im_protocols,
7304 windows->im_next_image,CurrentTime);
7307 case VisualDirectoryCommand:
7310 Visual Image directory.
7312 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7320 if (resource_info->confirm_exit == MagickFalse)
7321 XClientMessage(display,windows->image.id,windows->im_protocols,
7322 windows->im_exit,CurrentTime);
7329 Confirm program exit.
7331 status=XConfirmWidget(display,windows,"Do you really want to exit",
7332 resource_info->client_name);
7334 XClientMessage(display,windows->image.id,windows->im_protocols,
7335 windows->im_exit,CurrentTime);
7344 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7352 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7361 status=XPasteImage(display,resource_info,windows,*image,exception);
7362 if (status == MagickFalse)
7364 XNoticeWidget(display,windows,"Unable to paste X image",
7365 (*image)->filename);
7370 case HalfSizeCommand:
7375 windows->image.window_changes.width=windows->image.ximage->width/2;
7376 windows->image.window_changes.height=windows->image.ximage->height/2;
7377 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7380 case OriginalSizeCommand:
7383 Original image size.
7385 windows->image.window_changes.width=(int) (*image)->columns;
7386 windows->image.window_changes.height=(int) (*image)->rows;
7387 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7390 case DoubleSizeCommand:
7393 Double the image size.
7395 windows->image.window_changes.width=windows->image.ximage->width << 1;
7396 windows->image.window_changes.height=windows->image.ximage->height << 1;
7397 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7416 width=(size_t) windows->image.ximage->width;
7417 height=(size_t) windows->image.ximage->height;
7420 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7421 (double) width,(double) height);
7422 status=XDialogWidget(display,windows,"Resize",
7423 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7424 if (*geometry == '\0')
7427 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7428 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7429 windows->image.window_changes.width=(int) width;
7430 windows->image.window_changes.height=(int) height;
7431 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7437 image_geometry[MaxTextExtent];
7439 if ((windows->image.crop_geometry == (char *) NULL) &&
7440 ((int) (*image)->columns == windows->image.ximage->width) &&
7441 ((int) (*image)->rows == windows->image.ximage->height))
7444 Apply size transforms to image.
7446 XSetCursorState(display,windows,MagickTrue);
7447 XCheckRefreshWindows(display,windows);
7449 Crop and/or scale displayed image.
7451 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7452 windows->image.ximage->width,windows->image.ximage->height);
7453 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7455 if (windows->image.crop_geometry != (char *) NULL)
7456 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7457 windows->image.crop_geometry);
7460 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7461 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7464 case RefreshCommand:
7466 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7469 case RestoreCommand:
7472 Restore Image window to its original size.
7474 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7475 (windows->image.height == (unsigned int) (*image)->rows) &&
7476 (windows->image.crop_geometry == (char *) NULL))
7478 (void) XBell(display,0);
7481 windows->image.window_changes.width=(int) (*image)->columns;
7482 windows->image.window_changes.height=(int) (*image)->rows;
7483 if (windows->image.crop_geometry != (char *) NULL)
7485 windows->image.crop_geometry=(char *)
7486 RelinquishMagickMemory(windows->image.crop_geometry);
7487 windows->image.crop_geometry=(char *) NULL;
7491 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7492 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7500 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7509 status=XChopImage(display,resource_info,windows,image,exception);
7510 if (status == MagickFalse)
7512 XNoticeWidget(display,windows,"Unable to cut X image",
7513 (*image)->filename);
7524 Flop image scanlines.
7526 XSetCursorState(display,windows,MagickTrue);
7527 XCheckRefreshWindows(display,windows);
7528 flop_image=FlopImage(*image,exception);
7529 if (flop_image != (Image *) NULL)
7531 *image=DestroyImage(*image);
7534 CatchException(exception);
7535 XSetCursorState(display,windows,MagickFalse);
7536 if (windows->image.crop_geometry != (char *) NULL)
7541 width=(unsigned int) (*image)->columns;
7542 height=(unsigned int) (*image)->rows;
7543 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7545 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7546 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7548 if (windows->image.orphan != MagickFalse)
7550 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7559 Flip image scanlines.
7561 XSetCursorState(display,windows,MagickTrue);
7562 XCheckRefreshWindows(display,windows);
7563 flip_image=FlipImage(*image,exception);
7564 if (flip_image != (Image *) NULL)
7566 *image=DestroyImage(*image);
7569 CatchException(exception);
7570 XSetCursorState(display,windows,MagickFalse);
7571 if (windows->image.crop_geometry != (char *) NULL)
7576 width=(unsigned int) (*image)->columns;
7577 height=(unsigned int) (*image)->rows;
7578 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7580 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7581 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7583 if (windows->image.orphan != MagickFalse)
7585 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7588 case RotateRightCommand:
7591 Rotate image 90 degrees clockwise.
7593 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7594 if (status == MagickFalse)
7596 XNoticeWidget(display,windows,"Unable to rotate X image",
7597 (*image)->filename);
7602 case RotateLeftCommand:
7605 Rotate image 90 degrees counter-clockwise.
7607 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7608 if (status == MagickFalse)
7610 XNoticeWidget(display,windows,"Unable to rotate X image",
7611 (*image)->filename);
7621 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7622 if (status == MagickFalse)
7624 XNoticeWidget(display,windows,"Unable to rotate X image",
7625 (*image)->filename);
7636 geometry[MaxTextExtent] = "45.0x45.0";
7639 Query user for shear color and geometry.
7641 XColorBrowserWidget(display,windows,"Select",color);
7644 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7646 if (*geometry == '\0')
7651 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7653 XSetCursorState(display,windows,MagickTrue);
7654 XCheckRefreshWindows(display,windows);
7655 (void) QueryColorCompliance(color,AllCompliance,
7656 &(*image)->background_color,exception);
7657 flags=ParseGeometry(geometry,&geometry_info);
7658 if ((flags & SigmaValue) == 0)
7659 geometry_info.sigma=geometry_info.rho;
7660 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7662 if (shear_image != (Image *) NULL)
7664 *image=DestroyImage(*image);
7667 CatchException(exception);
7668 XSetCursorState(display,windows,MagickFalse);
7669 if (windows->image.orphan != MagickFalse)
7671 windows->image.window_changes.width=(int) (*image)->columns;
7672 windows->image.window_changes.height=(int) (*image)->rows;
7673 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7674 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7683 geometry[MaxTextExtent] = "+2+2";
7686 Query user for the roll geometry.
7688 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7690 if (*geometry == '\0')
7695 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7697 XSetCursorState(display,windows,MagickTrue);
7698 XCheckRefreshWindows(display,windows);
7699 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7701 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7703 if (roll_image != (Image *) NULL)
7705 *image=DestroyImage(*image);
7708 CatchException(exception);
7709 XSetCursorState(display,windows,MagickFalse);
7710 if (windows->image.orphan != MagickFalse)
7712 windows->image.window_changes.width=(int) (*image)->columns;
7713 windows->image.window_changes.height=(int) (*image)->rows;
7714 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7715 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7721 fuzz[MaxTextExtent];
7724 Query user for the fuzz factor.
7726 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7727 (*image)->fuzz/(QuantumRange+1.0));
7728 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7731 (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0);
7735 status=XTrimImage(display,resource_info,windows,*image,exception);
7736 if (status == MagickFalse)
7738 XNoticeWidget(display,windows,"Unable to trim X image",
7739 (*image)->filename);
7747 hue_percent[MaxTextExtent] = "110";
7750 Query user for percent hue change.
7752 (void) XDialogWidget(display,windows,"Apply",
7753 "Enter percent change in image hue (0-200):",hue_percent);
7754 if (*hue_percent == '\0')
7759 XSetCursorState(display,windows,MagickTrue);
7760 XCheckRefreshWindows(display,windows);
7761 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7762 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7764 (void) ModulateImage(*image,modulate_factors,exception);
7765 XSetCursorState(display,windows,MagickFalse);
7766 if (windows->image.orphan != MagickFalse)
7768 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7769 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7772 case SaturationCommand:
7775 saturation_percent[MaxTextExtent] = "110";
7778 Query user for percent saturation change.
7780 (void) XDialogWidget(display,windows,"Apply",
7781 "Enter percent change in color saturation (0-200):",saturation_percent);
7782 if (*saturation_percent == '\0')
7785 Vary color saturation.
7787 XSetCursorState(display,windows,MagickTrue);
7788 XCheckRefreshWindows(display,windows);
7789 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7790 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7792 (void) ModulateImage(*image,modulate_factors,exception);
7793 XSetCursorState(display,windows,MagickFalse);
7794 if (windows->image.orphan != MagickFalse)
7796 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7797 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7800 case BrightnessCommand:
7803 brightness_percent[MaxTextExtent] = "110";
7806 Query user for percent brightness change.
7808 (void) XDialogWidget(display,windows,"Apply",
7809 "Enter percent change in color brightness (0-200):",brightness_percent);
7810 if (*brightness_percent == '\0')
7813 Vary the color brightness.
7815 XSetCursorState(display,windows,MagickTrue);
7816 XCheckRefreshWindows(display,windows);
7817 (void) CopyMagickString(modulate_factors,brightness_percent,
7819 (void) ModulateImage(*image,modulate_factors,exception);
7820 XSetCursorState(display,windows,MagickFalse);
7821 if (windows->image.orphan != MagickFalse)
7823 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7824 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7830 factor[MaxTextExtent] = "1.6";
7833 Query user for gamma value.
7835 (void) XDialogWidget(display,windows,"Gamma",
7836 "Enter gamma value (e.g. 1.2):",factor);
7837 if (*factor == '\0')
7840 Gamma correct image.
7842 XSetCursorState(display,windows,MagickTrue);
7843 XCheckRefreshWindows(display,windows);
7844 (void) GammaImage(*image,atof(factor),exception);
7845 XSetCursorState(display,windows,MagickFalse);
7846 if (windows->image.orphan != MagickFalse)
7848 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7849 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7855 Sharpen the image contrast.
7857 XSetCursorState(display,windows,MagickTrue);
7858 XCheckRefreshWindows(display,windows);
7859 (void) ContrastImage(*image,MagickTrue,exception);
7860 XSetCursorState(display,windows,MagickFalse);
7861 if (windows->image.orphan != MagickFalse)
7863 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7864 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7870 Dull the image contrast.
7872 XSetCursorState(display,windows,MagickTrue);
7873 XCheckRefreshWindows(display,windows);
7874 (void) ContrastImage(*image,MagickFalse,exception);
7875 XSetCursorState(display,windows,MagickFalse);
7876 if (windows->image.orphan != MagickFalse)
7878 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7879 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7882 case ContrastStretchCommand:
7889 levels[MaxTextExtent] = "1%";
7892 Query user for gamma value.
7894 (void) XDialogWidget(display,windows,"Contrast Stretch",
7895 "Enter black and white points:",levels);
7896 if (*levels == '\0')
7899 Contrast stretch image.
7901 XSetCursorState(display,windows,MagickTrue);
7902 XCheckRefreshWindows(display,windows);
7903 flags=ParseGeometry(levels,&geometry_info);
7904 black_point=geometry_info.rho;
7905 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7906 if ((flags & PercentValue) != 0)
7908 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7909 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7911 white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point;
7912 (void) ContrastStretchImage(*image,black_point,white_point,
7914 XSetCursorState(display,windows,MagickFalse);
7915 if (windows->image.orphan != MagickFalse)
7917 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7918 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7921 case SigmoidalContrastCommand:
7930 levels[MaxTextExtent] = "3x50%";
7933 Query user for gamma value.
7935 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7936 "Enter contrast and midpoint:",levels);
7937 if (*levels == '\0')
7940 Contrast stretch image.
7942 XSetCursorState(display,windows,MagickTrue);
7943 XCheckRefreshWindows(display,windows);
7944 flags=ParseGeometry(levels,&geometry_info);
7945 if ((flags & SigmaValue) == 0)
7946 geometry_info.sigma=1.0*QuantumRange/2.0;
7947 if ((flags & PercentValue) != 0)
7948 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7949 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7950 geometry_info.sigma,exception);
7951 XSetCursorState(display,windows,MagickFalse);
7952 if (windows->image.orphan != MagickFalse)
7954 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7955 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7958 case NormalizeCommand:
7961 Perform histogram normalization on the image.
7963 XSetCursorState(display,windows,MagickTrue);
7964 XCheckRefreshWindows(display,windows);
7965 (void) NormalizeImage(*image,exception);
7966 XSetCursorState(display,windows,MagickFalse);
7967 if (windows->image.orphan != MagickFalse)
7969 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7970 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7973 case EqualizeCommand:
7976 Perform histogram equalization on the image.
7978 XSetCursorState(display,windows,MagickTrue);
7979 XCheckRefreshWindows(display,windows);
7980 (void) EqualizeImage(*image,exception);
7981 XSetCursorState(display,windows,MagickFalse);
7982 if (windows->image.orphan != MagickFalse)
7984 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7985 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7991 Negate colors in image.
7993 XSetCursorState(display,windows,MagickTrue);
7994 XCheckRefreshWindows(display,windows);
7995 (void) NegateImage(*image,MagickFalse,exception);
7996 XSetCursorState(display,windows,MagickFalse);
7997 if (windows->image.orphan != MagickFalse)
7999 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8000 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8003 case GrayscaleCommand:
8006 Convert image to grayscale.
8008 XSetCursorState(display,windows,MagickTrue);
8009 XCheckRefreshWindows(display,windows);
8010 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
8011 GrayscaleType : GrayscaleMatteType,exception);
8012 XSetCursorState(display,windows,MagickFalse);
8013 if (windows->image.orphan != MagickFalse)
8015 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8016 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8025 filename[MaxTextExtent] = "\0";
8028 Request image file name from user.
8030 XFileBrowserWidget(display,windows,"Map",filename);
8031 if (*filename == '\0')
8036 XSetCursorState(display,windows,MagickTrue);
8037 XCheckRefreshWindows(display,windows);
8038 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8039 affinity_image=ReadImage(image_info,exception);
8040 if (affinity_image != (Image *) NULL)
8042 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8043 affinity_image=DestroyImage(affinity_image);
8045 CatchException(exception);
8046 XSetCursorState(display,windows,MagickFalse);
8047 if (windows->image.orphan != MagickFalse)
8049 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8050 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8053 case QuantizeCommand:
8059 colors[MaxTextExtent] = "256";
8062 Query user for maximum number of colors.
8064 status=XDialogWidget(display,windows,"Quantize",
8065 "Maximum number of colors:",colors);
8066 if (*colors == '\0')
8069 Color reduce the image.
8071 XSetCursorState(display,windows,MagickTrue);
8072 XCheckRefreshWindows(display,windows);
8073 quantize_info.number_colors=StringToUnsignedLong(colors);
8074 quantize_info.dither=status != 0 ? MagickTrue : MagickFalse;
8075 (void) QuantizeImage(&quantize_info,*image,exception);
8076 XSetCursorState(display,windows,MagickFalse);
8077 if (windows->image.orphan != MagickFalse)
8079 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8080 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8083 case DespeckleCommand:
8091 XSetCursorState(display,windows,MagickTrue);
8092 XCheckRefreshWindows(display,windows);
8093 despeckle_image=DespeckleImage(*image,exception);
8094 if (despeckle_image != (Image *) NULL)
8096 *image=DestroyImage(*image);
8097 *image=despeckle_image;
8099 CatchException(exception);
8100 XSetCursorState(display,windows,MagickFalse);
8101 if (windows->image.orphan != MagickFalse)
8103 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8104 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8113 radius[MaxTextExtent] = "0.0x1.0";
8116 Query user for emboss radius.
8118 (void) XDialogWidget(display,windows,"Emboss",
8119 "Enter the emboss radius and standard deviation:",radius);
8120 if (*radius == '\0')
8123 Reduce noise in the image.
8125 XSetCursorState(display,windows,MagickTrue);
8126 XCheckRefreshWindows(display,windows);
8127 flags=ParseGeometry(radius,&geometry_info);
8128 if ((flags & SigmaValue) == 0)
8129 geometry_info.sigma=1.0;
8130 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8132 if (emboss_image != (Image *) NULL)
8134 *image=DestroyImage(*image);
8135 *image=emboss_image;
8137 CatchException(exception);
8138 XSetCursorState(display,windows,MagickFalse);
8139 if (windows->image.orphan != MagickFalse)
8141 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8142 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8145 case ReduceNoiseCommand:
8151 radius[MaxTextExtent] = "0";
8154 Query user for noise radius.
8156 (void) XDialogWidget(display,windows,"Reduce Noise",
8157 "Enter the noise radius:",radius);
8158 if (*radius == '\0')
8161 Reduce noise in the image.
8163 XSetCursorState(display,windows,MagickTrue);
8164 XCheckRefreshWindows(display,windows);
8165 flags=ParseGeometry(radius,&geometry_info);
8166 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8167 geometry_info.rho,(size_t) geometry_info.rho,exception);
8168 if (noise_image != (Image *) NULL)
8170 *image=DestroyImage(*image);
8173 CatchException(exception);
8174 XSetCursorState(display,windows,MagickFalse);
8175 if (windows->image.orphan != MagickFalse)
8177 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8178 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8181 case AddNoiseCommand:
8190 noise_type[MaxTextExtent] = "Gaussian";
8193 Add noise to the image.
8195 noises=GetCommandOptions(MagickNoiseOptions);
8196 if (noises == (char **) NULL)
8198 XListBrowserWidget(display,windows,&windows->widget,
8199 (const char **) noises,"Add Noise",
8200 "Select a type of noise to add to your image:",noise_type);
8201 noises=DestroyStringList(noises);
8202 if (*noise_type == '\0')
8204 XSetCursorState(display,windows,MagickTrue);
8205 XCheckRefreshWindows(display,windows);
8206 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8207 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8208 if (noise_image != (Image *) NULL)
8210 *image=DestroyImage(*image);
8213 CatchException(exception);
8214 XSetCursorState(display,windows,MagickFalse);
8215 if (windows->image.orphan != MagickFalse)
8217 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8218 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8221 case SharpenCommand:
8227 radius[MaxTextExtent] = "0.0x1.0";
8230 Query user for sharpen radius.
8232 (void) XDialogWidget(display,windows,"Sharpen",
8233 "Enter the sharpen radius and standard deviation:",radius);
8234 if (*radius == '\0')
8237 Sharpen image scanlines.
8239 XSetCursorState(display,windows,MagickTrue);
8240 XCheckRefreshWindows(display,windows);
8241 flags=ParseGeometry(radius,&geometry_info);
8242 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8243 geometry_info.xi,exception);
8244 if (sharp_image != (Image *) NULL)
8246 *image=DestroyImage(*image);
8249 CatchException(exception);
8250 XSetCursorState(display,windows,MagickFalse);
8251 if (windows->image.orphan != MagickFalse)
8253 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8254 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8263 radius[MaxTextExtent] = "0.0x1.0";
8266 Query user for blur radius.
8268 (void) XDialogWidget(display,windows,"Blur",
8269 "Enter the blur radius and standard deviation:",radius);
8270 if (*radius == '\0')
8275 XSetCursorState(display,windows,MagickTrue);
8276 XCheckRefreshWindows(display,windows);
8277 flags=ParseGeometry(radius,&geometry_info);
8278 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8279 geometry_info.xi,exception);
8280 if (blur_image != (Image *) NULL)
8282 *image=DestroyImage(*image);
8285 CatchException(exception);
8286 XSetCursorState(display,windows,MagickFalse);
8287 if (windows->image.orphan != MagickFalse)
8289 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8290 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8293 case ThresholdCommand:
8299 factor[MaxTextExtent] = "128";
8302 Query user for threshold value.
8304 (void) XDialogWidget(display,windows,"Threshold",
8305 "Enter threshold value:",factor);
8306 if (*factor == '\0')
8309 Gamma correct image.
8311 XSetCursorState(display,windows,MagickTrue);
8312 XCheckRefreshWindows(display,windows);
8313 threshold=SiPrefixToDouble(factor,QuantumRange);
8314 (void) BilevelImage(*image,threshold,exception);
8315 XSetCursorState(display,windows,MagickFalse);
8316 if (windows->image.orphan != MagickFalse)
8318 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8319 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8322 case EdgeDetectCommand:
8328 radius[MaxTextExtent] = "0";
8331 Query user for edge factor.
8333 (void) XDialogWidget(display,windows,"Detect Edges",
8334 "Enter the edge detect radius:",radius);
8335 if (*radius == '\0')
8338 Detect edge in image.
8340 XSetCursorState(display,windows,MagickTrue);
8341 XCheckRefreshWindows(display,windows);
8342 flags=ParseGeometry(radius,&geometry_info);
8343 edge_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8345 if (edge_image != (Image *) NULL)
8347 *image=DestroyImage(*image);
8350 CatchException(exception);
8351 XSetCursorState(display,windows,MagickFalse);
8352 if (windows->image.orphan != MagickFalse)
8354 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8355 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8364 amount[MaxTextExtent] = "2";
8367 Query user for spread amount.
8369 (void) XDialogWidget(display,windows,"Spread",
8370 "Enter the displacement amount:",amount);
8371 if (*amount == '\0')
8374 Displace image pixels by a random amount.
8376 XSetCursorState(display,windows,MagickTrue);
8377 XCheckRefreshWindows(display,windows);
8378 flags=ParseGeometry(amount,&geometry_info);
8379 spread_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8381 if (spread_image != (Image *) NULL)
8383 *image=DestroyImage(*image);
8384 *image=spread_image;
8386 CatchException(exception);
8387 XSetCursorState(display,windows,MagickFalse);
8388 if (windows->image.orphan != MagickFalse)
8390 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8391 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8403 geometry[MaxTextExtent] = "30x30";
8406 Query user for the shade geometry.
8408 status=XDialogWidget(display,windows,"Shade",
8409 "Enter the azimuth and elevation of the light source:",geometry);
8410 if (*geometry == '\0')
8415 XSetCursorState(display,windows,MagickTrue);
8416 XCheckRefreshWindows(display,windows);
8417 flags=ParseGeometry(geometry,&geometry_info);
8418 if ((flags & SigmaValue) == 0)
8419 geometry_info.sigma=1.0;
8420 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
8421 geometry_info.rho,geometry_info.sigma,exception);
8422 if (shade_image != (Image *) NULL)
8424 *image=DestroyImage(*image);
8427 CatchException(exception);
8428 XSetCursorState(display,windows,MagickFalse);
8429 if (windows->image.orphan != MagickFalse)
8431 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8432 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8438 bevel_width[MaxTextExtent] = "10";
8441 Query user for bevel width.
8443 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8444 if (*bevel_width == '\0')
8449 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8451 XSetCursorState(display,windows,MagickTrue);
8452 XCheckRefreshWindows(display,windows);
8453 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8455 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8456 XSetCursorState(display,windows,MagickFalse);
8457 if (windows->image.orphan != MagickFalse)
8459 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8460 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8463 case SegmentCommand:
8466 threshold[MaxTextExtent] = "1.0x1.5";
8469 Query user for smoothing threshold.
8471 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8473 if (*threshold == '\0')
8478 XSetCursorState(display,windows,MagickTrue);
8479 XCheckRefreshWindows(display,windows);
8480 flags=ParseGeometry(threshold,&geometry_info);
8481 if ((flags & SigmaValue) == 0)
8482 geometry_info.sigma=1.0;
8483 (void) SegmentImage(*image,RGBColorspace,MagickFalse,geometry_info.rho,
8484 geometry_info.sigma,exception);
8485 XSetCursorState(display,windows,MagickFalse);
8486 if (windows->image.orphan != MagickFalse)
8488 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8489 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8492 case SepiaToneCommand:
8501 factor[MaxTextExtent] = "80%";
8504 Query user for sepia-tone factor.
8506 (void) XDialogWidget(display,windows,"Sepia Tone",
8507 "Enter the sepia tone factor (0 - 99.9%):",factor);
8508 if (*factor == '\0')
8511 Sepia tone image pixels.
8513 XSetCursorState(display,windows,MagickTrue);
8514 XCheckRefreshWindows(display,windows);
8515 threshold=SiPrefixToDouble(factor,QuantumRange);
8516 sepia_image=SepiaToneImage(*image,threshold,exception);
8517 if (sepia_image != (Image *) NULL)
8519 *image=DestroyImage(*image);
8522 CatchException(exception);
8523 XSetCursorState(display,windows,MagickFalse);
8524 if (windows->image.orphan != MagickFalse)
8526 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8527 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8530 case SolarizeCommand:
8536 factor[MaxTextExtent] = "60%";
8539 Query user for solarize factor.
8541 (void) XDialogWidget(display,windows,"Solarize",
8542 "Enter the solarize factor (0 - 99.9%):",factor);
8543 if (*factor == '\0')
8546 Solarize image pixels.
8548 XSetCursorState(display,windows,MagickTrue);
8549 XCheckRefreshWindows(display,windows);
8550 threshold=SiPrefixToDouble(factor,QuantumRange);
8551 (void) SolarizeImage(*image,threshold,exception);
8552 XSetCursorState(display,windows,MagickFalse);
8553 if (windows->image.orphan != MagickFalse)
8555 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8556 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8565 degrees[MaxTextExtent] = "60";
8568 Query user for swirl angle.
8570 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8572 if (*degrees == '\0')
8575 Swirl image pixels about the center.
8577 XSetCursorState(display,windows,MagickTrue);
8578 XCheckRefreshWindows(display,windows);
8579 flags=ParseGeometry(degrees,&geometry_info);
8580 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8582 if (swirl_image != (Image *) NULL)
8584 *image=DestroyImage(*image);
8587 CatchException(exception);
8588 XSetCursorState(display,windows,MagickFalse);
8589 if (windows->image.orphan != MagickFalse)
8591 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8592 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8595 case ImplodeCommand:
8601 factor[MaxTextExtent] = "0.3";
8604 Query user for implode factor.
8606 (void) XDialogWidget(display,windows,"Implode",
8607 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8608 if (*factor == '\0')
8611 Implode image pixels about the center.
8613 XSetCursorState(display,windows,MagickTrue);
8614 XCheckRefreshWindows(display,windows);
8615 flags=ParseGeometry(factor,&geometry_info);
8616 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8618 if (implode_image != (Image *) NULL)
8620 *image=DestroyImage(*image);
8621 *image=implode_image;
8623 CatchException(exception);
8624 XSetCursorState(display,windows,MagickFalse);
8625 if (windows->image.orphan != MagickFalse)
8627 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8628 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8631 case VignetteCommand:
8637 geometry[MaxTextExtent] = "0x20";
8640 Query user for the vignette geometry.
8642 (void) XDialogWidget(display,windows,"Vignette",
8643 "Enter the radius, sigma, and x and y offsets:",geometry);
8644 if (*geometry == '\0')
8647 Soften the edges of the image in vignette style
8649 XSetCursorState(display,windows,MagickTrue);
8650 XCheckRefreshWindows(display,windows);
8651 flags=ParseGeometry(geometry,&geometry_info);
8652 if ((flags & SigmaValue) == 0)
8653 geometry_info.sigma=1.0;
8654 if ((flags & XiValue) == 0)
8655 geometry_info.xi=0.1*(*image)->columns;
8656 if ((flags & PsiValue) == 0)
8657 geometry_info.psi=0.1*(*image)->rows;
8658 vignette_image=VignetteImage(*image,geometry_info.rho,geometry_info.sigma,
8659 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
8661 if (vignette_image != (Image *) NULL)
8663 *image=DestroyImage(*image);
8664 *image=vignette_image;
8666 CatchException(exception);
8667 XSetCursorState(display,windows,MagickFalse);
8668 if (windows->image.orphan != MagickFalse)
8670 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8671 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8680 geometry[MaxTextExtent] = "25x150";
8683 Query user for the wave geometry.
8685 (void) XDialogWidget(display,windows,"Wave",
8686 "Enter the amplitude and length of the wave:",geometry);
8687 if (*geometry == '\0')
8690 Alter an image along a sine wave.
8692 XSetCursorState(display,windows,MagickTrue);
8693 XCheckRefreshWindows(display,windows);
8694 flags=ParseGeometry(geometry,&geometry_info);
8695 if ((flags & SigmaValue) == 0)
8696 geometry_info.sigma=1.0;
8697 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8698 (*image)->interpolate,exception);
8699 if (wave_image != (Image *) NULL)
8701 *image=DestroyImage(*image);
8704 CatchException(exception);
8705 XSetCursorState(display,windows,MagickFalse);
8706 if (windows->image.orphan != MagickFalse)
8708 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8709 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8712 case OilPaintCommand:
8718 radius[MaxTextExtent] = "0";
8721 Query user for circular neighborhood radius.
8723 (void) XDialogWidget(display,windows,"Oil Paint",
8724 "Enter the mask radius:",radius);
8725 if (*radius == '\0')
8728 OilPaint image scanlines.
8730 XSetCursorState(display,windows,MagickTrue);
8731 XCheckRefreshWindows(display,windows);
8732 flags=ParseGeometry(radius,&geometry_info);
8733 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8735 if (paint_image != (Image *) NULL)
8737 *image=DestroyImage(*image);
8740 CatchException(exception);
8741 XSetCursorState(display,windows,MagickFalse);
8742 if (windows->image.orphan != MagickFalse)
8744 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8745 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8748 case CharcoalDrawCommand:
8754 radius[MaxTextExtent] = "0x1";
8757 Query user for charcoal radius.
8759 (void) XDialogWidget(display,windows,"Charcoal Draw",
8760 "Enter the charcoal radius and sigma:",radius);
8761 if (*radius == '\0')
8766 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8768 XSetCursorState(display,windows,MagickTrue);
8769 XCheckRefreshWindows(display,windows);
8770 flags=ParseGeometry(radius,&geometry_info);
8771 if ((flags & SigmaValue) == 0)
8772 geometry_info.sigma=geometry_info.rho;
8773 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8774 geometry_info.xi,exception);
8775 if (charcoal_image != (Image *) NULL)
8777 *image=DestroyImage(*image);
8778 *image=charcoal_image;
8780 CatchException(exception);
8781 XSetCursorState(display,windows,MagickFalse);
8782 if (windows->image.orphan != MagickFalse)
8784 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8785 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8788 case AnnotateCommand:
8791 Annotate the image with text.
8793 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8794 if (status == MagickFalse)
8796 XNoticeWidget(display,windows,"Unable to annotate X image",
8797 (*image)->filename);
8807 status=XDrawEditImage(display,resource_info,windows,image,exception);
8808 if (status == MagickFalse)
8810 XNoticeWidget(display,windows,"Unable to draw on the X image",
8811 (*image)->filename);
8821 status=XColorEditImage(display,resource_info,windows,image,exception);
8822 if (status == MagickFalse)
8824 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8825 (*image)->filename);
8835 status=XMatteEditImage(display,resource_info,windows,image,exception);
8836 if (status == MagickFalse)
8838 XNoticeWidget(display,windows,"Unable to matte edit X image",
8839 (*image)->filename);
8844 case CompositeCommand:
8849 status=XCompositeImage(display,resource_info,windows,*image,
8851 if (status == MagickFalse)
8853 XNoticeWidget(display,windows,"Unable to composite X image",
8854 (*image)->filename);
8859 case AddBorderCommand:
8865 geometry[MaxTextExtent] = "6x6";
8868 Query user for border color and geometry.
8870 XColorBrowserWidget(display,windows,"Select",color);
8873 (void) XDialogWidget(display,windows,"Add Border",
8874 "Enter border geometry:",geometry);
8875 if (*geometry == '\0')
8878 Add a border to the image.
8880 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8882 XSetCursorState(display,windows,MagickTrue);
8883 XCheckRefreshWindows(display,windows);
8884 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8886 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8888 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8890 if (border_image != (Image *) NULL)
8892 *image=DestroyImage(*image);
8893 *image=border_image;
8895 CatchException(exception);
8896 XSetCursorState(display,windows,MagickFalse);
8897 if (windows->image.orphan != MagickFalse)
8899 windows->image.window_changes.width=(int) (*image)->columns;
8900 windows->image.window_changes.height=(int) (*image)->rows;
8901 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8902 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8905 case AddFrameCommand:
8914 geometry[MaxTextExtent] = "6x6";
8917 Query user for frame color and geometry.
8919 XColorBrowserWidget(display,windows,"Select",color);
8922 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8924 if (*geometry == '\0')
8927 Surround image with an ornamental border.
8929 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8931 XSetCursorState(display,windows,MagickTrue);
8932 XCheckRefreshWindows(display,windows);
8933 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8935 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8937 frame_info.width=page_geometry.width;
8938 frame_info.height=page_geometry.height;
8939 frame_info.outer_bevel=page_geometry.x;
8940 frame_info.inner_bevel=page_geometry.y;
8941 frame_info.x=(ssize_t) frame_info.width;
8942 frame_info.y=(ssize_t) frame_info.height;
8943 frame_info.width=(*image)->columns+2*frame_info.width;
8944 frame_info.height=(*image)->rows+2*frame_info.height;
8945 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8946 if (frame_image != (Image *) NULL)
8948 *image=DestroyImage(*image);
8951 CatchException(exception);
8952 XSetCursorState(display,windows,MagickFalse);
8953 if (windows->image.orphan != MagickFalse)
8955 windows->image.window_changes.width=(int) (*image)->columns;
8956 windows->image.window_changes.height=(int) (*image)->rows;
8957 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8958 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8961 case CommentCommand:
8975 unique_file=AcquireUniqueFileResource(image_info->filename);
8976 if (unique_file == -1)
8977 XNoticeWidget(display,windows,"Unable to edit image comment",
8978 image_info->filename);
8979 value=GetImageProperty(*image,"comment",exception);
8980 if (value == (char *) NULL)
8981 unique_file=close(unique_file)-1;
8987 file=fdopen(unique_file,"w");
8988 if (file == (FILE *) NULL)
8990 XNoticeWidget(display,windows,"Unable to edit image comment",
8991 image_info->filename);
8994 for (p=value; *p != '\0'; p++)
8995 (void) fputc((int) *p,file);
8996 (void) fputc('\n',file);
8997 (void) fclose(file);
8999 XSetCursorState(display,windows,MagickTrue);
9000 XCheckRefreshWindows(display,windows);
9001 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
9003 if (status == MagickFalse)
9004 XNoticeWidget(display,windows,"Unable to edit image comment",
9011 comment=FileToString(image_info->filename,~0UL,exception);
9012 if (comment != (char *) NULL)
9014 (void) SetImageProperty(*image,"comment",comment,exception);
9015 (*image)->taint=MagickTrue;
9018 (void) RelinquishUniqueFileResource(image_info->filename);
9019 XSetCursorState(display,windows,MagickFalse);
9027 XSetCursorState(display,windows,MagickTrue);
9028 XCheckRefreshWindows(display,windows);
9029 (void) AcquireUniqueFilename(filename);
9030 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9032 status=WriteImage(image_info,*image,exception);
9033 if (status == MagickFalse)
9034 XNoticeWidget(display,windows,"Unable to launch image editor",
9038 nexus=ReadImage(resource_info->image_info,exception);
9039 CatchException(exception);
9040 XClientMessage(display,windows->image.id,windows->im_protocols,
9041 windows->im_next_image,CurrentTime);
9043 (void) RelinquishUniqueFileResource(filename);
9044 XSetCursorState(display,windows,MagickFalse);
9047 case RegionofInterestCommand:
9050 Apply an image processing technique to a region of interest.
9052 (void) XROIImage(display,resource_info,windows,image,exception);
9062 if (windows->magnify.mapped != MagickFalse)
9063 (void) XRaiseWindow(display,windows->magnify.id);
9069 XSetCursorState(display,windows,MagickTrue);
9070 (void) XMapRaised(display,windows->magnify.id);
9071 XSetCursorState(display,windows,MagickFalse);
9075 case ShowPreviewCommand:
9084 preview_type[MaxTextExtent] = "Gamma";
9087 Select preview type from menu.
9089 previews=GetCommandOptions(MagickPreviewOptions);
9090 if (previews == (char **) NULL)
9092 XListBrowserWidget(display,windows,&windows->widget,
9093 (const char **) previews,"Preview",
9094 "Select an enhancement, effect, or F/X:",preview_type);
9095 previews=DestroyStringList(previews);
9096 if (*preview_type == '\0')
9101 XSetCursorState(display,windows,MagickTrue);
9102 XCheckRefreshWindows(display,windows);
9103 image_info->preview_type=(PreviewType)
9104 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9105 image_info->group=(ssize_t) windows->image.id;
9106 (void) DeleteImageProperty(*image,"label");
9107 (void) SetImageProperty(*image,"label","Preview",exception);
9108 (void) AcquireUniqueFilename(filename);
9109 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9111 status=WriteImage(image_info,*image,exception);
9112 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9113 preview_image=ReadImage(image_info,exception);
9114 (void) RelinquishUniqueFileResource(filename);
9115 if (preview_image == (Image *) NULL)
9117 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9119 status=WriteImage(image_info,preview_image,exception);
9120 preview_image=DestroyImage(preview_image);
9121 if (status == MagickFalse)
9122 XNoticeWidget(display,windows,"Unable to show image preview",
9123 (*image)->filename);
9124 XDelay(display,1500);
9125 XSetCursorState(display,windows,MagickFalse);
9128 case ShowHistogramCommand:
9134 Show image histogram.
9136 XSetCursorState(display,windows,MagickTrue);
9137 XCheckRefreshWindows(display,windows);
9138 image_info->group=(ssize_t) windows->image.id;
9139 (void) DeleteImageProperty(*image,"label");
9140 (void) SetImageProperty(*image,"label","Histogram",exception);
9141 (void) AcquireUniqueFilename(filename);
9142 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9144 status=WriteImage(image_info,*image,exception);
9145 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9146 histogram_image=ReadImage(image_info,exception);
9147 (void) RelinquishUniqueFileResource(filename);
9148 if (histogram_image == (Image *) NULL)
9150 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9151 "show:%s",filename);
9152 status=WriteImage(image_info,histogram_image,exception);
9153 histogram_image=DestroyImage(histogram_image);
9154 if (status == MagickFalse)
9155 XNoticeWidget(display,windows,"Unable to show histogram",
9156 (*image)->filename);
9157 XDelay(display,1500);
9158 XSetCursorState(display,windows,MagickFalse);
9161 case ShowMatteCommand:
9166 if ((*image)->matte == MagickFalse)
9168 XNoticeWidget(display,windows,
9169 "Image does not have any matte information",(*image)->filename);
9175 XSetCursorState(display,windows,MagickTrue);
9176 XCheckRefreshWindows(display,windows);
9177 image_info->group=(ssize_t) windows->image.id;
9178 (void) DeleteImageProperty(*image,"label");
9179 (void) SetImageProperty(*image,"label","Matte",exception);
9180 (void) AcquireUniqueFilename(filename);
9181 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9183 status=WriteImage(image_info,*image,exception);
9184 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9185 matte_image=ReadImage(image_info,exception);
9186 (void) RelinquishUniqueFileResource(filename);
9187 if (matte_image == (Image *) NULL)
9189 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9191 status=WriteImage(image_info,matte_image,exception);
9192 matte_image=DestroyImage(matte_image);
9193 if (status == MagickFalse)
9194 XNoticeWidget(display,windows,"Unable to show matte",
9195 (*image)->filename);
9196 XDelay(display,1500);
9197 XSetCursorState(display,windows,MagickFalse);
9200 case BackgroundCommand:
9205 status=XBackgroundImage(display,resource_info,windows,image,exception);
9206 if (status == MagickFalse)
9208 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9209 if (nexus != (Image *) NULL)
9210 XClientMessage(display,windows->image.id,windows->im_protocols,
9211 windows->im_next_image,CurrentTime);
9214 case SlideShowCommand:
9217 delay[MaxTextExtent] = "5";
9220 Display next image after pausing.
9222 (void) XDialogWidget(display,windows,"Slide Show",
9223 "Pause how many 1/100ths of a second between images:",delay);
9226 resource_info->delay=StringToUnsignedLong(delay);
9227 XClientMessage(display,windows->image.id,windows->im_protocols,
9228 windows->im_next_image,CurrentTime);
9231 case PreferencesCommand:
9234 Set user preferences.
9236 status=XPreferencesWidget(display,resource_info,windows);
9237 if (status == MagickFalse)
9239 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9240 if (nexus != (Image *) NULL)
9241 XClientMessage(display,windows->image.id,windows->im_protocols,
9242 windows->im_next_image,CurrentTime);
9248 User requested help.
9250 XTextViewWidget(display,resource_info,windows,MagickFalse,
9251 "Help Viewer - Display",DisplayHelp);
9254 case BrowseDocumentationCommand:
9264 Browse the ImageMagick documentation.
9266 root_window=XRootWindow(display,XDefaultScreen(display));
9267 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9268 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9269 if (mozilla_window != (Window) NULL)
9272 command[MaxTextExtent],
9276 Display documentation using Netscape remote control.
9278 url=GetMagickHomeURL();
9279 (void) FormatLocaleString(command,MaxTextExtent,
9280 "openurl(%s,new-tab)",url);
9281 url=DestroyString(url);
9282 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9283 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9284 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9285 XSetCursorState(display,windows,MagickFalse);
9288 XSetCursorState(display,windows,MagickTrue);
9289 XCheckRefreshWindows(display,windows);
9290 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9292 if (status == MagickFalse)
9293 XNoticeWidget(display,windows,"Unable to browse documentation",
9295 XDelay(display,1500);
9296 XSetCursorState(display,windows,MagickFalse);
9299 case VersionCommand:
9301 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9302 GetMagickCopyright());
9305 case SaveToUndoBufferCommand:
9309 (void) XBell(display,0);
9313 image_info=DestroyImageInfo(image_info);
9318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9322 + X M a g n i f y I m a g e %
9326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9328 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9329 % The magnified portion is displayed in a separate window.
9331 % The format of the XMagnifyImage method is:
9333 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9334 % ExceptionInfo *exception)
9336 % A description of each parameter follows:
9338 % o display: Specifies a connection to an X server; returned from
9341 % o windows: Specifies a pointer to a XWindows structure.
9343 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9344 % the entire image is refreshed.
9346 % o exception: return any errors or warnings in this structure.
9349 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9350 ExceptionInfo *exception)
9353 text[MaxTextExtent];
9363 Update magnified image until the mouse button is released.
9365 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9369 windows->magnify.x=(int) windows->image.x+x;
9370 windows->magnify.y=(int) windows->image.y+y;
9374 Map and unmap Info widget as text cursor crosses its boundaries.
9376 if (windows->info.mapped != MagickFalse)
9378 if ((x < (int) (windows->info.x+windows->info.width)) &&
9379 (y < (int) (windows->info.y+windows->info.height)))
9380 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9383 if ((x > (int) (windows->info.x+windows->info.width)) ||
9384 (y > (int) (windows->info.y+windows->info.height)))
9385 (void) XMapWindow(display,windows->info.id);
9386 if (windows->info.mapped != MagickFalse)
9389 Display pointer position.
9391 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9392 windows->magnify.x,windows->magnify.y);
9393 XInfoWidget(display,windows,text);
9396 Wait for next event.
9398 XScreenEvent(display,windows,event,exception);
9399 switch (event->type)
9406 User has finished magnifying image.
9425 Check boundary conditions.
9430 if (x >= (int) windows->image.width)
9431 x=(int) windows->image.width-1;
9435 if (y >= (int) windows->image.height)
9436 y=(int) windows->image.height-1;
9437 } while ((state & ExitState) == 0);
9439 Display magnified image.
9441 XSetCursorState(display,windows,MagickFalse);
9445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9449 + X M a g n i f y W i n d o w C o m m a n d %
9453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9455 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9456 % pixel as specified by the key symbol.
9458 % The format of the XMagnifyWindowCommand method is:
9460 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9461 % const MagickStatusType state,const KeySym key_symbol,
9462 % ExceptionInfo *exception)
9464 % A description of each parameter follows:
9466 % o display: Specifies a connection to an X server; returned from
9469 % o windows: Specifies a pointer to a XWindows structure.
9471 % o state: key mask.
9473 % o key_symbol: Specifies a KeySym which indicates which side of the image
9476 % o exception: return any errors or warnings in this structure.
9479 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9480 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9486 User specified a magnify factor or position.
9489 if ((state & Mod1Mask) != 0)
9491 switch ((int) key_symbol)
9495 (void) XWithdrawWindow(display,windows->magnify.id,
9496 windows->magnify.screen);
9502 windows->magnify.x=(int) windows->image.width/2;
9503 windows->magnify.y=(int) windows->image.height/2;
9509 if (windows->magnify.x > 0)
9510 windows->magnify.x-=quantum;
9516 if (windows->magnify.y > 0)
9517 windows->magnify.y-=quantum;
9523 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9524 windows->magnify.x+=quantum;
9530 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9531 windows->magnify.y+=quantum;
9545 windows->magnify.data=(key_symbol-XK_0);
9559 windows->magnify.data=(key_symbol-XK_KP_0);
9565 XMakeMagnifyImage(display,windows,exception);
9569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9573 + X M a k e P a n I m a g e %
9577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9579 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9582 % The format of the XMakePanImage method is:
9584 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9585 % XWindows *windows,Image *image,ExceptionInfo *exception)
9587 % A description of each parameter follows:
9589 % o display: Specifies a connection to an X server; returned from
9592 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9594 % o windows: Specifies a pointer to a XWindows structure.
9596 % o image: the image.
9598 % o exception: return any errors or warnings in this structure.
9601 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9602 XWindows *windows,Image *image,ExceptionInfo *exception)
9608 Create and display image for panning icon.
9610 XSetCursorState(display,windows,MagickTrue);
9611 XCheckRefreshWindows(display,windows);
9612 windows->pan.x=(int) windows->image.x;
9613 windows->pan.y=(int) windows->image.y;
9614 status=XMakeImage(display,resource_info,&windows->pan,image,
9615 windows->pan.width,windows->pan.height,exception);
9616 if (status == MagickFalse)
9617 ThrowXWindowFatalException(ResourceLimitError,
9618 "MemoryAllocationFailed",image->filename);
9619 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9620 windows->pan.pixmap);
9621 (void) XClearWindow(display,windows->pan.id);
9622 XDrawPanRectangle(display,windows);
9623 XSetCursorState(display,windows,MagickFalse);
9627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9631 + X M a t t a E d i t I m a g e %
9635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9637 % XMatteEditImage() allows the user to interactively change the Matte channel
9638 % of an image. If the image is PseudoClass it is promoted to DirectClass
9639 % before the matte information is stored.
9641 % The format of the XMatteEditImage method is:
9643 % MagickBooleanType XMatteEditImage(Display *display,
9644 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9645 % ExceptionInfo *exception)
9647 % A description of each parameter follows:
9649 % o display: Specifies a connection to an X server; returned from
9652 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9654 % o windows: Specifies a pointer to a XWindows structure.
9656 % o image: the image; returned from ReadImage.
9658 % o exception: return any errors or warnings in this structure.
9661 static MagickBooleanType XMatteEditImage(Display *display,
9662 XResourceInfo *resource_info,XWindows *windows,Image **image,
9663 ExceptionInfo *exception)
9666 matte[MaxTextExtent] = "0";
9681 static const ModeType
9682 MatteEditCommands[] =
9685 MatteEditBorderCommand,
9686 MatteEditFuzzCommand,
9687 MatteEditValueCommand,
9688 MatteEditUndoCommand,
9689 MatteEditHelpCommand,
9690 MatteEditDismissCommand
9694 method = PointMethod;
9697 border_color = { 0, 0, 0, 0, 0, 0 };
9700 command[MaxTextExtent],
9701 text[MaxTextExtent];
9733 (void) CloneString(&windows->command.name,"Matte Edit");
9734 windows->command.data=4;
9735 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9736 (void) XMapRaised(display,windows->command.id);
9737 XClientMessage(display,windows->image.id,windows->im_protocols,
9738 windows->im_update_widget,CurrentTime);
9742 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9743 resource_info->background_color,resource_info->foreground_color);
9744 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9746 Track pointer until button 1 is pressed.
9748 XQueryPosition(display,windows->image.id,&x,&y);
9749 (void) XSelectInput(display,windows->image.id,
9750 windows->image.attributes.event_mask | PointerMotionMask);
9754 if (windows->info.mapped != MagickFalse)
9757 Display pointer position.
9759 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9760 x+windows->image.x,y+windows->image.y);
9761 XInfoWidget(display,windows,text);
9764 Wait for next event.
9766 XScreenEvent(display,windows,&event,exception);
9767 if (event.xany.window == windows->command.id)
9770 Select a command from the Command widget.
9772 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9775 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9778 switch (MatteEditCommands[id])
9780 case MatteEditMethod:
9786 Select a method from the pop-up menu.
9788 methods=GetCommandOptions(MagickMethodOptions);
9789 if (methods == (char **) NULL)
9791 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9792 (const char **) methods,command);
9794 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9795 MagickFalse,methods[entry]);
9796 methods=DestroyStringList(methods);
9799 case MatteEditBorderCommand:
9802 *ColorMenu[MaxNumberPens];
9808 Initialize menu selections.
9810 for (i=0; i < (int) (MaxNumberPens-2); i++)
9811 ColorMenu[i]=resource_info->pen_colors[i];
9812 ColorMenu[MaxNumberPens-2]="Browser...";
9813 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9815 Select a pen color from the pop-up menu.
9817 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9818 (const char **) ColorMenu,command);
9821 if (pen_number == (MaxNumberPens-2))
9824 color_name[MaxTextExtent] = "gray";
9827 Select a pen color from a dialog.
9829 resource_info->pen_colors[pen_number]=color_name;
9830 XColorBrowserWidget(display,windows,"Select",color_name);
9831 if (*color_name == '\0')
9837 (void) XParseColor(display,windows->map_info->colormap,
9838 resource_info->pen_colors[pen_number],&border_color);
9841 case MatteEditFuzzCommand:
9844 fuzz[MaxTextExtent];
9859 Select a command from the pop-up menu.
9861 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9867 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],(double)
9871 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9872 (void) XDialogWidget(display,windows,"Ok",
9873 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9876 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9877 (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0);
9880 case MatteEditValueCommand:
9883 message[MaxTextExtent];
9895 Select a command from the pop-up menu.
9897 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9903 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9905 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9906 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9907 (Quantum) TransparentAlpha);
9910 (void) FormatLocaleString(message,MaxTextExtent,
9911 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9913 (void) XDialogWidget(display,windows,"Matte",message,matte);
9918 case MatteEditUndoCommand:
9920 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9924 case MatteEditHelpCommand:
9926 XTextViewWidget(display,resource_info,windows,MagickFalse,
9927 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9930 case MatteEditDismissCommand:
9942 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9949 if (event.xbutton.button != Button1)
9951 if ((event.xbutton.window != windows->image.id) &&
9952 (event.xbutton.window != windows->magnify.id))
9959 (void) XMagickCommand(display,resource_info,windows,
9960 SaveToUndoBufferCommand,image,exception);
9961 state|=UpdateConfigurationState;
9966 if (event.xbutton.button != Button1)
9968 if ((event.xbutton.window != windows->image.id) &&
9969 (event.xbutton.window != windows->magnify.id))
9972 Update colormap information.
9976 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9977 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9978 XInfoWidget(display,windows,text);
9979 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9980 state&=(~UpdateConfigurationState);
9988 command[MaxTextExtent];
9993 if (event.xkey.window == windows->magnify.id)
9998 window=windows->magnify.id;
9999 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
10001 if (event.xkey.window != windows->image.id)
10004 Respond to a user key press.
10006 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10007 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10008 switch ((int) key_symbol)
10022 XTextViewWidget(display,resource_info,windows,MagickFalse,
10023 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10028 (void) XBell(display,0);
10037 Map and unmap Info widget as cursor crosses its boundaries.
10041 if (windows->info.mapped != MagickFalse)
10043 if ((x < (int) (windows->info.x+windows->info.width)) &&
10044 (y < (int) (windows->info.y+windows->info.height)))
10045 (void) XWithdrawWindow(display,windows->info.id,
10046 windows->info.screen);
10049 if ((x > (int) (windows->info.x+windows->info.width)) ||
10050 (y > (int) (windows->info.y+windows->info.height)))
10051 (void) XMapWindow(display,windows->info.id);
10057 if (event.xany.window == windows->magnify.id)
10059 x=windows->magnify.x-windows->image.x;
10060 y=windows->magnify.y-windows->image.y;
10064 if ((state & UpdateConfigurationState) != 0)
10074 Matte edit is relative to image configuration.
10076 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10078 XPutPixel(windows->image.ximage,x_offset,y_offset,
10079 windows->pixel_info->background_color.pixel);
10080 width=(unsigned int) (*image)->columns;
10081 height=(unsigned int) (*image)->rows;
10084 if (windows->image.crop_geometry != (char *) NULL)
10085 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10087 x_offset=(int) (width*(windows->image.x+x_offset)/
10088 windows->image.ximage->width+x);
10089 y_offset=(int) (height*(windows->image.y+y_offset)/
10090 windows->image.ximage->height+y);
10091 if ((x_offset < 0) || (y_offset < 0))
10093 if ((x_offset >= (int) (*image)->columns) ||
10094 (y_offset >= (int) (*image)->rows))
10096 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10097 return(MagickFalse);
10098 (*image)->matte=MagickTrue;
10099 image_view=AcquireCacheView(*image);
10106 Update matte information using point algorithm.
10108 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10109 (ssize_t) y_offset,1,1,exception);
10110 if (q == (Quantum *) NULL)
10112 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10113 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10116 case ReplaceMethod:
10123 virtual_pixel[CompositePixelChannel];
10126 Update matte information using replace algorithm.
10128 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
10129 (ssize_t) y_offset,virtual_pixel,exception);
10130 target.red=virtual_pixel[RedPixelChannel];
10131 target.green=virtual_pixel[GreenPixelChannel];
10132 target.blue=virtual_pixel[BluePixelChannel];
10133 target.alpha=virtual_pixel[AlphaPixelChannel];
10134 for (y=0; y < (int) (*image)->rows; y++)
10136 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10137 (*image)->columns,1,exception);
10138 if (q == (Quantum *) NULL)
10140 for (x=0; x < (int) (*image)->columns; x++)
10142 GetPixelInfoPixel(*image,q,&pixel);
10143 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10144 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10145 q+=GetPixelChannels(*image);
10147 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10152 case FloodfillMethod:
10153 case FillToBorderMethod:
10165 Update matte information using floodfill algorithm.
10167 (void) GetOneVirtualMagickPixel(*image,
10168 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10169 y_offset,&target,exception);
10170 if (method == FillToBorderMethod)
10172 target.red=(MagickRealType) ScaleShortToQuantum(
10174 target.green=(MagickRealType) ScaleShortToQuantum(
10175 border_color.green);
10176 target.blue=(MagickRealType) ScaleShortToQuantum(
10177 border_color.blue);
10179 draw_info=CloneDrawInfo(resource_info->image_info,
10180 (DrawInfo *) NULL);
10181 draw_info->fill.alpha=ClampToQuantum(InterpretLocaleValue(matte,
10183 channel_mask=SetPixelChannelMask(*image,AlphaChannel);
10184 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10185 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
10186 MagickFalse : MagickTrue,exception);
10187 (void) SetPixelChannelMap(*image,channel_mask);
10188 draw_info=DestroyDrawInfo(draw_info);
10194 Update matte information using reset algorithm.
10196 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10197 return(MagickFalse);
10198 for (y=0; y < (int) (*image)->rows; y++)
10200 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10201 (*image)->columns,1,exception);
10202 if (q == (Quantum *) NULL)
10204 for (x=0; x < (int) (*image)->columns; x++)
10206 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10207 q+=GetPixelChannels(*image);
10209 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10212 if (StringToLong(matte) == (long) OpaqueAlpha)
10213 (*image)->matte=MagickFalse;
10217 image_view=DestroyCacheView(image_view);
10218 state&=(~UpdateConfigurationState);
10220 } while ((state & ExitState) == 0);
10221 (void) XSelectInput(display,windows->image.id,
10222 windows->image.attributes.event_mask);
10223 XSetCursorState(display,windows,MagickFalse);
10224 (void) XFreeCursor(display,cursor);
10225 return(MagickTrue);
10229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10233 + X O p e n I m a g e %
10237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10239 % XOpenImage() loads an image from a file.
10241 % The format of the XOpenImage method is:
10243 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10244 % XWindows *windows,const unsigned int command)
10246 % A description of each parameter follows:
10248 % o display: Specifies a connection to an X server; returned from
10251 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10253 % o windows: Specifies a pointer to a XWindows structure.
10255 % o command: A value other than zero indicates that the file is selected
10256 % from the command line argument list.
10259 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10260 XWindows *windows,const MagickBooleanType command)
10275 filename[MaxTextExtent] = "\0";
10278 Request file name from user.
10280 if (command == MagickFalse)
10281 XFileBrowserWidget(display,windows,"Open",filename);
10297 Select next image from the command line.
10299 status=XGetCommand(display,windows->image.id,&files,&count);
10302 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10303 return((Image *) NULL);
10305 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10306 if (filelist == (char **) NULL)
10308 ThrowXWindowFatalException(ResourceLimitError,
10309 "MemoryAllocationFailed","...");
10310 (void) XFreeStringList(files);
10311 return((Image *) NULL);
10314 for (i=1; i < count; i++)
10315 if (*files[i] != '-')
10316 filelist[j++]=files[i];
10317 filelist[j]=(char *) NULL;
10318 XListBrowserWidget(display,windows,&windows->widget,
10319 (const char **) filelist,"Load","Select Image to Load:",filename);
10320 filelist=(char **) RelinquishMagickMemory(filelist);
10321 (void) XFreeStringList(files);
10323 if (*filename == '\0')
10324 return((Image *) NULL);
10325 image_info=CloneImageInfo(resource_info->image_info);
10326 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10328 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10329 exception=AcquireExceptionInfo();
10330 (void) SetImageInfo(image_info,0,exception);
10331 if (LocaleCompare(image_info->magick,"X") == 0)
10334 seconds[MaxTextExtent];
10337 User may want to delay the X server screen grab.
10339 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10340 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10342 if (*seconds == '\0')
10343 return((Image *) NULL);
10344 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10346 magick_info=GetMagickInfo(image_info->magick,exception);
10347 if ((magick_info != (const MagickInfo *) NULL) &&
10348 (magick_info->raw != MagickFalse))
10351 geometry[MaxTextExtent];
10354 Request image size from the user.
10356 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10357 if (image_info->size != (char *) NULL)
10358 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10359 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10361 (void) CloneString(&image_info->size,geometry);
10366 XSetCursorState(display,windows,MagickTrue);
10367 XCheckRefreshWindows(display,windows);
10368 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10369 nexus=ReadImage(image_info,exception);
10370 CatchException(exception);
10371 XSetCursorState(display,windows,MagickFalse);
10372 if (nexus != (Image *) NULL)
10373 XClientMessage(display,windows->image.id,windows->im_protocols,
10374 windows->im_next_image,CurrentTime);
10382 Unknown image format.
10384 text=FileToString(filename,~0,exception);
10385 if (text == (char *) NULL)
10386 return((Image *) NULL);
10387 textlist=StringToList(text);
10388 if (textlist != (char **) NULL)
10391 title[MaxTextExtent];
10396 (void) FormatLocaleString(title,MaxTextExtent,
10397 "Unknown format: %s",filename);
10398 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10399 (const char **) textlist);
10400 for (i=0; textlist[i] != (char *) NULL; i++)
10401 textlist[i]=DestroyString(textlist[i]);
10402 textlist=(char **) RelinquishMagickMemory(textlist);
10404 text=DestroyString(text);
10406 exception=DestroyExceptionInfo(exception);
10407 image_info=DestroyImageInfo(image_info);
10412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10416 + X P a n I m a g e %
10420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10422 % XPanImage() pans the image until the mouse button is released.
10424 % The format of the XPanImage method is:
10426 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10427 % ExceptionInfo *exception)
10429 % A description of each parameter follows:
10431 % o display: Specifies a connection to an X server; returned from
10434 % o windows: Specifies a pointer to a XWindows structure.
10436 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10437 % the entire image is refreshed.
10439 % o exception: return any errors or warnings in this structure.
10442 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10443 ExceptionInfo *exception)
10446 text[MaxTextExtent];
10464 if ((windows->image.ximage->width > (int) windows->image.width) &&
10465 (windows->image.ximage->height > (int) windows->image.height))
10466 cursor=XCreateFontCursor(display,XC_fleur);
10468 if (windows->image.ximage->width > (int) windows->image.width)
10469 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10471 if (windows->image.ximage->height > (int) windows->image.height)
10472 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10474 cursor=XCreateFontCursor(display,XC_arrow);
10475 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10477 Pan image as pointer moves until the mouse button is released.
10479 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10480 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10481 pan_info.width=windows->pan.width*windows->image.width/
10482 windows->image.ximage->width;
10483 pan_info.height=windows->pan.height*windows->image.height/
10484 windows->image.ximage->height;
10487 state=UpdateConfigurationState;
10490 switch (event->type)
10495 User choose an initial pan location.
10497 pan_info.x=(ssize_t) event->xbutton.x;
10498 pan_info.y=(ssize_t) event->xbutton.y;
10499 state|=UpdateConfigurationState;
10502 case ButtonRelease:
10505 User has finished panning the image.
10507 pan_info.x=(ssize_t) event->xbutton.x;
10508 pan_info.y=(ssize_t) event->xbutton.y;
10509 state|=UpdateConfigurationState | ExitState;
10514 pan_info.x=(ssize_t) event->xmotion.x;
10515 pan_info.y=(ssize_t) event->xmotion.y;
10516 state|=UpdateConfigurationState;
10521 if ((state & UpdateConfigurationState) != 0)
10524 Check boundary conditions.
10526 if (pan_info.x < (ssize_t) (pan_info.width/2))
10529 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10530 if (pan_info.x < 0)
10533 if ((int) (pan_info.x+windows->image.width) >
10534 windows->image.ximage->width)
10535 pan_info.x=(ssize_t)
10536 (windows->image.ximage->width-windows->image.width);
10537 if (pan_info.y < (ssize_t) (pan_info.height/2))
10540 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10541 if (pan_info.y < 0)
10544 if ((int) (pan_info.y+windows->image.height) >
10545 windows->image.ximage->height)
10546 pan_info.y=(ssize_t)
10547 (windows->image.ximage->height-windows->image.height);
10548 if ((windows->image.x != (int) pan_info.x) ||
10549 (windows->image.y != (int) pan_info.y))
10552 Display image pan offset.
10554 windows->image.x=(int) pan_info.x;
10555 windows->image.y=(int) pan_info.y;
10556 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10557 windows->image.width,windows->image.height,windows->image.x,
10559 XInfoWidget(display,windows,text);
10561 Refresh Image window.
10563 XDrawPanRectangle(display,windows);
10564 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10566 state&=(~UpdateConfigurationState);
10569 Wait for next event.
10571 if ((state & ExitState) == 0)
10572 XScreenEvent(display,windows,event,exception);
10573 } while ((state & ExitState) == 0);
10577 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10578 (void) XFreeCursor(display,cursor);
10579 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10587 + X P a s t e I m a g e %
10591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10593 % XPasteImage() pastes an image previously saved with XCropImage in the X
10594 % window image at a location the user chooses with the pointer.
10596 % The format of the XPasteImage method is:
10598 % MagickBooleanType XPasteImage(Display *display,
10599 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10600 % ExceptionInfo *exception)
10602 % A description of each parameter follows:
10604 % o display: Specifies a connection to an X server; returned from
10607 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10609 % o windows: Specifies a pointer to a XWindows structure.
10611 % o image: the image; returned from ReadImage.
10613 % o exception: return any errors or warnings in this structure.
10616 static MagickBooleanType XPasteImage(Display *display,
10617 XResourceInfo *resource_info,XWindows *windows,Image *image,
10618 ExceptionInfo *exception)
10629 static const ModeType
10632 PasteOperatorsCommand,
10634 PasteDismissCommand
10637 static CompositeOperator
10638 compose = CopyCompositeOp;
10641 text[MaxTextExtent];
10675 if (resource_info->copy_image == (Image *) NULL)
10676 return(MagickFalse);
10677 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10679 Map Command widget.
10681 (void) CloneString(&windows->command.name,"Paste");
10682 windows->command.data=1;
10683 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10684 (void) XMapRaised(display,windows->command.id);
10685 XClientMessage(display,windows->image.id,windows->im_protocols,
10686 windows->im_update_widget,CurrentTime);
10688 Track pointer until button 1 is pressed.
10690 XSetCursorState(display,windows,MagickFalse);
10691 XQueryPosition(display,windows->image.id,&x,&y);
10692 (void) XSelectInput(display,windows->image.id,
10693 windows->image.attributes.event_mask | PointerMotionMask);
10694 paste_info.x=(ssize_t) windows->image.x+x;
10695 paste_info.y=(ssize_t) windows->image.y+y;
10696 paste_info.width=0;
10697 paste_info.height=0;
10698 cursor=XCreateFontCursor(display,XC_ul_angle);
10699 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10700 state=DefaultState;
10703 if (windows->info.mapped != MagickFalse)
10706 Display pointer position.
10708 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10709 (long) paste_info.x,(long) paste_info.y);
10710 XInfoWidget(display,windows,text);
10712 highlight_info=paste_info;
10713 highlight_info.x=paste_info.x-windows->image.x;
10714 highlight_info.y=paste_info.y-windows->image.y;
10715 XHighlightRectangle(display,windows->image.id,
10716 windows->image.highlight_context,&highlight_info);
10718 Wait for next event.
10720 XScreenEvent(display,windows,&event,exception);
10721 XHighlightRectangle(display,windows->image.id,
10722 windows->image.highlight_context,&highlight_info);
10723 if (event.xany.window == windows->command.id)
10726 Select a command from the Command widget.
10728 id=XCommandWidget(display,windows,PasteMenu,&event);
10731 switch (PasteCommands[id])
10733 case PasteOperatorsCommand:
10736 command[MaxTextExtent],
10740 Select a command from the pop-up menu.
10742 operators=GetCommandOptions(MagickComposeOptions);
10743 if (operators == (char **) NULL)
10745 entry=XMenuWidget(display,windows,PasteMenu[id],
10746 (const char **) operators,command);
10748 compose=(CompositeOperator) ParseCommandOption(
10749 MagickComposeOptions,MagickFalse,operators[entry]);
10750 operators=DestroyStringList(operators);
10753 case PasteHelpCommand:
10755 XTextViewWidget(display,resource_info,windows,MagickFalse,
10756 "Help Viewer - Image Composite",ImagePasteHelp);
10759 case PasteDismissCommand:
10764 state|=EscapeState;
10773 switch (event.type)
10777 if (image->debug != MagickFalse)
10778 (void) LogMagickEvent(X11Event,GetMagickModule(),
10779 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10780 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10781 if (event.xbutton.button != Button1)
10783 if (event.xbutton.window != windows->image.id)
10786 Paste rectangle is relative to image configuration.
10788 width=(unsigned int) image->columns;
10789 height=(unsigned int) image->rows;
10792 if (windows->image.crop_geometry != (char *) NULL)
10793 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10795 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10796 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10797 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10798 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10799 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10800 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10801 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10804 case ButtonRelease:
10806 if (image->debug != MagickFalse)
10807 (void) LogMagickEvent(X11Event,GetMagickModule(),
10808 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10809 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10810 if (event.xbutton.button != Button1)
10812 if (event.xbutton.window != windows->image.id)
10814 if ((paste_info.width != 0) && (paste_info.height != 0))
10817 User has selected the location of the paste image.
10819 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10820 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10830 command[MaxTextExtent];
10838 if (event.xkey.window != windows->image.id)
10841 Respond to a user key press.
10843 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10844 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10845 *(command+length)='\0';
10846 if (image->debug != MagickFalse)
10847 (void) LogMagickEvent(X11Event,GetMagickModule(),
10848 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10849 switch ((int) key_symbol)
10857 paste_image=DestroyImage(paste_image);
10858 state|=EscapeState;
10865 (void) XSetFunction(display,windows->image.highlight_context,
10867 XTextViewWidget(display,resource_info,windows,MagickFalse,
10868 "Help Viewer - Image Composite",ImagePasteHelp);
10869 (void) XSetFunction(display,windows->image.highlight_context,
10875 (void) XBell(display,0);
10884 Map and unmap Info widget as text cursor crosses its boundaries.
10888 if (windows->info.mapped != MagickFalse)
10890 if ((x < (int) (windows->info.x+windows->info.width)) &&
10891 (y < (int) (windows->info.y+windows->info.height)))
10892 (void) XWithdrawWindow(display,windows->info.id,
10893 windows->info.screen);
10896 if ((x > (int) (windows->info.x+windows->info.width)) ||
10897 (y > (int) (windows->info.y+windows->info.height)))
10898 (void) XMapWindow(display,windows->info.id);
10899 paste_info.x=(ssize_t) windows->image.x+x;
10900 paste_info.y=(ssize_t) windows->image.y+y;
10905 if (image->debug != MagickFalse)
10906 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10911 } while ((state & ExitState) == 0);
10912 (void) XSelectInput(display,windows->image.id,
10913 windows->image.attributes.event_mask);
10914 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10915 XSetCursorState(display,windows,MagickFalse);
10916 (void) XFreeCursor(display,cursor);
10917 if ((state & EscapeState) != 0)
10918 return(MagickTrue);
10920 Image pasting is relative to image configuration.
10922 XSetCursorState(display,windows,MagickTrue);
10923 XCheckRefreshWindows(display,windows);
10924 width=(unsigned int) image->columns;
10925 height=(unsigned int) image->rows;
10928 if (windows->image.crop_geometry != (char *) NULL)
10929 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10930 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10932 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10933 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10934 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10936 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10937 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10939 Paste image with X Image window.
10941 (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y,
10943 paste_image=DestroyImage(paste_image);
10944 XSetCursorState(display,windows,MagickFalse);
10946 Update image colormap.
10948 XConfigureImageColormap(display,resource_info,windows,image,exception);
10949 (void) XConfigureImage(display,resource_info,windows,image,exception);
10950 return(MagickTrue);
10954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10958 + X P r i n t I m a g e %
10962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10964 % XPrintImage() prints an image to a Postscript printer.
10966 % The format of the XPrintImage method is:
10968 % MagickBooleanType XPrintImage(Display *display,
10969 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10970 % ExceptionInfo *exception)
10972 % A description of each parameter follows:
10974 % o display: Specifies a connection to an X server; returned from
10977 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10979 % o windows: Specifies a pointer to a XWindows structure.
10981 % o image: the image.
10983 % o exception: return any errors or warnings in this structure.
10986 static MagickBooleanType XPrintImage(Display *display,
10987 XResourceInfo *resource_info,XWindows *windows,Image *image,
10988 ExceptionInfo *exception)
10991 filename[MaxTextExtent],
10992 geometry[MaxTextExtent];
11004 Request Postscript page geometry from user.
11006 image_info=CloneImageInfo(resource_info->image_info);
11007 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
11008 if (image_info->page != (char *) NULL)
11009 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11010 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11011 "Select Postscript Page Geometry:",geometry);
11012 if (*geometry == '\0')
11013 return(MagickTrue);
11014 image_info->page=GetPageGeometry(geometry);
11016 Apply image transforms.
11018 XSetCursorState(display,windows,MagickTrue);
11019 XCheckRefreshWindows(display,windows);
11020 print_image=CloneImage(image,0,0,MagickTrue,exception);
11021 if (print_image == (Image *) NULL)
11022 return(MagickFalse);
11023 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11024 windows->image.ximage->width,windows->image.ximage->height);
11025 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11030 (void) AcquireUniqueFilename(filename);
11031 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11033 status=WriteImage(image_info,print_image,exception);
11034 (void) RelinquishUniqueFileResource(filename);
11035 print_image=DestroyImage(print_image);
11036 image_info=DestroyImageInfo(image_info);
11037 XSetCursorState(display,windows,MagickFalse);
11038 return(status != 0 ? MagickTrue : MagickFalse);
11042 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11046 + X R O I I m a g e %
11050 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11052 % XROIImage() applies an image processing technique to a region of interest.
11054 % The format of the XROIImage method is:
11056 % MagickBooleanType XROIImage(Display *display,
11057 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11058 % ExceptionInfo *exception)
11060 % A description of each parameter follows:
11062 % o display: Specifies a connection to an X server; returned from
11065 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11067 % o windows: Specifies a pointer to a XWindows structure.
11069 % o image: the image; returned from ReadImage.
11071 % o exception: return any errors or warnings in this structure.
11074 static MagickBooleanType XROIImage(Display *display,
11075 XResourceInfo *resource_info,XWindows *windows,Image **image,
11076 ExceptionInfo *exception)
11078 #define ApplyMenus 7
11128 "Contrast Stretch...",
11129 "Sigmoidal Contrast...",
11163 "Charcoal Draw...",
11166 *MiscellanyMenu[] =
11177 **Menus[ApplyMenus] =
11188 static const CommandType
11211 TransformCommands[] =
11215 RotateRightCommand,
11218 EnhanceCommands[] =
11226 ContrastStretchCommand,
11227 SigmoidalContrastCommand,
11235 EffectsCommands[] =
11239 ReduceNoiseCommand,
11258 CharcoalDrawCommand
11260 MiscellanyCommands[] =
11264 ShowPreviewCommand,
11265 ShowHistogramCommand,
11274 static const CommandType
11275 *Commands[ApplyMenus] =
11287 command[MaxTextExtent],
11288 text[MaxTextExtent];
11308 MagickProgressMonitor
11327 Map Command widget.
11329 (void) CloneString(&windows->command.name,"ROI");
11330 windows->command.data=0;
11331 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11332 (void) XMapRaised(display,windows->command.id);
11333 XClientMessage(display,windows->image.id,windows->im_protocols,
11334 windows->im_update_widget,CurrentTime);
11336 Track pointer until button 1 is pressed.
11338 XQueryPosition(display,windows->image.id,&x,&y);
11339 (void) XSelectInput(display,windows->image.id,
11340 windows->image.attributes.event_mask | PointerMotionMask);
11341 roi_info.x=(ssize_t) windows->image.x+x;
11342 roi_info.y=(ssize_t) windows->image.y+y;
11345 cursor=XCreateFontCursor(display,XC_fleur);
11346 state=DefaultState;
11349 if (windows->info.mapped != MagickFalse)
11352 Display pointer position.
11354 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11355 (long) roi_info.x,(long) roi_info.y);
11356 XInfoWidget(display,windows,text);
11359 Wait for next event.
11361 XScreenEvent(display,windows,&event,exception);
11362 if (event.xany.window == windows->command.id)
11365 Select a command from the Command widget.
11367 id=XCommandWidget(display,windows,ROIMenu,&event);
11370 switch (ROICommands[id])
11372 case ROIHelpCommand:
11374 XTextViewWidget(display,resource_info,windows,MagickFalse,
11375 "Help Viewer - Region of Interest",ImageROIHelp);
11378 case ROIDismissCommand:
11383 state|=EscapeState;
11392 switch (event.type)
11396 if (event.xbutton.button != Button1)
11398 if (event.xbutton.window != windows->image.id)
11401 Note first corner of region of interest rectangle-- exit loop.
11403 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11404 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11405 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11409 case ButtonRelease:
11418 if (event.xkey.window != windows->image.id)
11421 Respond to a user key press.
11423 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11424 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11425 switch ((int) key_symbol)
11433 state|=EscapeState;
11440 XTextViewWidget(display,resource_info,windows,MagickFalse,
11441 "Help Viewer - Region of Interest",ImageROIHelp);
11446 (void) XBell(display,0);
11455 Map and unmap Info widget as text cursor crosses its boundaries.
11459 if (windows->info.mapped != MagickFalse)
11461 if ((x < (int) (windows->info.x+windows->info.width)) &&
11462 (y < (int) (windows->info.y+windows->info.height)))
11463 (void) XWithdrawWindow(display,windows->info.id,
11464 windows->info.screen);
11467 if ((x > (int) (windows->info.x+windows->info.width)) ||
11468 (y > (int) (windows->info.y+windows->info.height)))
11469 (void) XMapWindow(display,windows->info.id);
11470 roi_info.x=(ssize_t) windows->image.x+x;
11471 roi_info.y=(ssize_t) windows->image.y+y;
11477 } while ((state & ExitState) == 0);
11478 (void) XSelectInput(display,windows->image.id,
11479 windows->image.attributes.event_mask);
11480 if ((state & EscapeState) != 0)
11483 User want to exit without region of interest.
11485 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11486 (void) XFreeCursor(display,cursor);
11487 return(MagickTrue);
11489 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11493 Size rectangle as pointer moves until the mouse button is released.
11495 x=(int) roi_info.x;
11496 y=(int) roi_info.y;
11499 state=DefaultState;
11502 highlight_info=roi_info;
11503 highlight_info.x=roi_info.x-windows->image.x;
11504 highlight_info.y=roi_info.y-windows->image.y;
11505 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11508 Display info and draw region of interest rectangle.
11510 if (windows->info.mapped == MagickFalse)
11511 (void) XMapWindow(display,windows->info.id);
11512 (void) FormatLocaleString(text,MaxTextExtent,
11513 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11514 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11515 XInfoWidget(display,windows,text);
11516 XHighlightRectangle(display,windows->image.id,
11517 windows->image.highlight_context,&highlight_info);
11520 if (windows->info.mapped != MagickFalse)
11521 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11523 Wait for next event.
11525 XScreenEvent(display,windows,&event,exception);
11526 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11527 XHighlightRectangle(display,windows->image.id,
11528 windows->image.highlight_context,&highlight_info);
11529 switch (event.type)
11533 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11534 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11537 case ButtonRelease:
11540 User has committed to region of interest rectangle.
11542 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11543 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11544 XSetCursorState(display,windows,MagickFalse);
11546 if (LocaleCompare(windows->command.name,"Apply") == 0)
11548 (void) CloneString(&windows->command.name,"Apply");
11549 windows->command.data=ApplyMenus;
11550 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11557 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11558 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11563 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11564 ((state & ExitState) != 0))
11567 Check boundary conditions.
11569 if (roi_info.x < 0)
11572 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11573 roi_info.x=(ssize_t) windows->image.ximage->width;
11574 if ((int) roi_info.x < x)
11575 roi_info.width=(unsigned int) (x-roi_info.x);
11578 roi_info.width=(unsigned int) (roi_info.x-x);
11579 roi_info.x=(ssize_t) x;
11581 if (roi_info.y < 0)
11584 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11585 roi_info.y=(ssize_t) windows->image.ximage->height;
11586 if ((int) roi_info.y < y)
11587 roi_info.height=(unsigned int) (y-roi_info.y);
11590 roi_info.height=(unsigned int) (roi_info.y-y);
11591 roi_info.y=(ssize_t) y;
11594 } while ((state & ExitState) == 0);
11596 Wait for user to grab a corner of the rectangle or press return.
11598 state=DefaultState;
11599 command_type=NullCommand;
11600 (void) XMapWindow(display,windows->info.id);
11603 if (windows->info.mapped != MagickFalse)
11606 Display pointer position.
11608 (void) FormatLocaleString(text,MaxTextExtent,
11609 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11610 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11611 XInfoWidget(display,windows,text);
11613 highlight_info=roi_info;
11614 highlight_info.x=roi_info.x-windows->image.x;
11615 highlight_info.y=roi_info.y-windows->image.y;
11616 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11618 state|=EscapeState;
11622 if ((state & UpdateRegionState) != 0)
11624 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11625 switch (command_type)
11630 (void) XMagickCommand(display,resource_info,windows,command_type,
11637 Region of interest is relative to image configuration.
11639 progress_monitor=SetImageProgressMonitor(*image,
11640 (MagickProgressMonitor) NULL,(*image)->client_data);
11641 crop_info=roi_info;
11642 width=(unsigned int) (*image)->columns;
11643 height=(unsigned int) (*image)->rows;
11646 if (windows->image.crop_geometry != (char *) NULL)
11647 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11649 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11651 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11652 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11653 scale_factor=(MagickRealType)
11654 height/windows->image.ximage->height;
11656 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11657 crop_info.height=(unsigned int)
11658 (scale_factor*crop_info.height+0.5);
11659 roi_image=CropImage(*image,&crop_info,exception);
11660 (void) SetImageProgressMonitor(*image,progress_monitor,
11661 (*image)->client_data);
11662 if (roi_image == (Image *) NULL)
11665 Apply image processing technique to the region of interest.
11667 windows->image.orphan=MagickTrue;
11668 (void) XMagickCommand(display,resource_info,windows,command_type,
11669 &roi_image,exception);
11670 progress_monitor=SetImageProgressMonitor(*image,
11671 (MagickProgressMonitor) NULL,(*image)->client_data);
11672 (void) XMagickCommand(display,resource_info,windows,
11673 SaveToUndoBufferCommand,image,exception);
11674 windows->image.orphan=MagickFalse;
11675 (void) CompositeImage(*image,CopyCompositeOp,roi_image,
11676 crop_info.x,crop_info.y,exception);
11677 roi_image=DestroyImage(roi_image);
11678 (void) SetImageProgressMonitor(*image,progress_monitor,
11679 (*image)->client_data);
11683 if (command_type != InfoCommand)
11685 XConfigureImageColormap(display,resource_info,windows,*image,
11687 (void) XConfigureImage(display,resource_info,windows,*image,
11690 XCheckRefreshWindows(display,windows);
11691 XInfoWidget(display,windows,text);
11692 (void) XSetFunction(display,windows->image.highlight_context,
11694 state&=(~UpdateRegionState);
11696 XHighlightRectangle(display,windows->image.id,
11697 windows->image.highlight_context,&highlight_info);
11698 XScreenEvent(display,windows,&event,exception);
11699 if (event.xany.window == windows->command.id)
11702 Select a command from the Command widget.
11704 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11705 command_type=NullCommand;
11706 id=XCommandWidget(display,windows,ApplyMenu,&event);
11709 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11710 command_type=ApplyCommands[id];
11711 if (id < ApplyMenus)
11714 Select a command from a pop-up menu.
11716 entry=XMenuWidget(display,windows,ApplyMenu[id],
11717 (const char **) Menus[id],command);
11720 (void) CopyMagickString(command,Menus[id][entry],
11722 command_type=Commands[id][entry];
11726 (void) XSetFunction(display,windows->image.highlight_context,
11728 XHighlightRectangle(display,windows->image.id,
11729 windows->image.highlight_context,&highlight_info);
11730 if (command_type == HelpCommand)
11732 (void) XSetFunction(display,windows->image.highlight_context,
11734 XTextViewWidget(display,resource_info,windows,MagickFalse,
11735 "Help Viewer - Region of Interest",ImageROIHelp);
11736 (void) XSetFunction(display,windows->image.highlight_context,
11740 if (command_type == QuitCommand)
11745 state|=EscapeState;
11749 if (command_type != NullCommand)
11750 state|=UpdateRegionState;
11753 XHighlightRectangle(display,windows->image.id,
11754 windows->image.highlight_context,&highlight_info);
11755 switch (event.type)
11759 x=windows->image.x;
11760 y=windows->image.y;
11761 if (event.xbutton.button != Button1)
11763 if (event.xbutton.window != windows->image.id)
11765 x=windows->image.x+event.xbutton.x;
11766 y=windows->image.y+event.xbutton.y;
11767 if ((x < (int) (roi_info.x+RoiDelta)) &&
11768 (x > (int) (roi_info.x-RoiDelta)) &&
11769 (y < (int) (roi_info.y+RoiDelta)) &&
11770 (y > (int) (roi_info.y-RoiDelta)))
11772 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11773 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11774 state|=UpdateConfigurationState;
11777 if ((x < (int) (roi_info.x+RoiDelta)) &&
11778 (x > (int) (roi_info.x-RoiDelta)) &&
11779 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11780 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11782 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11783 state|=UpdateConfigurationState;
11786 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11787 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11788 (y < (int) (roi_info.y+RoiDelta)) &&
11789 (y > (int) (roi_info.y-RoiDelta)))
11791 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11792 state|=UpdateConfigurationState;
11795 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11796 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11797 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11798 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11800 state|=UpdateConfigurationState;
11804 case ButtonRelease:
11806 if (event.xbutton.window == windows->pan.id)
11807 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11808 (highlight_info.y != crop_info.y-windows->image.y))
11809 XHighlightRectangle(display,windows->image.id,
11810 windows->image.highlight_context,&highlight_info);
11811 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11812 event.xbutton.time);
11817 if (event.xexpose.window == windows->image.id)
11818 if (event.xexpose.count == 0)
11820 event.xexpose.x=(int) highlight_info.x;
11821 event.xexpose.y=(int) highlight_info.y;
11822 event.xexpose.width=(int) highlight_info.width;
11823 event.xexpose.height=(int) highlight_info.height;
11824 XRefreshWindow(display,&windows->image,&event);
11826 if (event.xexpose.window == windows->info.id)
11827 if (event.xexpose.count == 0)
11828 XInfoWidget(display,windows,text);
11836 if (event.xkey.window != windows->image.id)
11839 Respond to a user key press.
11841 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11842 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11843 switch ((int) key_symbol)
11850 state|=EscapeState;
11859 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11860 roi_info.y=(ssize_t) (windows->image.height/2L-
11861 roi_info.height/2L);
11893 (void) XSetFunction(display,windows->image.highlight_context,
11895 XTextViewWidget(display,resource_info,windows,MagickFalse,
11896 "Help Viewer - Region of Interest",ImageROIHelp);
11897 (void) XSetFunction(display,windows->image.highlight_context,
11903 command_type=XImageWindowCommand(display,resource_info,windows,
11904 event.xkey.state,key_symbol,image,exception);
11905 if (command_type != NullCommand)
11906 state|=UpdateRegionState;
11910 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11918 if (event.xbutton.window != windows->image.id)
11921 Map and unmap Info widget as text cursor crosses its boundaries.
11925 if (windows->info.mapped != MagickFalse)
11927 if ((x < (int) (windows->info.x+windows->info.width)) &&
11928 (y < (int) (windows->info.y+windows->info.height)))
11929 (void) XWithdrawWindow(display,windows->info.id,
11930 windows->info.screen);
11933 if ((x > (int) (windows->info.x+windows->info.width)) ||
11934 (y > (int) (windows->info.y+windows->info.height)))
11935 (void) XMapWindow(display,windows->info.id);
11936 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11937 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11940 case SelectionRequest:
11945 XSelectionRequestEvent
11949 Set primary selection.
11951 (void) FormatLocaleString(text,MaxTextExtent,
11952 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11953 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11954 request=(&(event.xselectionrequest));
11955 (void) XChangeProperty(request->display,request->requestor,
11956 request->property,request->target,8,PropModeReplace,
11957 (unsigned char *) text,(int) strlen(text));
11958 notify.type=SelectionNotify;
11959 notify.display=request->display;
11960 notify.requestor=request->requestor;
11961 notify.selection=request->selection;
11962 notify.target=request->target;
11963 notify.time=request->time;
11964 if (request->property == None)
11965 notify.property=request->target;
11967 notify.property=request->property;
11968 (void) XSendEvent(request->display,request->requestor,False,0,
11969 (XEvent *) ¬ify);
11974 if ((state & UpdateConfigurationState) != 0)
11976 (void) XPutBackEvent(display,&event);
11977 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11980 } while ((state & ExitState) == 0);
11981 } while ((state & ExitState) == 0);
11982 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11983 XSetCursorState(display,windows,MagickFalse);
11984 if ((state & EscapeState) != 0)
11985 return(MagickTrue);
11986 return(MagickTrue);
11990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11994 + X R o t a t e I m a g e %
11998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12000 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
12001 % rotation angle is computed from the slope of a line drawn by the user.
12003 % The format of the XRotateImage method is:
12005 % MagickBooleanType XRotateImage(Display *display,
12006 % XResourceInfo *resource_info,XWindows *windows,double degrees,
12007 % Image **image,ExceptionInfo *exception)
12009 % A description of each parameter follows:
12011 % o display: Specifies a connection to an X server; returned from
12014 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12016 % o windows: Specifies a pointer to a XWindows structure.
12018 % o degrees: Specifies the number of degrees to rotate the image.
12020 % o image: the image.
12022 % o exception: return any errors or warnings in this structure.
12025 static MagickBooleanType XRotateImage(Display *display,
12026 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12027 ExceptionInfo *exception)
12040 direction = HorizontalRotateCommand;
12042 static const ModeType
12043 DirectionCommands[] =
12045 HorizontalRotateCommand,
12046 VerticalRotateCommand
12050 RotateColorCommand,
12051 RotateDirectionCommand,
12053 RotateDismissCommand
12056 static unsigned int
12060 command[MaxTextExtent],
12061 text[MaxTextExtent];
12072 normalized_degrees;
12082 if (degrees == 0.0)
12097 Map Command widget.
12099 (void) CloneString(&windows->command.name,"Rotate");
12100 windows->command.data=2;
12101 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12102 (void) XMapRaised(display,windows->command.id);
12103 XClientMessage(display,windows->image.id,windows->im_protocols,
12104 windows->im_update_widget,CurrentTime);
12106 Wait for first button press.
12108 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12109 XQueryPosition(display,windows->image.id,&x,&y);
12114 state=DefaultState;
12117 XHighlightLine(display,windows->image.id,
12118 windows->image.highlight_context,&rotate_info);
12120 Wait for next event.
12122 XScreenEvent(display,windows,&event,exception);
12123 XHighlightLine(display,windows->image.id,
12124 windows->image.highlight_context,&rotate_info);
12125 if (event.xany.window == windows->command.id)
12128 Select a command from the Command widget.
12130 id=XCommandWidget(display,windows,RotateMenu,&event);
12133 (void) XSetFunction(display,windows->image.highlight_context,
12135 switch (RotateCommands[id])
12137 case RotateColorCommand:
12140 *ColorMenu[MaxNumberPens];
12149 Initialize menu selections.
12151 for (i=0; i < (int) (MaxNumberPens-2); i++)
12152 ColorMenu[i]=resource_info->pen_colors[i];
12153 ColorMenu[MaxNumberPens-2]="Browser...";
12154 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12156 Select a pen color from the pop-up menu.
12158 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12159 (const char **) ColorMenu,command);
12160 if (pen_number < 0)
12162 if (pen_number == (MaxNumberPens-2))
12165 color_name[MaxTextExtent] = "gray";
12168 Select a pen color from a dialog.
12170 resource_info->pen_colors[pen_number]=color_name;
12171 XColorBrowserWidget(display,windows,"Select",color_name);
12172 if (*color_name == '\0')
12178 (void) XParseColor(display,windows->map_info->colormap,
12179 resource_info->pen_colors[pen_number],&color);
12180 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12181 (unsigned int) MaxColors,&color);
12182 windows->pixel_info->pen_colors[pen_number]=color;
12183 pen_id=(unsigned int) pen_number;
12186 case RotateDirectionCommand:
12197 Select a command from the pop-up menu.
12199 id=XMenuWidget(display,windows,RotateMenu[id],
12200 Directions,command);
12202 direction=DirectionCommands[id];
12205 case RotateHelpCommand:
12207 XTextViewWidget(display,resource_info,windows,MagickFalse,
12208 "Help Viewer - Image Rotation",ImageRotateHelp);
12211 case RotateDismissCommand:
12216 state|=EscapeState;
12223 (void) XSetFunction(display,windows->image.highlight_context,
12227 switch (event.type)
12231 if (event.xbutton.button != Button1)
12233 if (event.xbutton.window != windows->image.id)
12238 (void) XSetFunction(display,windows->image.highlight_context,
12240 rotate_info.x1=event.xbutton.x;
12241 rotate_info.y1=event.xbutton.y;
12245 case ButtonRelease:
12252 command[MaxTextExtent];
12257 if (event.xkey.window != windows->image.id)
12260 Respond to a user key press.
12262 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12263 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12264 switch ((int) key_symbol)
12272 state|=EscapeState;
12279 (void) XSetFunction(display,windows->image.highlight_context,
12281 XTextViewWidget(display,resource_info,windows,MagickFalse,
12282 "Help Viewer - Image Rotation",ImageRotateHelp);
12283 (void) XSetFunction(display,windows->image.highlight_context,
12289 (void) XBell(display,0);
12297 rotate_info.x1=event.xmotion.x;
12298 rotate_info.y1=event.xmotion.y;
12301 rotate_info.x2=rotate_info.x1;
12302 rotate_info.y2=rotate_info.y1;
12303 if (direction == HorizontalRotateCommand)
12304 rotate_info.x2+=32;
12306 rotate_info.y2-=32;
12307 } while ((state & ExitState) == 0);
12308 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12309 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12310 if ((state & EscapeState) != 0)
12311 return(MagickTrue);
12313 Draw line as pointer moves until the mouse button is released.
12316 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12317 state=DefaultState;
12323 Display info and draw rotation line.
12325 if (windows->info.mapped == MagickFalse)
12326 (void) XMapWindow(display,windows->info.id);
12327 (void) FormatLocaleString(text,MaxTextExtent," %g",
12328 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12329 XInfoWidget(display,windows,text);
12330 XHighlightLine(display,windows->image.id,
12331 windows->image.highlight_context,&rotate_info);
12334 if (windows->info.mapped != MagickFalse)
12335 (void) XWithdrawWindow(display,windows->info.id,
12336 windows->info.screen);
12338 Wait for next event.
12340 XScreenEvent(display,windows,&event,exception);
12342 XHighlightLine(display,windows->image.id,
12343 windows->image.highlight_context,&rotate_info);
12344 switch (event.type)
12348 case ButtonRelease:
12351 User has committed to rotation line.
12353 rotate_info.x2=event.xbutton.x;
12354 rotate_info.y2=event.xbutton.y;
12362 rotate_info.x2=event.xmotion.x;
12363 rotate_info.y2=event.xmotion.y;
12369 Check boundary conditions.
12371 if (rotate_info.x2 < 0)
12374 if (rotate_info.x2 > (int) windows->image.width)
12375 rotate_info.x2=(short) windows->image.width;
12376 if (rotate_info.y2 < 0)
12379 if (rotate_info.y2 > (int) windows->image.height)
12380 rotate_info.y2=(short) windows->image.height;
12382 Compute rotation angle from the slope of the line.
12385 distance=(unsigned int)
12386 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12387 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12389 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12390 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12391 } while ((state & ExitState) == 0);
12392 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12393 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12395 return(MagickTrue);
12397 if (direction == VerticalRotateCommand)
12399 if (degrees == 0.0)
12400 return(MagickTrue);
12404 normalized_degrees=degrees;
12405 while (normalized_degrees < -45.0)
12406 normalized_degrees+=360.0;
12407 for (rotations=0; normalized_degrees > 45.0; rotations++)
12408 normalized_degrees-=90.0;
12409 if (normalized_degrees != 0.0)
12410 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12412 XSetCursorState(display,windows,MagickTrue);
12413 XCheckRefreshWindows(display,windows);
12414 (*image)->background_color.red=ScaleShortToQuantum(
12415 windows->pixel_info->pen_colors[pen_id].red);
12416 (*image)->background_color.green=ScaleShortToQuantum(
12417 windows->pixel_info->pen_colors[pen_id].green);
12418 (*image)->background_color.blue=ScaleShortToQuantum(
12419 windows->pixel_info->pen_colors[pen_id].blue);
12420 rotate_image=RotateImage(*image,degrees,exception);
12421 XSetCursorState(display,windows,MagickFalse);
12422 if (rotate_image == (Image *) NULL)
12423 return(MagickFalse);
12424 *image=DestroyImage(*image);
12425 *image=rotate_image;
12426 if (windows->image.crop_geometry != (char *) NULL)
12429 Rotate crop geometry.
12431 width=(unsigned int) (*image)->columns;
12432 height=(unsigned int) (*image)->rows;
12433 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12434 switch (rotations % 4)
12444 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12445 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12452 Rotate 180 degrees.
12454 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12455 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12461 Rotate 270 degrees.
12463 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12464 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12469 if (windows->image.orphan != MagickFalse)
12470 return(MagickTrue);
12471 if (normalized_degrees != 0.0)
12474 Update image colormap.
12476 windows->image.window_changes.width=(int) (*image)->columns;
12477 windows->image.window_changes.height=(int) (*image)->rows;
12478 if (windows->image.crop_geometry != (char *) NULL)
12481 Obtain dimensions of image from crop geometry.
12483 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12485 windows->image.window_changes.width=(int) width;
12486 windows->image.window_changes.height=(int) height;
12488 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12491 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12493 windows->image.window_changes.width=windows->image.ximage->height;
12494 windows->image.window_changes.height=windows->image.ximage->width;
12497 Update image configuration.
12499 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12500 return(MagickTrue);
12504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12508 + X S a v e I m a g e %
12512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12514 % XSaveImage() saves an image to a file.
12516 % The format of the XSaveImage method is:
12518 % MagickBooleanType XSaveImage(Display *display,
12519 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12520 % ExceptionInfo *exception)
12522 % A description of each parameter follows:
12524 % o display: Specifies a connection to an X server; returned from
12527 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12529 % o windows: Specifies a pointer to a XWindows structure.
12531 % o image: the image.
12533 % o exception: return any errors or warnings in this structure.
12536 static MagickBooleanType XSaveImage(Display *display,
12537 XResourceInfo *resource_info,XWindows *windows,Image *image,
12538 ExceptionInfo *exception)
12541 filename[MaxTextExtent],
12542 geometry[MaxTextExtent];
12554 Request file name from user.
12556 if (resource_info->write_filename != (char *) NULL)
12557 (void) CopyMagickString(filename,resource_info->write_filename,
12562 path[MaxTextExtent];
12567 GetPathComponent(image->filename,HeadPath,path);
12568 GetPathComponent(image->filename,TailPath,filename);
12571 status=chdir(path);
12573 (void) ThrowMagickException(exception,GetMagickModule(),
12574 FileOpenError,"UnableToOpenFile","%s",path);
12577 XFileBrowserWidget(display,windows,"Save",filename);
12578 if (*filename == '\0')
12579 return(MagickTrue);
12580 if (IsPathAccessible(filename) != MagickFalse)
12586 File exists-- seek user's permission before overwriting.
12588 status=XConfirmWidget(display,windows,"Overwrite",filename);
12590 return(MagickTrue);
12592 image_info=CloneImageInfo(resource_info->image_info);
12593 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12594 (void) SetImageInfo(image_info,1,exception);
12595 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12596 (LocaleCompare(image_info->magick,"JPG") == 0))
12599 quality[MaxTextExtent];
12605 Request JPEG quality from user.
12607 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12609 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12611 if (*quality == '\0')
12612 return(MagickTrue);
12613 image->quality=StringToUnsignedLong(quality);
12614 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12616 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12617 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12618 (LocaleCompare(image_info->magick,"PS") == 0) ||
12619 (LocaleCompare(image_info->magick,"PS2") == 0))
12622 geometry[MaxTextExtent];
12625 Request page geometry from user.
12627 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12628 if (LocaleCompare(image_info->magick,"PDF") == 0)
12629 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12630 if (image_info->page != (char *) NULL)
12631 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12632 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12633 "Select page geometry:",geometry);
12634 if (*geometry != '\0')
12635 image_info->page=GetPageGeometry(geometry);
12638 Apply image transforms.
12640 XSetCursorState(display,windows,MagickTrue);
12641 XCheckRefreshWindows(display,windows);
12642 save_image=CloneImage(image,0,0,MagickTrue,exception);
12643 if (save_image == (Image *) NULL)
12644 return(MagickFalse);
12645 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12646 windows->image.ximage->width,windows->image.ximage->height);
12647 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12652 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12653 status=WriteImage(image_info,save_image,exception);
12654 if (status != MagickFalse)
12655 image->taint=MagickFalse;
12656 save_image=DestroyImage(save_image);
12657 image_info=DestroyImageInfo(image_info);
12658 XSetCursorState(display,windows,MagickFalse);
12659 return(status != 0 ? MagickTrue : MagickFalse);
12663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12667 + X S c r e e n E v e n t %
12671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12673 % XScreenEvent() handles global events associated with the Pan and Magnify
12676 % The format of the XScreenEvent function is:
12678 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12679 % ExceptionInfo *exception)
12681 % A description of each parameter follows:
12683 % o display: Specifies a pointer to the Display structure; returned from
12686 % o windows: Specifies a pointer to a XWindows structure.
12688 % o event: Specifies a pointer to a X11 XEvent structure.
12690 % o exception: return any errors or warnings in this structure.
12694 #if defined(__cplusplus) || defined(c_plusplus)
12698 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12703 windows=(XWindows *) data;
12704 if ((event->type == ClientMessage) &&
12705 (event->xclient.window == windows->image.id))
12706 return(MagickFalse);
12707 return(MagickTrue);
12710 #if defined(__cplusplus) || defined(c_plusplus)
12714 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12715 ExceptionInfo *exception)
12721 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12722 if (event->xany.window == windows->command.id)
12724 switch (event->type)
12727 case ButtonRelease:
12729 if ((event->xbutton.button == Button3) &&
12730 (event->xbutton.state & Mod1Mask))
12733 Convert Alt-Button3 to Button2.
12735 event->xbutton.button=Button2;
12736 event->xbutton.state&=(~Mod1Mask);
12738 if (event->xbutton.window == windows->backdrop.id)
12740 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12741 event->xbutton.time);
12744 if (event->xbutton.window == windows->pan.id)
12746 XPanImage(display,windows,event,exception);
12749 if (event->xbutton.window == windows->image.id)
12750 if (event->xbutton.button == Button2)
12753 Update magnified image.
12755 x=event->xbutton.x;
12756 y=event->xbutton.y;
12760 if (x >= (int) windows->image.width)
12761 x=(int) (windows->image.width-1);
12762 windows->magnify.x=(int) windows->image.x+x;
12766 if (y >= (int) windows->image.height)
12767 y=(int) (windows->image.height-1);
12768 windows->magnify.y=windows->image.y+y;
12769 if (windows->magnify.mapped == MagickFalse)
12770 (void) XMapRaised(display,windows->magnify.id);
12771 XMakeMagnifyImage(display,windows,exception);
12772 if (event->type == ButtonRelease)
12773 (void) XWithdrawWindow(display,windows->info.id,
12774 windows->info.screen);
12779 case ClientMessage:
12782 If client window delete message, exit.
12784 if (event->xclient.message_type != windows->wm_protocols)
12786 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12788 if (event->xclient.window == windows->magnify.id)
12790 (void) XWithdrawWindow(display,windows->magnify.id,
12791 windows->magnify.screen);
12796 case ConfigureNotify:
12798 if (event->xconfigure.window == windows->magnify.id)
12804 Magnify window has a new configuration.
12806 windows->magnify.width=(unsigned int) event->xconfigure.width;
12807 windows->magnify.height=(unsigned int) event->xconfigure.height;
12808 if (windows->magnify.mapped == MagickFalse)
12811 while ((int) magnify <= event->xconfigure.width)
12813 while ((int) magnify <= event->xconfigure.height)
12816 if (((int) magnify != event->xconfigure.width) ||
12817 ((int) magnify != event->xconfigure.height))
12822 window_changes.width=(int) magnify;
12823 window_changes.height=(int) magnify;
12824 (void) XReconfigureWMWindow(display,windows->magnify.id,
12825 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12829 XMakeMagnifyImage(display,windows,exception);
12836 if (event->xexpose.window == windows->image.id)
12838 XRefreshWindow(display,&windows->image,event);
12841 if (event->xexpose.window == windows->pan.id)
12842 if (event->xexpose.count == 0)
12844 XDrawPanRectangle(display,windows);
12847 if (event->xexpose.window == windows->magnify.id)
12848 if (event->xexpose.count == 0)
12850 XMakeMagnifyImage(display,windows,exception);
12858 command[MaxTextExtent];
12863 if (event->xkey.window != windows->magnify.id)
12866 Respond to a user key press.
12868 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12869 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12870 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12876 if (event->xmap.window == windows->magnify.id)
12878 windows->magnify.mapped=MagickTrue;
12879 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12882 if (event->xmap.window == windows->info.id)
12884 windows->info.mapped=MagickTrue;
12891 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12892 if (event->xmotion.window == windows->image.id)
12893 if (windows->magnify.mapped != MagickFalse)
12896 Update magnified image.
12898 x=event->xmotion.x;
12899 y=event->xmotion.y;
12903 if (x >= (int) windows->image.width)
12904 x=(int) (windows->image.width-1);
12905 windows->magnify.x=(int) windows->image.x+x;
12909 if (y >= (int) windows->image.height)
12910 y=(int) (windows->image.height-1);
12911 windows->magnify.y=windows->image.y+y;
12912 XMakeMagnifyImage(display,windows,exception);
12918 if (event->xunmap.window == windows->magnify.id)
12920 windows->magnify.mapped=MagickFalse;
12923 if (event->xunmap.window == windows->info.id)
12925 windows->info.mapped=MagickFalse;
12936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12940 + X S e t C r o p G e o m e t r y %
12944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12946 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12947 % and translates it to a cropping geometry relative to the image.
12949 % The format of the XSetCropGeometry method is:
12951 % void XSetCropGeometry(Display *display,XWindows *windows,
12952 % RectangleInfo *crop_info,Image *image)
12954 % A description of each parameter follows:
12956 % o display: Specifies a connection to an X server; returned from
12959 % o windows: Specifies a pointer to a XWindows structure.
12961 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12962 % Image window to crop.
12964 % o image: the image.
12967 static void XSetCropGeometry(Display *display,XWindows *windows,
12968 RectangleInfo *crop_info,Image *image)
12971 text[MaxTextExtent];
12984 if (windows->info.mapped != MagickFalse)
12987 Display info on cropping rectangle.
12989 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12990 (double) crop_info->width,(double) crop_info->height,(double)
12991 crop_info->x,(double) crop_info->y);
12992 XInfoWidget(display,windows,text);
12995 Cropping geometry is relative to any previous crop geometry.
12999 width=(unsigned int) image->columns;
13000 height=(unsigned int) image->rows;
13001 if (windows->image.crop_geometry != (char *) NULL)
13002 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13004 windows->image.crop_geometry=AcquireString((char *) NULL);
13006 Define the crop geometry string from the cropping rectangle.
13008 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13009 if (crop_info->x > 0)
13010 x+=(int) (scale_factor*crop_info->x+0.5);
13011 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13014 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13015 if (crop_info->y > 0)
13016 y+=(int) (scale_factor*crop_info->y+0.5);
13017 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13020 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13021 "%ux%u%+d%+d",width,height,x,y);
13025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13029 + X T i l e I m a g e %
13033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13035 % XTileImage() loads or deletes a selected tile from a visual image directory.
13036 % The load or delete command is chosen from a menu.
13038 % The format of the XTileImage method is:
13040 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13041 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13043 % A description of each parameter follows:
13045 % o tile_image: XTileImage reads or deletes the tile image
13046 % and returns it. A null image is returned if an error occurs.
13048 % o display: Specifies a connection to an X server; returned from
13051 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13053 % o windows: Specifies a pointer to a XWindows structure.
13055 % o image: the image; returned from ReadImage.
13057 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13058 % the entire image is refreshed.
13060 % o exception: return any errors or warnings in this structure.
13063 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13064 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13077 static const ModeType
13088 command[MaxTextExtent],
13089 filename[MaxTextExtent];
13116 Tile image is relative to montage image configuration.
13120 width=(unsigned int) image->columns;
13121 height=(unsigned int) image->rows;
13122 if (windows->image.crop_geometry != (char *) NULL)
13123 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13124 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13125 event->xbutton.x+=windows->image.x;
13126 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13127 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13128 event->xbutton.y+=windows->image.y;
13129 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13131 Determine size and location of each tile in the visual image directory.
13133 width=(unsigned int) image->columns;
13134 height=(unsigned int) image->rows;
13137 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13138 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13139 (event->xbutton.x-x)/width;
13143 Button press is outside any tile.
13145 (void) XBell(display,0);
13146 return((Image *) NULL);
13149 Determine file name from the tile directory.
13151 p=image->directory;
13152 for (i=tile; (i != 0) && (*p != '\0'); )
13161 Button press is outside any tile.
13163 (void) XBell(display,0);
13164 return((Image *) NULL);
13167 Select a command from the pop-up menu.
13169 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13171 return((Image *) NULL);
13173 while ((*q != '\n') && (*q != '\0'))
13175 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13177 Perform command for the selected tile.
13179 XSetCursorState(display,windows,MagickTrue);
13180 XCheckRefreshWindows(display,windows);
13181 tile_image=NewImageList();
13182 switch (TileCommands[id])
13184 case TileLoadCommand:
13189 XCheckRefreshWindows(display,windows);
13190 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13192 (void) CopyMagickString(resource_info->image_info->filename,filename,
13194 tile_image=ReadImage(resource_info->image_info,exception);
13195 CatchException(exception);
13196 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13199 case TileNextCommand:
13202 Display next image.
13204 XClientMessage(display,windows->image.id,windows->im_protocols,
13205 windows->im_next_image,CurrentTime);
13208 case TileFormerCommand:
13211 Display former image.
13213 XClientMessage(display,windows->image.id,windows->im_protocols,
13214 windows->im_former_image,CurrentTime);
13217 case TileDeleteCommand:
13222 if (IsPathAccessible(filename) == MagickFalse)
13224 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13227 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13230 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
13231 if (status != MagickFalse)
13233 XNoticeWidget(display,windows,"Unable to delete image file:",
13238 case TileUpdateCommand:
13248 virtual_pixel[CompositePixelChannel];
13257 Ensure all the images exist.
13260 GetPixelInfo(image,&pixel);
13261 for (p=image->directory; *p != '\0'; p++)
13267 while ((*q != '\n') && (*q != '\0'))
13269 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13271 if (IsPathAccessible(filename) != MagickFalse)
13277 Overwrite tile with background color.
13279 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13280 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13281 image_view=AcquireCacheView(image);
13282 (void) GetOneCacheViewVirtualPixel(image_view,0,0,virtual_pixel,
13284 pixel.red=virtual_pixel[RedPixelChannel];
13285 pixel.green=virtual_pixel[GreenPixelChannel];
13286 pixel.blue=virtual_pixel[BluePixelChannel];
13287 pixel.alpha=virtual_pixel[AlphaPixelChannel];
13288 for (i=0; i < (int) height; i++)
13290 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13291 y_offset+i,width,1,exception);
13292 if (s == (Quantum *) NULL)
13294 for (j=0; j < (int) width; j++)
13296 SetPixelPixelInfo(image,&pixel,s);
13297 s+=GetPixelChannels(image);
13299 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13302 image_view=DestroyCacheView(image_view);
13305 windows->image.window_changes.width=(int) image->columns;
13306 windows->image.window_changes.height=(int) image->rows;
13307 XConfigureImageColormap(display,resource_info,windows,image,exception);
13308 (void) XConfigureImage(display,resource_info,windows,image,exception);
13314 XSetCursorState(display,windows,MagickFalse);
13315 return(tile_image);
13319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13323 + X T r a n s l a t e I m a g e %
13327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13329 % XTranslateImage() translates the image within an Image window by one pixel
13330 % as specified by the key symbol. If the image has a `montage string the
13331 % translation is respect to the width and height contained within the string.
13333 % The format of the XTranslateImage method is:
13335 % void XTranslateImage(Display *display,XWindows *windows,
13336 % Image *image,const KeySym key_symbol)
13338 % A description of each parameter follows:
13340 % o display: Specifies a connection to an X server; returned from
13343 % o windows: Specifies a pointer to a XWindows structure.
13345 % o image: the image.
13347 % o key_symbol: Specifies a KeySym which indicates which side of the image
13351 static void XTranslateImage(Display *display,XWindows *windows,
13352 Image *image,const KeySym key_symbol)
13355 text[MaxTextExtent];
13366 User specified a pan position offset.
13368 x_offset=windows->image.width;
13369 y_offset=windows->image.height;
13370 if (image->montage != (char *) NULL)
13371 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13372 switch ((int) key_symbol)
13377 windows->image.x=(int) windows->image.width/2;
13378 windows->image.y=(int) windows->image.height/2;
13384 windows->image.x-=x_offset;
13391 windows->image.y-=y_offset;
13397 windows->image.x+=x_offset;
13404 windows->image.y+=y_offset;
13411 Check boundary conditions.
13413 if (windows->image.x < 0)
13414 windows->image.x=0;
13416 if ((int) (windows->image.x+windows->image.width) >
13417 windows->image.ximage->width)
13418 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13419 if (windows->image.y < 0)
13420 windows->image.y=0;
13422 if ((int) (windows->image.y+windows->image.height) >
13423 windows->image.ximage->height)
13424 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13426 Refresh Image window.
13428 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13429 windows->image.width,windows->image.height,windows->image.x,
13431 XInfoWidget(display,windows,text);
13432 XCheckRefreshWindows(display,windows);
13433 XDrawPanRectangle(display,windows);
13434 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13435 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13443 + X T r i m I m a g e %
13447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13449 % XTrimImage() trims the edges from the Image window.
13451 % The format of the XTrimImage method is:
13453 % MagickBooleanType XTrimImage(Display *display,
13454 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13455 % ExceptionInfo *exception)
13457 % A description of each parameter follows:
13459 % o display: Specifies a connection to an X server; returned from
13462 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13464 % o windows: Specifies a pointer to a XWindows structure.
13466 % o image: the image.
13468 % o exception: return any errors or warnings in this structure.
13471 static MagickBooleanType XTrimImage(Display *display,
13472 XResourceInfo *resource_info,XWindows *windows,Image *image,
13473 ExceptionInfo *exception)
13487 Trim edges from image.
13489 XSetCursorState(display,windows,MagickTrue);
13490 XCheckRefreshWindows(display,windows);
13492 Crop the left edge.
13494 background=XGetPixel(windows->image.ximage,0,0);
13495 trim_info.width=(size_t) windows->image.ximage->width;
13496 for (x=0; x < windows->image.ximage->width; x++)
13498 for (y=0; y < windows->image.ximage->height; y++)
13500 pixel=XGetPixel(windows->image.ximage,x,y);
13501 if (pixel != background)
13504 if (y < windows->image.ximage->height)
13507 trim_info.x=(ssize_t) x;
13508 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13510 XSetCursorState(display,windows,MagickFalse);
13511 return(MagickFalse);
13514 Crop the right edge.
13516 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13517 for (x=windows->image.ximage->width-1; x != 0; x--)
13519 for (y=0; y < windows->image.ximage->height; y++)
13521 pixel=XGetPixel(windows->image.ximage,x,y);
13522 if (pixel != background)
13525 if (y < windows->image.ximage->height)
13528 trim_info.width=(size_t) (x-trim_info.x+1);
13532 background=XGetPixel(windows->image.ximage,0,0);
13533 trim_info.height=(size_t) windows->image.ximage->height;
13534 for (y=0; y < windows->image.ximage->height; y++)
13536 for (x=0; x < windows->image.ximage->width; x++)
13538 pixel=XGetPixel(windows->image.ximage,x,y);
13539 if (pixel != background)
13542 if (x < windows->image.ximage->width)
13545 trim_info.y=(ssize_t) y;
13547 Crop the bottom edge.
13549 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13550 for (y=windows->image.ximage->height-1; y != 0; y--)
13552 for (x=0; x < windows->image.ximage->width; x++)
13554 pixel=XGetPixel(windows->image.ximage,x,y);
13555 if (pixel != background)
13558 if (x < windows->image.ximage->width)
13561 trim_info.height=(size_t) y-trim_info.y+1;
13562 if (((unsigned int) trim_info.width != windows->image.width) ||
13563 ((unsigned int) trim_info.height != windows->image.height))
13566 Reconfigure Image window as defined by the trimming rectangle.
13568 XSetCropGeometry(display,windows,&trim_info,image);
13569 windows->image.window_changes.width=(int) trim_info.width;
13570 windows->image.window_changes.height=(int) trim_info.height;
13571 (void) XConfigureImage(display,resource_info,windows,image,exception);
13573 XSetCursorState(display,windows,MagickFalse);
13574 return(MagickTrue);
13578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13582 + X V i s u a l D i r e c t o r y I m a g e %
13586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13588 % XVisualDirectoryImage() creates a Visual Image Directory.
13590 % The format of the XVisualDirectoryImage method is:
13592 % Image *XVisualDirectoryImage(Display *display,
13593 % XResourceInfo *resource_info,XWindows *windows,
13594 % ExceptionInfo *exception)
13596 % A description of each parameter follows:
13598 % o display: Specifies a connection to an X server; returned from
13601 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13603 % o windows: Specifies a pointer to a XWindows structure.
13605 % o exception: return any errors or warnings in this structure.
13608 static Image *XVisualDirectoryImage(Display *display,
13609 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13611 #define TileImageTag "Scale/Image"
13612 #define XClientName "montage"
13645 filename[MaxTextExtent] = "\0",
13646 filenames[MaxTextExtent] = "*";
13649 background_resources;
13652 Request file name from user.
13654 XFileBrowserWidget(display,windows,"Directory",filenames);
13655 if (*filenames == '\0')
13656 return((Image *) NULL);
13658 Expand the filenames.
13660 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13661 if (filelist == (char **) NULL)
13663 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13665 return((Image *) NULL);
13668 filelist[0]=filenames;
13669 status=ExpandFilenames(&number_files,&filelist);
13670 if ((status == MagickFalse) || (number_files == 0))
13672 if (number_files == 0)
13673 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13675 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13677 return((Image *) NULL);
13680 Set image background resources.
13682 background_resources=(*resource_info);
13683 background_resources.window_id=AcquireString("");
13684 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13685 "0x%lx",windows->image.id);
13686 background_resources.backdrop=MagickTrue;
13688 Read each image and convert them to a tile.
13690 backdrop=(windows->visual_info->klass == TrueColor) ||
13691 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13692 read_info=CloneImageInfo(resource_info->image_info);
13693 (void) SetImageOption(read_info,"jpeg:size","120x120");
13694 (void) CloneString(&read_info->size,DefaultTileGeometry);
13695 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13697 images=NewImageList();
13698 XSetCursorState(display,windows,MagickTrue);
13699 XCheckRefreshWindows(display,windows);
13700 for (i=0; i < (int) number_files; i++)
13702 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13703 filelist[i]=DestroyString(filelist[i]);
13704 *read_info->magick='\0';
13705 next_image=ReadImage(read_info,exception);
13706 CatchException(exception);
13707 if (next_image != (Image *) NULL)
13709 (void) DeleteImageProperty(next_image,"label");
13710 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13711 read_info,next_image,DefaultTileLabel,exception),exception);
13712 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13714 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13715 geometry.height,exception);
13716 if (thumbnail_image != (Image *) NULL)
13718 next_image=DestroyImage(next_image);
13719 next_image=thumbnail_image;
13723 (void) XDisplayBackgroundImage(display,&background_resources,
13724 next_image,exception);
13725 XSetCursorState(display,windows,MagickTrue);
13727 AppendImageToList(&images,next_image);
13728 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13733 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13734 (MagickSizeType) number_files);
13735 if (proceed == MagickFalse)
13740 filelist=(char **) RelinquishMagickMemory(filelist);
13741 if (images == (Image *) NULL)
13743 read_info=DestroyImageInfo(read_info);
13744 XSetCursorState(display,windows,MagickFalse);
13745 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13746 return((Image *) NULL);
13749 Create the Visual Image Directory.
13751 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13752 montage_info->pointsize=10;
13753 if (resource_info->font != (char *) NULL)
13754 (void) CloneString(&montage_info->font,resource_info->font);
13755 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13756 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13757 images),exception);
13758 images=DestroyImageList(images);
13759 montage_info=DestroyMontageInfo(montage_info);
13760 read_info=DestroyImageInfo(read_info);
13761 XSetCursorState(display,windows,MagickFalse);
13762 if (montage_image == (Image *) NULL)
13763 return(montage_image);
13764 XClientMessage(display,windows->image.id,windows->im_protocols,
13765 windows->im_next_image,CurrentTime);
13766 return(montage_image);
13770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13774 % X D i s p l a y B a c k g r o u n d I m a g e %
13778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13780 % XDisplayBackgroundImage() displays an image in the background of a window.
13782 % The format of the XDisplayBackgroundImage method is:
13784 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13785 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13787 % A description of each parameter follows:
13789 % o display: Specifies a connection to an X server; returned from
13792 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13794 % o image: the image.
13796 % o exception: return any errors or warnings in this structure.
13799 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13800 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13803 geometry[MaxTextExtent],
13804 visual_type[MaxTextExtent];
13817 static XStandardColormap
13821 *visual_info = (XVisualInfo *) NULL;
13842 Determine target window.
13844 assert(image != (Image *) NULL);
13845 assert(image->signature == MagickSignature);
13846 if (image->debug != MagickFalse)
13847 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13848 resources=(*resource_info);
13849 window_info.id=(Window) NULL;
13850 root_window=XRootWindow(display,XDefaultScreen(display));
13851 if (LocaleCompare(resources.window_id,"root") == 0)
13852 window_info.id=root_window;
13855 if (isdigit((unsigned char) *resources.window_id) != 0)
13856 window_info.id=XWindowByID(display,root_window,
13857 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13858 if (window_info.id == (Window) NULL)
13859 window_info.id=XWindowByName(display,root_window,resources.window_id);
13861 if (window_info.id == (Window) NULL)
13863 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13864 resources.window_id);
13865 return(MagickFalse);
13868 Determine window visual id.
13870 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13871 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13872 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13873 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13875 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13876 XVisualIDFromVisual(window_attributes.visual));
13877 if (visual_info == (XVisualInfo *) NULL)
13880 Allocate standard colormap.
13882 map_info=XAllocStandardColormap();
13883 if (map_info == (XStandardColormap *) NULL)
13884 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13886 map_info->colormap=(Colormap) NULL;
13887 pixel.pixels=(unsigned long *) NULL;
13889 Initialize visual info.
13891 resources.map_type=(char *) NULL;
13892 resources.visual_type=visual_type;
13893 visual_info=XBestVisualInfo(display,map_info,&resources);
13894 if (visual_info == (XVisualInfo *) NULL)
13895 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13896 resources.visual_type);
13898 Initialize window info.
13900 window_info.ximage=(XImage *) NULL;
13901 window_info.matte_image=(XImage *) NULL;
13902 window_info.pixmap=(Pixmap) NULL;
13903 window_info.matte_pixmap=(Pixmap) NULL;
13906 Free previous root colors.
13908 if (window_info.id == root_window)
13909 (void) XDestroyWindowColors(display,root_window);
13911 Initialize Standard Colormap.
13913 resources.colormap=SharedColormap;
13914 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13917 Graphic context superclass.
13919 context_values.background=pixel.background_color.pixel;
13920 context_values.foreground=pixel.foreground_color.pixel;
13921 pixel.annotate_context=XCreateGC(display,window_info.id,
13922 (size_t) (GCBackground | GCForeground),&context_values);
13923 if (pixel.annotate_context == (GC) NULL)
13924 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13927 Initialize Image window attributes.
13929 window_info.name=AcquireString("\0");
13930 window_info.icon_name=AcquireString("\0");
13931 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13932 &resources,&window_info);
13934 Create the X image.
13936 window_info.width=(unsigned int) image->columns;
13937 window_info.height=(unsigned int) image->rows;
13938 if ((image->columns != window_info.width) ||
13939 (image->rows != window_info.height))
13940 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13942 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13943 window_attributes.width,window_attributes.height);
13944 geometry_info.width=window_info.width;
13945 geometry_info.height=window_info.height;
13946 geometry_info.x=(ssize_t) window_info.x;
13947 geometry_info.y=(ssize_t) window_info.y;
13948 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13949 &geometry_info.width,&geometry_info.height);
13950 window_info.width=(unsigned int) geometry_info.width;
13951 window_info.height=(unsigned int) geometry_info.height;
13952 window_info.x=(int) geometry_info.x;
13953 window_info.y=(int) geometry_info.y;
13954 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13955 window_info.height,exception);
13956 if (status == MagickFalse)
13957 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13961 if (image->debug != MagickFalse)
13963 (void) LogMagickEvent(X11Event,GetMagickModule(),
13964 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13965 (double) image->columns,(double) image->rows);
13966 if (image->colors != 0)
13967 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13969 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13972 Adjust image dimensions as specified by backdrop or geometry options.
13974 width=(int) window_info.width;
13975 height=(int) window_info.height;
13976 if (resources.backdrop != MagickFalse)
13979 Center image on window.
13981 window_info.x=(window_attributes.width/2)-
13982 (window_info.ximage->width/2);
13983 window_info.y=(window_attributes.height/2)-
13984 (window_info.ximage->height/2);
13985 width=window_attributes.width;
13986 height=window_attributes.height;
13988 if ((resources.image_geometry != (char *) NULL) &&
13989 (*resources.image_geometry != '\0'))
13992 default_geometry[MaxTextExtent];
14002 User specified geometry.
14004 size_hints=XAllocSizeHints();
14005 if (size_hints == (XSizeHints *) NULL)
14006 ThrowXWindowFatalException(ResourceLimitFatalError,
14007 "MemoryAllocationFailed",image->filename);
14008 size_hints->flags=0L;
14009 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
14011 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
14012 default_geometry,window_info.border_width,size_hints,&window_info.x,
14013 &window_info.y,&width,&height,&gravity);
14014 if (flags & (XValue | YValue))
14016 width=window_attributes.width;
14017 height=window_attributes.height;
14019 (void) XFree((void *) size_hints);
14022 Create the X pixmap.
14024 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14025 (unsigned int) height,window_info.depth);
14026 if (window_info.pixmap == (Pixmap) NULL)
14027 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14030 Display pixmap on the window.
14032 if (((unsigned int) width > window_info.width) ||
14033 ((unsigned int) height > window_info.height))
14034 (void) XFillRectangle(display,window_info.pixmap,
14035 window_info.annotate_context,0,0,(unsigned int) width,
14036 (unsigned int) height);
14037 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14038 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14039 window_info.width,(unsigned int) window_info.height);
14040 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14041 (void) XClearWindow(display,window_info.id);
14042 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14043 XDelay(display,delay == 0UL ? 10UL : delay);
14044 (void) XSync(display,MagickFalse);
14045 return(window_info.id == root_window ? MagickTrue : MagickFalse);
14049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14053 + X D i s p l a y I m a g e %
14057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14059 % XDisplayImage() displays an image via X11. A new image is created and
14060 % returned if the user interactively transforms the displayed image.
14062 % The format of the XDisplayImage method is:
14064 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14065 % char **argv,int argc,Image **image,size_t *state,
14066 % ExceptionInfo *exception)
14068 % A description of each parameter follows:
14070 % o nexus: Method XDisplayImage returns an image when the
14071 % user chooses 'Open Image' from the command menu or picks a tile
14072 % from the image directory. Otherwise a null image is returned.
14074 % o display: Specifies a connection to an X server; returned from
14077 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14079 % o argv: Specifies the application's argument list.
14081 % o argc: Specifies the number of arguments.
14083 % o image: Specifies an address to an address of an Image structure;
14085 % o exception: return any errors or warnings in this structure.
14088 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14089 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14091 #define MagnifySize 256 /* must be a power of 2 */
14092 #define MagickMenus 10
14093 #define MagickTitle "Commands"
14120 "Visual Directory...",
14166 "Contrast Stretch...",
14167 "Sigmoidal Contrast...",
14201 "Charcoal Draw...",
14215 "Region of Interest...",
14218 *MiscellanyMenu[] =
14233 "Browse Documentation",
14260 **Menus[MagickMenus] =
14298 VisualDirectoryCommand,
14312 OriginalSizeCommand,
14319 TransformCommands[] =
14325 RotateRightCommand,
14332 EnhanceCommands[] =
14340 ContrastStretchCommand,
14341 SigmoidalContrastCommand,
14349 EffectsCommands[] =
14353 ReduceNoiseCommand,
14373 CharcoalDrawCommand
14375 ImageEditCommands[] =
14386 RegionofInterestCommand
14388 MiscellanyCommands[] =
14392 ShowPreviewCommand,
14393 ShowHistogramCommand,
14402 BrowseDocumentationCommand,
14405 ShortCutsCommands[] =
14417 VirtualCommands[] =
14426 *Commands[MagickMenus] =
14436 MiscellanyCommands,
14441 command[MaxTextExtent],
14443 geometry[MaxTextExtent],
14444 resource_name[MaxTextExtent];
14471 working_directory[MaxTextExtent];
14477 *magick_windows[MaxXWindows];
14479 static unsigned int
14539 assert(image != (Image **) NULL);
14540 assert((*image)->signature == MagickSignature);
14541 if ((*image)->debug != MagickFalse)
14542 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14543 display_image=(*image);
14544 warning_handler=(WarningHandler) NULL;
14545 windows=XSetWindows((XWindows *) ~0);
14546 if (windows != (XWindows *) NULL)
14551 status=chdir(working_directory);
14553 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14554 "UnableToOpenFile","%s",working_directory);
14555 warning_handler=resource_info->display_warnings ?
14556 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14557 warning_handler=resource_info->display_warnings ?
14558 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14563 Allocate windows structure.
14565 resource_info->colors=display_image->colors;
14566 windows=XSetWindows(XInitializeWindows(display,resource_info));
14567 if (windows == (XWindows *) NULL)
14568 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14569 (*image)->filename);
14571 Initialize window id's.
14574 magick_windows[number_windows++]=(&windows->icon);
14575 magick_windows[number_windows++]=(&windows->backdrop);
14576 magick_windows[number_windows++]=(&windows->image);
14577 magick_windows[number_windows++]=(&windows->info);
14578 magick_windows[number_windows++]=(&windows->command);
14579 magick_windows[number_windows++]=(&windows->widget);
14580 magick_windows[number_windows++]=(&windows->popup);
14581 magick_windows[number_windows++]=(&windows->magnify);
14582 magick_windows[number_windows++]=(&windows->pan);
14583 for (i=0; i < (int) number_windows; i++)
14584 magick_windows[i]->id=(Window) NULL;
14589 Initialize font info.
14591 if (windows->font_info != (XFontStruct *) NULL)
14592 (void) XFreeFont(display,windows->font_info);
14593 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14594 if (windows->font_info == (XFontStruct *) NULL)
14595 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14596 resource_info->font);
14598 Initialize Standard Colormap.
14600 map_info=windows->map_info;
14601 icon_map=windows->icon_map;
14602 visual_info=windows->visual_info;
14603 icon_visual=windows->icon_visual;
14604 pixel=windows->pixel_info;
14605 icon_pixel=windows->icon_pixel;
14606 font_info=windows->font_info;
14607 icon_resources=windows->icon_resources;
14608 class_hints=windows->class_hints;
14609 manager_hints=windows->manager_hints;
14610 root_window=XRootWindow(display,visual_info->screen);
14611 nexus=NewImageList();
14612 if (display_image->debug != MagickFalse)
14614 (void) LogMagickEvent(X11Event,GetMagickModule(),
14615 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14616 (double) display_image->scene,(double) display_image->columns,
14617 (double) display_image->rows);
14618 if (display_image->colors != 0)
14619 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14620 display_image->colors);
14621 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14622 display_image->magick);
14624 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14625 map_info,pixel,exception);
14626 display_image->taint=MagickFalse;
14628 Initialize graphic context.
14630 windows->context.id=(Window) NULL;
14631 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14632 resource_info,&windows->context);
14633 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14634 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14635 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14636 manager_hints->flags=InputHint | StateHint;
14637 manager_hints->input=MagickFalse;
14638 manager_hints->initial_state=WithdrawnState;
14639 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14640 &windows->context);
14641 if (display_image->debug != MagickFalse)
14642 (void) LogMagickEvent(X11Event,GetMagickModule(),
14643 "Window id: 0x%lx (context)",windows->context.id);
14644 context_values.background=pixel->background_color.pixel;
14645 context_values.font=font_info->fid;
14646 context_values.foreground=pixel->foreground_color.pixel;
14647 context_values.graphics_exposures=MagickFalse;
14648 context_mask=(MagickStatusType)
14649 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14650 if (pixel->annotate_context != (GC) NULL)
14651 (void) XFreeGC(display,pixel->annotate_context);
14652 pixel->annotate_context=XCreateGC(display,windows->context.id,
14653 context_mask,&context_values);
14654 if (pixel->annotate_context == (GC) NULL)
14655 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14656 display_image->filename);
14657 context_values.background=pixel->depth_color.pixel;
14658 if (pixel->widget_context != (GC) NULL)
14659 (void) XFreeGC(display,pixel->widget_context);
14660 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14662 if (pixel->widget_context == (GC) NULL)
14663 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14664 display_image->filename);
14665 context_values.background=pixel->foreground_color.pixel;
14666 context_values.foreground=pixel->background_color.pixel;
14667 context_values.plane_mask=context_values.background ^
14668 context_values.foreground;
14669 if (pixel->highlight_context != (GC) NULL)
14670 (void) XFreeGC(display,pixel->highlight_context);
14671 pixel->highlight_context=XCreateGC(display,windows->context.id,
14672 (size_t) (context_mask | GCPlaneMask),&context_values);
14673 if (pixel->highlight_context == (GC) NULL)
14674 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14675 display_image->filename);
14676 (void) XDestroyWindow(display,windows->context.id);
14678 Initialize icon window.
14680 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14681 icon_resources,&windows->icon);
14682 windows->icon.geometry=resource_info->icon_geometry;
14683 XBestIconSize(display,&windows->icon,display_image);
14684 windows->icon.attributes.colormap=XDefaultColormap(display,
14685 icon_visual->screen);
14686 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14687 manager_hints->flags=InputHint | StateHint;
14688 manager_hints->input=MagickFalse;
14689 manager_hints->initial_state=IconicState;
14690 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14692 if (display_image->debug != MagickFalse)
14693 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14696 Initialize graphic context for icon window.
14698 if (icon_pixel->annotate_context != (GC) NULL)
14699 (void) XFreeGC(display,icon_pixel->annotate_context);
14700 context_values.background=icon_pixel->background_color.pixel;
14701 context_values.foreground=icon_pixel->foreground_color.pixel;
14702 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14703 (size_t) (GCBackground | GCForeground),&context_values);
14704 if (icon_pixel->annotate_context == (GC) NULL)
14705 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14706 display_image->filename);
14707 windows->icon.annotate_context=icon_pixel->annotate_context;
14709 Initialize Image window.
14711 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14713 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14714 if (resource_info->use_shared_memory == MagickFalse)
14715 windows->image.shared_memory=MagickFalse;
14716 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14721 title=InterpretImageProperties(resource_info->image_info,display_image,
14722 resource_info->title,exception);
14723 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14724 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14725 title=DestroyString(title);
14730 filename[MaxTextExtent];
14733 Window name is the base of the filename.
14735 GetPathComponent(display_image->magick_filename,TailPath,filename);
14736 if (display_image->scene == 0)
14737 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14738 "%s: %s",MagickPackageName,filename);
14740 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14741 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14742 (double) display_image->scene,(double) GetImageListLength(
14744 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14746 if (resource_info->immutable)
14747 windows->image.immutable=MagickTrue;
14748 windows->image.use_pixmap=resource_info->use_pixmap;
14749 windows->image.geometry=resource_info->image_geometry;
14750 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14751 XDisplayWidth(display,visual_info->screen),
14752 XDisplayHeight(display,visual_info->screen));
14753 geometry_info.width=display_image->columns;
14754 geometry_info.height=display_image->rows;
14757 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14758 &geometry_info.width,&geometry_info.height);
14759 windows->image.width=(unsigned int) geometry_info.width;
14760 windows->image.height=(unsigned int) geometry_info.height;
14761 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14762 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14763 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14764 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14765 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14766 resource_info,&windows->backdrop);
14767 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14770 Initialize backdrop window.
14772 windows->backdrop.x=0;
14773 windows->backdrop.y=0;
14774 (void) CloneString(&windows->backdrop.name,"Backdrop");
14775 windows->backdrop.flags=(size_t) (USSize | USPosition);
14776 windows->backdrop.width=(unsigned int)
14777 XDisplayWidth(display,visual_info->screen);
14778 windows->backdrop.height=(unsigned int)
14779 XDisplayHeight(display,visual_info->screen);
14780 windows->backdrop.border_width=0;
14781 windows->backdrop.immutable=MagickTrue;
14782 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14784 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14785 StructureNotifyMask;
14786 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14787 manager_hints->icon_window=windows->icon.id;
14788 manager_hints->input=MagickTrue;
14789 manager_hints->initial_state=resource_info->iconic ? IconicState :
14791 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14792 &windows->backdrop);
14793 if (display_image->debug != MagickFalse)
14794 (void) LogMagickEvent(X11Event,GetMagickModule(),
14795 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14796 (void) XMapWindow(display,windows->backdrop.id);
14797 (void) XClearWindow(display,windows->backdrop.id);
14798 if (windows->image.id != (Window) NULL)
14800 (void) XDestroyWindow(display,windows->image.id);
14801 windows->image.id=(Window) NULL;
14804 Position image in the center the backdrop.
14806 windows->image.flags|=USPosition;
14807 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14808 (windows->image.width/2);
14809 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14810 (windows->image.height/2);
14812 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14813 manager_hints->icon_window=windows->icon.id;
14814 manager_hints->input=MagickTrue;
14815 manager_hints->initial_state=resource_info->iconic ? IconicState :
14817 if (windows->group_leader.id != (Window) NULL)
14822 manager_hints->flags|=WindowGroupHint;
14823 manager_hints->window_group=windows->group_leader.id;
14824 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14825 if (display_image->debug != MagickFalse)
14826 (void) LogMagickEvent(X11Event,GetMagickModule(),
14827 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14829 XMakeWindow(display,
14830 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14831 argv,argc,class_hints,manager_hints,&windows->image);
14832 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14833 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14834 if (windows->group_leader.id != (Window) NULL)
14835 (void) XSetTransientForHint(display,windows->image.id,
14836 windows->group_leader.id);
14837 if (display_image->debug != MagickFalse)
14838 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14839 windows->image.id);
14841 Initialize Info widget.
14843 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14845 (void) CloneString(&windows->info.name,"Info");
14846 (void) CloneString(&windows->info.icon_name,"Info");
14847 windows->info.border_width=1;
14850 windows->info.flags|=PPosition;
14851 windows->info.attributes.win_gravity=UnmapGravity;
14852 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14853 StructureNotifyMask;
14854 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14855 manager_hints->input=MagickFalse;
14856 manager_hints->initial_state=NormalState;
14857 manager_hints->window_group=windows->image.id;
14858 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14860 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14861 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14862 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14863 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14864 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14865 if (windows->image.mapped != MagickFalse)
14866 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14867 if (display_image->debug != MagickFalse)
14868 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14871 Initialize Command widget.
14873 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14874 resource_info,&windows->command);
14875 windows->command.data=MagickMenus;
14876 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14877 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14878 resource_info->client_name);
14879 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14880 resource_name,"geometry",(char *) NULL);
14881 (void) CloneString(&windows->command.name,MagickTitle);
14882 windows->command.border_width=0;
14883 windows->command.flags|=PPosition;
14884 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14885 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14886 OwnerGrabButtonMask | StructureNotifyMask;
14887 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14888 manager_hints->input=MagickTrue;
14889 manager_hints->initial_state=NormalState;
14890 manager_hints->window_group=windows->image.id;
14891 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14892 &windows->command);
14893 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14894 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14896 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14897 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14898 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14899 if (windows->command.mapped != MagickFalse)
14900 (void) XMapRaised(display,windows->command.id);
14901 if (display_image->debug != MagickFalse)
14902 (void) LogMagickEvent(X11Event,GetMagickModule(),
14903 "Window id: 0x%lx (command)",windows->command.id);
14905 Initialize Widget window.
14907 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14908 resource_info,&windows->widget);
14909 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14910 resource_info->client_name);
14911 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14912 resource_name,"geometry",(char *) NULL);
14913 windows->widget.border_width=0;
14914 windows->widget.flags|=PPosition;
14915 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14916 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14917 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14918 StructureNotifyMask;
14919 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14920 manager_hints->input=MagickTrue;
14921 manager_hints->initial_state=NormalState;
14922 manager_hints->window_group=windows->image.id;
14923 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14925 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14926 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14927 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14928 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14929 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14930 if (display_image->debug != MagickFalse)
14931 (void) LogMagickEvent(X11Event,GetMagickModule(),
14932 "Window id: 0x%lx (widget)",windows->widget.id);
14934 Initialize popup window.
14936 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14937 resource_info,&windows->popup);
14938 windows->popup.border_width=0;
14939 windows->popup.flags|=PPosition;
14940 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14941 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14942 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14943 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14944 manager_hints->input=MagickTrue;
14945 manager_hints->initial_state=NormalState;
14946 manager_hints->window_group=windows->image.id;
14947 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14949 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14950 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14951 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14952 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14953 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14954 if (display_image->debug != MagickFalse)
14955 (void) LogMagickEvent(X11Event,GetMagickModule(),
14956 "Window id: 0x%lx (pop up)",windows->popup.id);
14958 Initialize Magnify window and cursor.
14960 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14961 resource_info,&windows->magnify);
14962 if (resource_info->use_shared_memory == MagickFalse)
14963 windows->magnify.shared_memory=MagickFalse;
14964 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14965 resource_info->client_name);
14966 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14967 resource_name,"geometry",(char *) NULL);
14968 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14969 resource_info->magnify);
14970 if (windows->magnify.cursor != (Cursor) NULL)
14971 (void) XFreeCursor(display,windows->magnify.cursor);
14972 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14973 map_info->colormap,resource_info->background_color,
14974 resource_info->foreground_color);
14975 if (windows->magnify.cursor == (Cursor) NULL)
14976 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14977 display_image->filename);
14978 windows->magnify.width=MagnifySize;
14979 windows->magnify.height=MagnifySize;
14980 windows->magnify.flags|=PPosition;
14981 windows->magnify.min_width=MagnifySize;
14982 windows->magnify.min_height=MagnifySize;
14983 windows->magnify.width_inc=MagnifySize;
14984 windows->magnify.height_inc=MagnifySize;
14985 windows->magnify.data=resource_info->magnify;
14986 windows->magnify.attributes.cursor=windows->magnify.cursor;
14987 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14988 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14989 StructureNotifyMask;
14990 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14991 manager_hints->input=MagickTrue;
14992 manager_hints->initial_state=NormalState;
14993 manager_hints->window_group=windows->image.id;
14994 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14995 &windows->magnify);
14996 if (display_image->debug != MagickFalse)
14997 (void) LogMagickEvent(X11Event,GetMagickModule(),
14998 "Window id: 0x%lx (magnify)",windows->magnify.id);
14999 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
15001 Initialize panning window.
15003 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
15004 resource_info,&windows->pan);
15005 (void) CloneString(&windows->pan.name,"Pan Icon");
15006 windows->pan.width=windows->icon.width;
15007 windows->pan.height=windows->icon.height;
15008 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
15009 resource_info->client_name);
15010 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
15011 resource_name,"geometry",(char *) NULL);
15012 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
15013 &windows->pan.width,&windows->pan.height);
15014 windows->pan.flags|=PPosition;
15015 windows->pan.immutable=MagickTrue;
15016 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15017 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15018 StructureNotifyMask;
15019 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15020 manager_hints->input=MagickFalse;
15021 manager_hints->initial_state=NormalState;
15022 manager_hints->window_group=windows->image.id;
15023 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15025 if (display_image->debug != MagickFalse)
15026 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15028 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15029 if (windows->info.mapped != MagickFalse)
15030 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15031 if ((windows->image.mapped == MagickFalse) ||
15032 (windows->backdrop.id != (Window) NULL))
15033 (void) XMapWindow(display,windows->image.id);
15035 Set our progress monitor and warning handlers.
15037 if (warning_handler == (WarningHandler) NULL)
15039 warning_handler=resource_info->display_warnings ?
15040 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15041 warning_handler=resource_info->display_warnings ?
15042 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15045 Initialize Image and Magnify X images.
15047 windows->image.x=0;
15048 windows->image.y=0;
15049 windows->magnify.shape=MagickFalse;
15050 width=(unsigned int) display_image->columns;
15051 height=(unsigned int) display_image->rows;
15052 if ((display_image->columns != width) || (display_image->rows != height))
15053 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15054 display_image->filename);
15055 status=XMakeImage(display,resource_info,&windows->image,display_image,
15056 width,height,exception);
15057 if (status == MagickFalse)
15058 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15059 display_image->filename);
15060 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15061 windows->magnify.width,windows->magnify.height,exception);
15062 if (status == MagickFalse)
15063 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15064 display_image->filename);
15065 if (windows->magnify.mapped != MagickFalse)
15066 (void) XMapRaised(display,windows->magnify.id);
15067 if (windows->pan.mapped != MagickFalse)
15068 (void) XMapRaised(display,windows->pan.id);
15069 windows->image.window_changes.width=(int) display_image->columns;
15070 windows->image.window_changes.height=(int) display_image->rows;
15071 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15072 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15073 (void) XSync(display,MagickFalse);
15077 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15078 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15080 if (resource_info->update != MagickFalse)
15086 Determine when file data was last modified.
15088 status=GetPathAttributes(display_image->filename,&attributes);
15089 if (status != MagickFalse)
15090 update_time=attributes.st_mtime;
15092 *state&=(~FormerImageState);
15093 *state&=(~MontageImageState);
15094 *state&=(~NextImageState);
15098 Handle a window event.
15100 if (windows->image.mapped != MagickFalse)
15101 if ((display_image->delay != 0) || (resource_info->update != 0))
15103 if (timer < time((time_t *) NULL))
15105 if (resource_info->update == MagickFalse)
15106 *state|=NextImageState | ExitState;
15113 Determine if image file was modified.
15115 status=GetPathAttributes(display_image->filename,&attributes);
15116 if (status != MagickFalse)
15117 if (update_time != attributes.st_mtime)
15122 (void) FormatLocaleString(
15123 resource_info->image_info->filename,MaxTextExtent,
15124 "%s:%s",display_image->magick,
15125 display_image->filename);
15126 nexus=ReadImage(resource_info->image_info,exception);
15127 if (nexus != (Image *) NULL)
15129 nexus=DestroyImage(nexus);
15130 *state|=NextImageState | ExitState;
15133 delay=display_image->delay/MagickMax(
15134 display_image->ticks_per_second,1L);
15135 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15138 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15141 Do not block if delay > 0.
15143 XDelay(display,SuspendTime << 2);
15147 timestamp=time((time_t *) NULL);
15148 (void) XNextEvent(display,&event);
15149 if (windows->image.stasis == MagickFalse)
15150 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15151 MagickTrue : MagickFalse;
15152 if (windows->magnify.stasis == MagickFalse)
15153 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15154 MagickTrue : MagickFalse;
15155 if (event.xany.window == windows->command.id)
15158 Select a command from the Command widget.
15160 id=XCommandWidget(display,windows,CommandMenu,&event);
15163 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15164 command_type=CommandMenus[id];
15165 if (id < MagickMenus)
15168 Select a command from a pop-up menu.
15170 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15174 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15175 command_type=Commands[id][entry];
15177 if (command_type != NullCommand)
15178 nexus=XMagickCommand(display,resource_info,windows,command_type,
15179 &display_image,exception);
15182 switch (event.type)
15186 if (display_image->debug != MagickFalse)
15187 (void) LogMagickEvent(X11Event,GetMagickModule(),
15188 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15189 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15190 if ((event.xbutton.button == Button3) &&
15191 (event.xbutton.state & Mod1Mask))
15194 Convert Alt-Button3 to Button2.
15196 event.xbutton.button=Button2;
15197 event.xbutton.state&=(~Mod1Mask);
15199 if (event.xbutton.window == windows->backdrop.id)
15201 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15202 event.xbutton.time);
15205 if (event.xbutton.window == windows->image.id)
15207 switch (event.xbutton.button)
15211 if (resource_info->immutable)
15214 Select a command from the Virtual menu.
15216 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15219 nexus=XMagickCommand(display,resource_info,windows,
15220 VirtualCommands[entry],&display_image,exception);
15224 Map/unmap Command widget.
15226 if (windows->command.mapped != MagickFalse)
15227 (void) XWithdrawWindow(display,windows->command.id,
15228 windows->command.screen);
15231 (void) XCommandWidget(display,windows,CommandMenu,
15233 (void) XMapRaised(display,windows->command.id);
15240 User pressed the image magnify button.
15242 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15243 &display_image,exception);
15244 XMagnifyImage(display,windows,&event,exception);
15249 if (resource_info->immutable)
15252 Select a command from the Virtual menu.
15254 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15257 nexus=XMagickCommand(display,resource_info,windows,
15258 VirtualCommands[entry],&display_image,exception);
15261 if (display_image->montage != (char *) NULL)
15264 Open or delete a tile from a visual image directory.
15266 nexus=XTileImage(display,resource_info,windows,
15267 display_image,&event,exception);
15268 if (nexus != (Image *) NULL)
15269 *state|=MontageImageState | NextImageState | ExitState;
15270 vid_info.x=(short int) windows->image.x;
15271 vid_info.y=(short int) windows->image.y;
15275 Select a command from the Short Cuts menu.
15277 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15280 nexus=XMagickCommand(display,resource_info,windows,
15281 ShortCutsCommands[entry],&display_image,exception);
15289 XTranslateImage(display,windows,*image,XK_Up);
15297 XTranslateImage(display,windows,*image,XK_Down);
15305 if (event.xbutton.window == windows->magnify.id)
15325 MagnifyCommands[] =
15338 Select a magnify factor from the pop-up menu.
15340 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15342 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15346 if (event.xbutton.window == windows->pan.id)
15348 switch (event.xbutton.button)
15355 XTranslateImage(display,windows,*image,XK_Up);
15363 XTranslateImage(display,windows,*image,XK_Down);
15368 XPanImage(display,windows,&event,exception);
15374 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15376 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15379 case ButtonRelease:
15381 if (display_image->debug != MagickFalse)
15382 (void) LogMagickEvent(X11Event,GetMagickModule(),
15383 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15384 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15387 case ClientMessage:
15389 if (display_image->debug != MagickFalse)
15390 (void) LogMagickEvent(X11Event,GetMagickModule(),
15391 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15392 event.xclient.message_type,event.xclient.format,(unsigned long)
15393 event.xclient.data.l[0]);
15394 if (event.xclient.message_type == windows->im_protocols)
15396 if (*event.xclient.data.l == (long) windows->im_update_widget)
15398 (void) CloneString(&windows->command.name,MagickTitle);
15399 windows->command.data=MagickMenus;
15400 (void) XCommandWidget(display,windows,CommandMenu,
15404 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15407 Update graphic context and window colormap.
15409 for (i=0; i < (int) number_windows; i++)
15411 if (magick_windows[i]->id == windows->icon.id)
15413 context_values.background=pixel->background_color.pixel;
15414 context_values.foreground=pixel->foreground_color.pixel;
15415 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15416 context_mask,&context_values);
15417 (void) XChangeGC(display,magick_windows[i]->widget_context,
15418 context_mask,&context_values);
15419 context_values.background=pixel->foreground_color.pixel;
15420 context_values.foreground=pixel->background_color.pixel;
15421 context_values.plane_mask=context_values.background ^
15422 context_values.foreground;
15423 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15424 (size_t) (context_mask | GCPlaneMask),
15426 magick_windows[i]->attributes.background_pixel=
15427 pixel->background_color.pixel;
15428 magick_windows[i]->attributes.border_pixel=
15429 pixel->border_color.pixel;
15430 magick_windows[i]->attributes.colormap=map_info->colormap;
15431 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15432 (unsigned long) magick_windows[i]->mask,
15433 &magick_windows[i]->attributes);
15435 if (windows->pan.mapped != MagickFalse)
15437 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15438 windows->pan.pixmap);
15439 (void) XClearWindow(display,windows->pan.id);
15440 XDrawPanRectangle(display,windows);
15442 if (windows->backdrop.id != (Window) NULL)
15443 (void) XInstallColormap(display,map_info->colormap);
15446 if (*event.xclient.data.l == (long) windows->im_former_image)
15448 *state|=FormerImageState | ExitState;
15451 if (*event.xclient.data.l == (long) windows->im_next_image)
15453 *state|=NextImageState | ExitState;
15456 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15458 *state|=RetainColorsState;
15461 if (*event.xclient.data.l == (long) windows->im_exit)
15468 if (event.xclient.message_type == windows->dnd_protocols)
15486 Display image named by the Drag-and-Drop selection.
15488 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15490 selection=XInternAtom(display,"DndSelection",MagickFalse);
15491 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15492 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15493 &length,&after,&data);
15494 if ((status != Success) || (length == 0))
15496 if (*event.xclient.data.l == 2)
15501 (void) CopyMagickString(resource_info->image_info->filename,
15502 (char *) data,MaxTextExtent);
15509 if (strncmp((char *) data, "file:", 5) != 0)
15511 (void) XFree((void *) data);
15514 (void) CopyMagickString(resource_info->image_info->filename,
15515 ((char *) data)+5,MaxTextExtent);
15517 nexus=ReadImage(resource_info->image_info,exception);
15518 CatchException(exception);
15519 if (nexus != (Image *) NULL)
15520 *state|=NextImageState | ExitState;
15521 (void) XFree((void *) data);
15525 If client window delete message, exit.
15527 if (event.xclient.message_type != windows->wm_protocols)
15529 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15531 (void) XWithdrawWindow(display,event.xclient.window,
15532 visual_info->screen);
15533 if (event.xclient.window == windows->image.id)
15538 if (event.xclient.window == windows->pan.id)
15541 Restore original image size when pan window is deleted.
15543 windows->image.window_changes.width=windows->image.ximage->width;
15544 windows->image.window_changes.height=windows->image.ximage->height;
15545 (void) XConfigureImage(display,resource_info,windows,
15546 display_image,exception);
15550 case ConfigureNotify:
15552 if (display_image->debug != MagickFalse)
15553 (void) LogMagickEvent(X11Event,GetMagickModule(),
15554 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15555 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15556 event.xconfigure.y,event.xconfigure.send_event);
15557 if (event.xconfigure.window == windows->image.id)
15560 Image window has a new configuration.
15562 if (event.xconfigure.send_event != 0)
15568 Position the transient windows relative of the Image window.
15570 if (windows->command.geometry == (char *) NULL)
15571 if (windows->command.mapped == MagickFalse)
15573 windows->command.x=event.xconfigure.x-
15574 windows->command.width-25;
15575 windows->command.y=event.xconfigure.y;
15576 XConstrainWindowPosition(display,&windows->command);
15577 window_changes.x=windows->command.x;
15578 window_changes.y=windows->command.y;
15579 (void) XReconfigureWMWindow(display,windows->command.id,
15580 windows->command.screen,(unsigned int) (CWX | CWY),
15583 if (windows->widget.geometry == (char *) NULL)
15584 if (windows->widget.mapped == MagickFalse)
15586 windows->widget.x=event.xconfigure.x+
15587 event.xconfigure.width/10;
15588 windows->widget.y=event.xconfigure.y+
15589 event.xconfigure.height/10;
15590 XConstrainWindowPosition(display,&windows->widget);
15591 window_changes.x=windows->widget.x;
15592 window_changes.y=windows->widget.y;
15593 (void) XReconfigureWMWindow(display,windows->widget.id,
15594 windows->widget.screen,(unsigned int) (CWX | CWY),
15597 if (windows->magnify.geometry == (char *) NULL)
15598 if (windows->magnify.mapped == MagickFalse)
15600 windows->magnify.x=event.xconfigure.x+
15601 event.xconfigure.width+25;
15602 windows->magnify.y=event.xconfigure.y;
15603 XConstrainWindowPosition(display,&windows->magnify);
15604 window_changes.x=windows->magnify.x;
15605 window_changes.y=windows->magnify.y;
15606 (void) XReconfigureWMWindow(display,windows->magnify.id,
15607 windows->magnify.screen,(unsigned int) (CWX | CWY),
15610 if (windows->pan.geometry == (char *) NULL)
15611 if (windows->pan.mapped == MagickFalse)
15613 windows->pan.x=event.xconfigure.x+
15614 event.xconfigure.width+25;
15615 windows->pan.y=event.xconfigure.y+
15616 windows->magnify.height+50;
15617 XConstrainWindowPosition(display,&windows->pan);
15618 window_changes.x=windows->pan.x;
15619 window_changes.y=windows->pan.y;
15620 (void) XReconfigureWMWindow(display,windows->pan.id,
15621 windows->pan.screen,(unsigned int) (CWX | CWY),
15625 if ((event.xconfigure.width == (int) windows->image.width) &&
15626 (event.xconfigure.height == (int) windows->image.height))
15628 windows->image.width=(unsigned int) event.xconfigure.width;
15629 windows->image.height=(unsigned int) event.xconfigure.height;
15630 windows->image.x=0;
15631 windows->image.y=0;
15632 if (display_image->montage != (char *) NULL)
15634 windows->image.x=vid_info.x;
15635 windows->image.y=vid_info.y;
15637 if ((windows->image.mapped != MagickFalse) &&
15638 (windows->image.stasis != MagickFalse))
15641 Update image window configuration.
15643 windows->image.window_changes.width=event.xconfigure.width;
15644 windows->image.window_changes.height=event.xconfigure.height;
15645 (void) XConfigureImage(display,resource_info,windows,
15646 display_image,exception);
15649 Update pan window configuration.
15651 if ((event.xconfigure.width < windows->image.ximage->width) ||
15652 (event.xconfigure.height < windows->image.ximage->height))
15654 (void) XMapRaised(display,windows->pan.id);
15655 XDrawPanRectangle(display,windows);
15658 if (windows->pan.mapped != MagickFalse)
15659 (void) XWithdrawWindow(display,windows->pan.id,
15660 windows->pan.screen);
15663 if (event.xconfigure.window == windows->magnify.id)
15669 Magnify window has a new configuration.
15671 windows->magnify.width=(unsigned int) event.xconfigure.width;
15672 windows->magnify.height=(unsigned int) event.xconfigure.height;
15673 if (windows->magnify.mapped == MagickFalse)
15676 while ((int) magnify <= event.xconfigure.width)
15678 while ((int) magnify <= event.xconfigure.height)
15681 if (((int) magnify != event.xconfigure.width) ||
15682 ((int) magnify != event.xconfigure.height))
15684 window_changes.width=(int) magnify;
15685 window_changes.height=(int) magnify;
15686 (void) XReconfigureWMWindow(display,windows->magnify.id,
15687 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15691 if ((windows->magnify.mapped != MagickFalse) &&
15692 (windows->magnify.stasis != MagickFalse))
15694 status=XMakeImage(display,resource_info,&windows->magnify,
15695 display_image,windows->magnify.width,windows->magnify.height,
15697 XMakeMagnifyImage(display,windows,exception);
15701 if ((windows->magnify.mapped != MagickFalse) &&
15702 (event.xconfigure.window == windows->pan.id))
15705 Pan icon window has a new configuration.
15707 if (event.xconfigure.send_event != 0)
15709 windows->pan.x=event.xconfigure.x;
15710 windows->pan.y=event.xconfigure.y;
15712 windows->pan.width=(unsigned int) event.xconfigure.width;
15713 windows->pan.height=(unsigned int) event.xconfigure.height;
15716 if (event.xconfigure.window == windows->icon.id)
15719 Icon window has a new configuration.
15721 windows->icon.width=(unsigned int) event.xconfigure.width;
15722 windows->icon.height=(unsigned int) event.xconfigure.height;
15727 case DestroyNotify:
15730 Group leader has exited.
15732 if (display_image->debug != MagickFalse)
15733 (void) LogMagickEvent(X11Event,GetMagickModule(),
15734 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15735 if (event.xdestroywindow.window == windows->group_leader.id)
15745 Selectively install colormap.
15747 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15748 if (event.xcrossing.mode != NotifyUngrab)
15749 XInstallColormap(display,map_info->colormap);
15754 if (display_image->debug != MagickFalse)
15755 (void) LogMagickEvent(X11Event,GetMagickModule(),
15756 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15757 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15760 Refresh windows that are now exposed.
15762 if ((event.xexpose.window == windows->image.id) &&
15763 (windows->image.mapped != MagickFalse))
15765 XRefreshWindow(display,&windows->image,&event);
15766 delay=display_image->delay/MagickMax(
15767 display_image->ticks_per_second,1L);
15768 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15771 if ((event.xexpose.window == windows->magnify.id) &&
15772 (windows->magnify.mapped != MagickFalse))
15774 XMakeMagnifyImage(display,windows,exception);
15777 if (event.xexpose.window == windows->pan.id)
15779 XDrawPanRectangle(display,windows);
15782 if (event.xexpose.window == windows->icon.id)
15784 XRefreshWindow(display,&windows->icon,&event);
15795 Respond to a user key press.
15797 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15798 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15799 *(command+length)='\0';
15800 if (display_image->debug != MagickFalse)
15801 (void) LogMagickEvent(X11Event,GetMagickModule(),
15802 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15803 key_symbol,command);
15804 if (event.xkey.window == windows->image.id)
15806 command_type=XImageWindowCommand(display,resource_info,windows,
15807 event.xkey.state,key_symbol,&display_image,exception);
15808 if (command_type != NullCommand)
15809 nexus=XMagickCommand(display,resource_info,windows,command_type,
15810 &display_image,exception);
15812 if (event.xkey.window == windows->magnify.id)
15813 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15815 if (event.xkey.window == windows->pan.id)
15817 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15818 (void) XWithdrawWindow(display,windows->pan.id,
15819 windows->pan.screen);
15821 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15822 XTextViewWidget(display,resource_info,windows,MagickFalse,
15823 "Help Viewer - Image Pan",ImagePanHelp);
15825 XTranslateImage(display,windows,*image,key_symbol);
15827 delay=display_image->delay/MagickMax(
15828 display_image->ticks_per_second,1L);
15829 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15835 Respond to a user key release.
15837 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15838 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15839 if (display_image->debug != MagickFalse)
15840 (void) LogMagickEvent(X11Event,GetMagickModule(),
15841 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15847 Selectively uninstall colormap.
15849 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15850 if (event.xcrossing.mode != NotifyUngrab)
15851 XUninstallColormap(display,map_info->colormap);
15856 if (display_image->debug != MagickFalse)
15857 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15858 event.xmap.window);
15859 if (event.xmap.window == windows->backdrop.id)
15861 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15863 windows->backdrop.mapped=MagickTrue;
15866 if (event.xmap.window == windows->image.id)
15868 if (windows->backdrop.id != (Window) NULL)
15869 (void) XInstallColormap(display,map_info->colormap);
15870 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15872 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15873 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15875 if (((int) windows->image.width < windows->image.ximage->width) ||
15876 ((int) windows->image.height < windows->image.ximage->height))
15877 (void) XMapRaised(display,windows->pan.id);
15878 windows->image.mapped=MagickTrue;
15881 if (event.xmap.window == windows->magnify.id)
15883 XMakeMagnifyImage(display,windows,exception);
15884 windows->magnify.mapped=MagickTrue;
15885 (void) XWithdrawWindow(display,windows->info.id,
15886 windows->info.screen);
15889 if (event.xmap.window == windows->pan.id)
15891 XMakePanImage(display,resource_info,windows,display_image,
15893 windows->pan.mapped=MagickTrue;
15896 if (event.xmap.window == windows->info.id)
15898 windows->info.mapped=MagickTrue;
15901 if (event.xmap.window == windows->icon.id)
15907 Create an icon image.
15909 taint=display_image->taint;
15910 XMakeStandardColormap(display,icon_visual,icon_resources,
15911 display_image,icon_map,icon_pixel,exception);
15912 (void) XMakeImage(display,icon_resources,&windows->icon,
15913 display_image,windows->icon.width,windows->icon.height,
15915 display_image->taint=taint;
15916 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15917 windows->icon.pixmap);
15918 (void) XClearWindow(display,windows->icon.id);
15919 (void) XWithdrawWindow(display,windows->info.id,
15920 windows->info.screen);
15921 windows->icon.mapped=MagickTrue;
15924 if (event.xmap.window == windows->command.id)
15926 windows->command.mapped=MagickTrue;
15929 if (event.xmap.window == windows->popup.id)
15931 windows->popup.mapped=MagickTrue;
15934 if (event.xmap.window == windows->widget.id)
15936 windows->widget.mapped=MagickTrue;
15941 case MappingNotify:
15943 (void) XRefreshKeyboardMapping(&event.xmapping);
15948 case PropertyNotify:
15964 if (display_image->debug != MagickFalse)
15965 (void) LogMagickEvent(X11Event,GetMagickModule(),
15966 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15967 event.xproperty.atom,event.xproperty.state);
15968 if (event.xproperty.atom != windows->im_remote_command)
15971 Display image named by the remote command protocol.
15973 status=XGetWindowProperty(display,event.xproperty.window,
15974 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15975 AnyPropertyType,&type,&format,&length,&after,&data);
15976 if ((status != Success) || (length == 0))
15978 if (LocaleCompare((char *) data,"-quit") == 0)
15980 XClientMessage(display,windows->image.id,windows->im_protocols,
15981 windows->im_exit,CurrentTime);
15982 (void) XFree((void *) data);
15985 (void) CopyMagickString(resource_info->image_info->filename,
15986 (char *) data,MaxTextExtent);
15987 (void) XFree((void *) data);
15988 nexus=ReadImage(resource_info->image_info,exception);
15989 CatchException(exception);
15990 if (nexus != (Image *) NULL)
15991 *state|=NextImageState | ExitState;
15994 case ReparentNotify:
15996 if (display_image->debug != MagickFalse)
15997 (void) LogMagickEvent(X11Event,GetMagickModule(),
15998 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15999 event.xreparent.window);
16004 if (display_image->debug != MagickFalse)
16005 (void) LogMagickEvent(X11Event,GetMagickModule(),
16006 "Unmap Notify: 0x%lx",event.xunmap.window);
16007 if (event.xunmap.window == windows->backdrop.id)
16009 windows->backdrop.mapped=MagickFalse;
16012 if (event.xunmap.window == windows->image.id)
16014 windows->image.mapped=MagickFalse;
16017 if (event.xunmap.window == windows->magnify.id)
16019 windows->magnify.mapped=MagickFalse;
16022 if (event.xunmap.window == windows->pan.id)
16024 windows->pan.mapped=MagickFalse;
16027 if (event.xunmap.window == windows->info.id)
16029 windows->info.mapped=MagickFalse;
16032 if (event.xunmap.window == windows->icon.id)
16034 if (map_info->colormap == icon_map->colormap)
16035 XConfigureImageColormap(display,resource_info,windows,
16036 display_image,exception);
16037 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16039 windows->icon.mapped=MagickFalse;
16042 if (event.xunmap.window == windows->command.id)
16044 windows->command.mapped=MagickFalse;
16047 if (event.xunmap.window == windows->popup.id)
16049 if (windows->backdrop.id != (Window) NULL)
16050 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16052 windows->popup.mapped=MagickFalse;
16055 if (event.xunmap.window == windows->widget.id)
16057 if (windows->backdrop.id != (Window) NULL)
16058 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16060 windows->widget.mapped=MagickFalse;
16067 if (display_image->debug != MagickFalse)
16068 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16073 } while (!(*state & ExitState));
16074 if ((*state & ExitState) == 0)
16075 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16076 &display_image,exception);
16078 if (resource_info->confirm_edit != MagickFalse)
16081 Query user if image has changed.
16083 if ((resource_info->immutable == MagickFalse) &&
16084 (display_image->taint != MagickFalse))
16089 status=XConfirmWidget(display,windows,"Your image changed.",
16090 "Do you want to save it");
16092 *state&=(~ExitState);
16095 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16096 &display_image,exception);
16099 if ((windows->visual_info->klass == GrayScale) ||
16100 (windows->visual_info->klass == PseudoColor) ||
16101 (windows->visual_info->klass == DirectColor))
16104 Withdraw pan and Magnify window.
16106 if (windows->info.mapped != MagickFalse)
16107 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16108 if (windows->magnify.mapped != MagickFalse)
16109 (void) XWithdrawWindow(display,windows->magnify.id,
16110 windows->magnify.screen);
16111 if (windows->command.mapped != MagickFalse)
16112 (void) XWithdrawWindow(display,windows->command.id,
16113 windows->command.screen);
16115 if (windows->pan.mapped != MagickFalse)
16116 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16117 if (resource_info->backdrop == MagickFalse)
16118 if (windows->backdrop.mapped)
16120 (void) XWithdrawWindow(display,windows->backdrop.id,
16121 windows->backdrop.screen);
16122 (void) XDestroyWindow(display,windows->backdrop.id);
16123 windows->backdrop.id=(Window) NULL;
16124 (void) XWithdrawWindow(display,windows->image.id,
16125 windows->image.screen);
16126 (void) XDestroyWindow(display,windows->image.id);
16127 windows->image.id=(Window) NULL;
16129 XSetCursorState(display,windows,MagickTrue);
16130 XCheckRefreshWindows(display,windows);
16131 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16132 *state&=(~ExitState);
16133 if (*state & ExitState)
16136 Free Standard Colormap.
16138 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16139 if (resource_info->map_type == (char *) NULL)
16140 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16144 if (resource_info->copy_image != (Image *) NULL)
16146 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16147 resource_info->copy_image=NewImageList();
16149 DestroyXResources();
16151 (void) XSync(display,MagickFalse);
16153 Restore our progress monitor and warning handlers.
16155 (void) SetErrorHandler(warning_handler);
16156 (void) SetWarningHandler(warning_handler);
16158 Change to home directory.
16160 directory=getcwd(working_directory,MaxTextExtent);
16166 status=chdir(resource_info->home_directory);
16168 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16169 "UnableToOpenFile","%s",resource_info->home_directory);
16171 *image=display_image;
16177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16181 + D i s p l a y I m a g e s %
16185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16187 % DisplayImages() displays an image sequence to any X window screen. It
16188 % returns a value other than 0 if successful. Check the exception member
16189 % of image to determine the reason for any failure.
16191 % The format of the DisplayImages method is:
16193 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16194 % Image *images,ExceptionInfo *exception)
16196 % A description of each parameter follows:
16198 % o image_info: the image info.
16200 % o image: the image.
16202 % o exception: return any errors or warnings in this structure.
16205 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16206 Image *image,ExceptionInfo *exception)
16208 assert(image_info != (const ImageInfo *) NULL);
16209 assert(image_info->signature == MagickSignature);
16210 assert(image != (Image *) NULL);
16211 assert(image->signature == MagickSignature);
16212 if (image->debug != MagickFalse)
16213 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16214 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16215 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
16216 return(MagickFalse);
16220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16224 + R e m o t e D i s p l a y C o m m a n d %
16228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16230 % RemoteDisplayCommand() encourages a remote display program to display the
16231 % specified image filename.
16233 % The format of the RemoteDisplayCommand method is:
16235 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16236 % const char *window,const char *filename,ExceptionInfo *exception)
16238 % A description of each parameter follows:
16240 % o image_info: the image info.
16242 % o window: Specifies the name or id of an X window.
16244 % o filename: the name of the image filename to display.
16246 % o exception: return any errors or warnings in this structure.
16249 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16250 const char *window,const char *filename,ExceptionInfo *exception)
16252 assert(image_info != (const ImageInfo *) NULL);
16253 assert(image_info->signature == MagickSignature);
16254 assert(filename != (char *) NULL);
16256 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16257 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16258 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename);
16259 return(MagickFalse);