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/client.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/colorspace.h"
49 #include "MagickCore/composite.h"
50 #include "MagickCore/constitute.h"
51 #include "MagickCore/decorate.h"
52 #include "MagickCore/delegate.h"
53 #include "MagickCore/display.h"
54 #include "MagickCore/display-private.h"
55 #include "MagickCore/draw.h"
56 #include "MagickCore/effect.h"
57 #include "MagickCore/enhance.h"
58 #include "MagickCore/exception.h"
59 #include "MagickCore/exception-private.h"
60 #include "MagickCore/fx.h"
61 #include "MagickCore/geometry.h"
62 #include "MagickCore/image.h"
63 #include "MagickCore/image-private.h"
64 #include "MagickCore/list.h"
65 #include "MagickCore/log.h"
66 #include "MagickCore/magick.h"
67 #include "MagickCore/memory_.h"
68 #include "MagickCore/monitor.h"
69 #include "MagickCore/monitor-private.h"
70 #include "MagickCore/montage.h"
71 #include "MagickCore/option.h"
72 #include "MagickCore/paint.h"
73 #include "MagickCore/pixel.h"
74 #include "MagickCore/pixel-accessor.h"
75 #include "MagickCore/PreRvIcccm.h"
76 #include "MagickCore/property.h"
77 #include "MagickCore/quantum.h"
78 #include "MagickCore/quantum-private.h"
79 #include "MagickCore/resize.h"
80 #include "MagickCore/resource_.h"
81 #include "MagickCore/shear.h"
82 #include "MagickCore/segment.h"
83 #include "MagickCore/string_.h"
84 #include "MagickCore/string-private.h"
85 #include "MagickCore/transform.h"
86 #include "MagickCore/threshold.h"
87 #include "MagickCore/utility.h"
88 #include "MagickCore/utility-private.h"
89 #include "MagickCore/version.h"
90 #include "MagickCore/widget.h"
91 #include "MagickCore/widget-private.h"
92 #include "MagickCore/xwindow.h"
93 #include "MagickCore/xwindow-private.h"
95 #if defined(MAGICKCORE_X11_DELEGATE)
99 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
102 Constant declarations.
104 static const unsigned char
107 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
111 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
139 Help widget declarations.
142 *ImageAnnotateHelp[] =
144 "In annotate mode, the Command widget has these options:",
194 "Choose a font name from the Font Name sub-menu. Additional",
195 "font names can be specified with the font browser. You can",
196 "change the menu names by setting the X resources font1",
199 "Choose a font color from the Font Color sub-menu.",
200 "Additional font colors can be specified with the color",
201 "browser. You can change the menu colors by setting the X",
202 "resources pen1 through pen9.",
204 "If you select the color browser and press Grab, you can",
205 "choose the font color by moving the pointer to the desired",
206 "color on the screen and press any button.",
208 "If you choose to rotate the text, choose Rotate Text from the",
209 "menu and select an angle. Typically you will only want to",
210 "rotate one line of text at a time. Depending on the angle you",
211 "choose, subsequent lines may end up overwriting each other.",
213 "Choosing a font and its color is optional. The default font",
214 "is fixed and the default color is black. However, you must",
215 "choose a location to begin entering text and press button 1.",
216 "An underscore character will appear at the location of the",
217 "pointer. The cursor changes to a pencil to indicate you are",
218 "in text mode. To exit immediately, press Dismiss.",
220 "In text mode, any key presses will display the character at",
221 "the location of the underscore and advance the underscore",
222 "cursor. Enter your text and once completed press Apply to",
223 "finish your image annotation. To correct errors press BACK",
224 "SPACE. To delete an entire line of text, press DELETE. Any",
225 "text that exceeds the boundaries of the image window is",
226 "automagically continued onto the next line.",
228 "The actual color you request for the font is saved in the",
229 "image. However, the color that appears in your image window",
230 "may be different. For example, on a monochrome screen the",
231 "text will appear black or white even if you choose the color",
232 "red as the font color. However, the image saved to a file",
233 "with -write is written with red lettering. To assure the",
234 "correct color text in the final image, any PseudoClass image",
235 "is promoted to DirectClass (see miff(5)). To force a",
236 "PseudoClass image to remain PseudoClass, use -colors.",
241 "In chop mode, the Command widget has these options:",
249 "If the you choose the horizontal direction (this the",
250 "default), the area of the image between the two horizontal",
251 "endpoints of the chop line is removed. Otherwise, the area",
252 "of the image between the two vertical endpoints of the chop",
255 "Select a location within the image window to begin your chop,",
256 "press and hold any button. Next, move the pointer to",
257 "another location in the image. As you move a line will",
258 "connect the initial location and the pointer. When you",
259 "release the button, the area within the image to chop is",
260 "determined by which direction you choose from the Command",
263 "To cancel the image chopping, move the pointer back to the",
264 "starting point of the line and release the button.",
267 *ImageColorEditHelp[] =
269 "In color edit mode, the Command widget has these options:",
310 "Choose a color editing method from the Method sub-menu",
311 "of the Command widget. The point method recolors any pixel",
312 "selected with the pointer until the button is released. The",
313 "replace method recolors any pixel that matches the color of",
314 "the pixel you select with a button press. Floodfill recolors",
315 "any pixel that matches the color of the pixel you select with",
316 "a button press and is a neighbor. Whereas filltoborder recolors",
317 "any neighbor pixel that is not the border color. Finally reset",
318 "changes the entire image to the designated color.",
320 "Next, choose a pixel color from the Pixel Color sub-menu.",
321 "Additional pixel colors can be specified with the color",
322 "browser. You can change the menu colors by setting the X",
323 "resources pen1 through pen9.",
325 "Now press button 1 to select a pixel within the image window",
326 "to change its color. Additional pixels may be recolored as",
327 "prescribed by the method you choose.",
329 "If the Magnify widget is mapped, it can be helpful in positioning",
330 "your pointer within the image (refer to button 2).",
332 "The actual color you request for the pixels is saved in the",
333 "image. However, the color that appears in your image window",
334 "may be different. For example, on a monochrome screen the",
335 "pixel will appear black or white even if you choose the",
336 "color red as the pixel color. However, the image saved to a",
337 "file with -write is written with red pixels. To assure the",
338 "correct color text in the final image, any PseudoClass image",
339 "is promoted to DirectClass (see miff(5)). To force a",
340 "PseudoClass image to remain PseudoClass, use -colors.",
343 *ImageCompositeHelp[] =
345 "First a widget window is displayed requesting you to enter an",
346 "image name. Press Composite, Grab or type a file name.",
347 "Press Cancel if you choose not to create a composite image.",
348 "When you choose Grab, move the pointer to the desired window",
349 "and press any button.",
351 "If the Composite image does not have any matte information,",
352 "you are informed and the file browser is displayed again.",
353 "Enter the name of a mask image. The image is typically",
354 "grayscale and the same size as the composite image. If the",
355 "image is not grayscale, it is converted to grayscale and the",
356 "resulting intensities are used as matte information.",
358 "A small window appears showing the location of the cursor in",
359 "the image window. You are now in composite mode. To exit",
360 "immediately, press Dismiss. In composite mode, the Command",
361 "widget has these options:",
387 "Choose a composite operation from the Operators sub-menu of",
388 "the Command widget. How each operator behaves is described",
389 "below. Image window is the image currently displayed on",
390 "your X server and image is the image obtained with the File",
393 "Over The result is the union of the two image shapes,",
394 " with image obscuring image window in the region of",
397 "In The result is simply image cut by the shape of",
398 " image window. None of the image data of image",
399 " window is in the result.",
401 "Out The resulting image is image with the shape of",
402 " image window cut out.",
404 "Atop The result is the same shape as image image window,",
405 " with image obscuring image window where the image",
406 " shapes overlap. Note this differs from over",
407 " because the portion of image outside image window's",
408 " shape does not appear in the result.",
410 "Xor The result is the image data from both image and",
411 " image window that is outside the overlap region.",
412 " The overlap region is blank.",
414 "Plus The result is just the sum of the image data.",
415 " Output values are cropped to QuantumRange (no overflow).",
417 "Minus The result of image - image window, with underflow",
420 "Add The result of image + image window, with overflow",
421 " wrapping around (mod 256).",
423 "Subtract The result of image - image window, with underflow",
424 " wrapping around (mod 256). The add and subtract",
425 " operators can be used to perform reversible",
429 " The result of abs(image - image window). This",
430 " useful for comparing two very similar images.",
433 " The result of image * image window. This",
434 " useful for the creation of drop-shadows.",
436 "Bumpmap The result of surface normals from image * image",
439 "Copy The resulting image is image window replaced with",
440 " image. Here the matte information is ignored.",
442 "CopyRed The red layer of the image window is replace with",
443 " the red layer of the image. The other layers are",
447 " The green layer of the image window is replace with",
448 " the green layer of the image. The other layers are",
451 "CopyBlue The blue layer of the image window is replace with",
452 " the blue layer of the image. The other layers are",
456 " The matte layer of the image window is replace with",
457 " the matte layer of the image. The other layers are",
460 "The image compositor requires a matte, or alpha channel in",
461 "the image for some operations. This extra channel usually",
462 "defines a mask which represents a sort of a cookie-cutter",
463 "for the image. This the case when matte is opaque (full",
464 "coverage) for pixels inside the shape, zero outside, and",
465 "between 0 and QuantumRange on the boundary. If image does not",
466 "have a matte channel, it is initialized with 0 for any pixel",
467 "matching in color to pixel location (0,0), otherwise QuantumRange.",
469 "If you choose Dissolve, the composite operator becomes Over. The",
470 "image matte channel percent transparency is initialized to factor.",
471 "The image window is initialized to (100-factor). Where factor is the",
472 "value you specify in the Dialog widget.",
474 "Displace shifts the image pixels as defined by a displacement",
475 "map. With this option, image is used as a displacement map.",
476 "Black, within the displacement map, is a maximum positive",
477 "displacement. White is a maximum negative displacement and",
478 "middle gray is neutral. The displacement is scaled to determine",
479 "the pixel shift. By default, the displacement applies in both the",
480 "horizontal and vertical directions. However, if you specify a mask,",
481 "image is the horizontal X displacement and mask the vertical Y",
484 "Note that matte information for image window is not retained",
485 "for colormapped X server visuals (e.g. StaticColor,",
486 "StaticColor, GrayScale, PseudoColor). Correct compositing",
487 "behavior may require a TrueColor or DirectColor visual or a",
488 "Standard Colormap.",
490 "Choosing a composite operator is optional. The default",
491 "operator is replace. However, you must choose a location to",
492 "composite your image and press button 1. Press and hold the",
493 "button before releasing and an outline of the image will",
494 "appear to help you identify your location.",
496 "The actual colors of the composite image is saved. However,",
497 "the color that appears in image window may be different.",
498 "For example, on a monochrome screen image window will appear",
499 "black or white even though your composited image may have",
500 "many colors. If the image is saved to a file it is written",
501 "with the correct colors. To assure the correct colors are",
502 "saved in the final image, any PseudoClass image is promoted",
503 "to DirectClass (see miff(5)). To force a PseudoClass image",
504 "to remain PseudoClass, use -colors.",
509 "In cut mode, the Command widget has these options:",
514 "To define a cut region, press button 1 and drag. The",
515 "cut region is defined by a highlighted rectangle that",
516 "expands or contracts as it follows the pointer. Once you",
517 "are satisfied with the cut region, release the button.",
518 "You are now in rectify mode. In rectify mode, the Command",
519 "widget has these options:",
525 "You can make adjustments by moving the pointer to one of the",
526 "cut rectangle corners, pressing a button, and dragging.",
527 "Finally, press Cut to commit your copy region. To",
528 "exit without cutting the image, press Dismiss.",
533 "In copy mode, the Command widget has these options:",
538 "To define a copy region, press button 1 and drag. The",
539 "copy region is defined by a highlighted rectangle that",
540 "expands or contracts as it follows the pointer. Once you",
541 "are satisfied with the copy region, release the button.",
542 "You are now in rectify mode. In rectify mode, the Command",
543 "widget has these options:",
549 "You can make adjustments by moving the pointer to one of the",
550 "copy rectangle corners, pressing a button, and dragging.",
551 "Finally, press Copy to commit your copy region. To",
552 "exit without copying the image, press Dismiss.",
557 "In crop mode, the Command widget has these options:",
562 "To define a cropping region, press button 1 and drag. The",
563 "cropping region is defined by a highlighted rectangle that",
564 "expands or contracts as it follows the pointer. Once you",
565 "are satisfied with the cropping region, release the button.",
566 "You are now in rectify mode. In rectify mode, the Command",
567 "widget has these options:",
573 "You can make adjustments by moving the pointer to one of the",
574 "cropping rectangle corners, pressing a button, and dragging.",
575 "Finally, press Crop to commit your cropping region. To",
576 "exit without cropping the image, press Dismiss.",
581 "The cursor changes to a crosshair to indicate you are in",
582 "draw mode. To exit immediately, press Dismiss. In draw mode,",
583 "the Command widget has these options:",
628 "Choose a drawing primitive from the Element sub-menu.",
630 "Choose a color from the Color sub-menu. Additional",
631 "colors can be specified with the color browser.",
633 "If you choose the color browser and press Grab, you can",
634 "select the color by moving the pointer to the desired",
635 "color on the screen and press any button. The transparent",
636 "color updates the image matte channel and is useful for",
637 "image compositing.",
639 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
640 "Additional stipples can be specified with the file browser.",
641 "Stipples obtained from the file browser must be on disk in the",
642 "X11 bitmap format.",
644 "Choose a width, if appropriate, from the Width sub-menu. To",
645 "choose a specific width select the Dialog widget.",
647 "Choose a point in the Image window and press button 1 and",
648 "hold. Next, move the pointer to another location in the",
649 "image. As you move, a line connects the initial location and",
650 "the pointer. When you release the button, the image is",
651 "updated with the primitive you just drew. For polygons, the",
652 "image is updated when you press and release the button without",
653 "moving the pointer.",
655 "To cancel image drawing, move the pointer back to the",
656 "starting point of the line and release the button.",
662 " The effects of each button press is described below. Three",
663 " buttons are required. If you have a two button mouse,",
664 " button 1 and 3 are returned. Press ALT and button 3 to",
665 " simulate button 2.",
667 " 1 Press this button to map or unmap the Command widget.",
669 " 2 Press and drag to define a region of the image to",
672 " 3 Press and drag to choose from a select set of commands.",
673 " This button behaves differently if the image being",
674 " displayed is a visual image directory. Here, choose a",
675 " particular tile of the directory and press this button and",
676 " drag to select a command from a pop-up menu. Choose from",
677 " these menu items:",
685 " If you choose Open, the image represented by the tile is",
686 " displayed. To return to the visual image directory, choose",
687 " Next from the Command widget. Next and Former moves to the",
688 " next or former image respectively. Choose Delete to delete",
689 " a particular image tile. Finally, choose Update to",
690 " synchronize all the image tiles with their respective",
694 " The Command widget lists a number of sub-menus and commands.",
706 " Visual Directory...",
740 " Contrast Stretch...",
741 " Sigmoidal Contrast...",
769 " Charcoal Drawing...",
780 " Region of Interest...",
792 " Browse Documentation",
795 " Menu items with a indented triangle have a sub-menu. They",
796 " are represented above as the indented items. To access a",
797 " sub-menu item, move the pointer to the appropriate menu and",
798 " press a button and drag. When you find the desired sub-menu",
799 " item, release the button and the command is executed. Move",
800 " the pointer away from the sub-menu if you decide not to",
801 " execute a particular command.",
803 "KEYBOARD ACCELERATORS",
804 " Accelerators are one or two key presses that effect a",
805 " particular command. The keyboard accelerators that",
806 " display(1) understands is:",
808 " Ctl+O Press to open an image from a file.",
810 " space Press to display the next image.",
812 " If the image is a multi-paged document such as a Postscript",
813 " document, you can skip ahead several pages by preceding",
814 " this command with a number. For example to display the",
815 " third page beyond the current page, press 3<space>.",
817 " backspace Press to display the former image.",
819 " If the image is a multi-paged document such as a Postscript",
820 " document, you can skip behind several pages by preceding",
821 " this command with a number. For example to display the",
822 " third page preceding the current page, press 3<backspace>.",
824 " Ctl+S Press to write the image to a file.",
826 " Ctl+P Press to print the image to a Postscript printer.",
828 " Ctl+D Press to delete an image file.",
830 " Ctl+N Press to create a blank canvas.",
832 " Ctl+Q Press to discard all images and exit program.",
834 " Ctl+Z Press to undo last image transformation.",
836 " Ctl+R Press to redo last image transformation.",
838 " Ctl+X Press to cut a region of the image.",
840 " Ctl+C Press to copy a region of the image.",
842 " Ctl+V Press to paste a region to the image.",
844 " < Press to half the image size.",
846 " - Press to return to the original image size.",
848 " > Press to double the image size.",
850 " % Press to resize the image to a width and height you",
853 "Cmd-A Press to make any image transformations permanent."
855 " By default, any image size transformations are applied",
856 " to the original image to create the image displayed on",
857 " the X server. However, the transformations are not",
858 " permanent (i.e. the original image does not change",
859 " size only the X image does). For example, if you",
860 " press > the X image will appear to double in size,",
861 " but the original image will in fact remain the same size.",
862 " To force the original image to double in size, press >",
863 " followed by Cmd-A.",
865 " @ Press to refresh the image window.",
867 " C Press to cut out a rectangular region of the image.",
869 " [ Press to chop the image.",
871 " H Press to flop image in the horizontal direction.",
873 " V Press to flip image in the vertical direction.",
875 " / Press to rotate the image 90 degrees clockwise.",
877 " \\ Press to rotate the image 90 degrees counter-clockwise.",
879 " * Press to rotate the image the number of degrees you",
882 " S Press to shear the image the number of degrees you",
885 " R Press to roll the image.",
887 " T Press to trim the image edges.",
889 " Shft-H Press to vary the image hue.",
891 " Shft-S Press to vary the color saturation.",
893 " Shft-L Press to vary the color brightness.",
895 " Shft-G Press to gamma correct the image.",
897 " Shft-C Press to sharpen the image contrast.",
899 " Shft-Z Press to dull the image contrast.",
901 " = Press to perform histogram equalization on the image.",
903 " Shft-N Press to perform histogram normalization on the image.",
905 " Shft-~ Press to negate the colors of the image.",
907 " . Press to convert the image colors to gray.",
909 " Shft-# Press to set the maximum number of unique colors in the",
912 " F2 Press to reduce the speckles in an image.",
914 " F3 Press to eliminate peak noise from an image.",
916 " F4 Press to add noise to an image.",
918 " F5 Press to sharpen an image.",
920 " F6 Press to delete an image file.",
922 " F7 Press to threshold the image.",
924 " F8 Press to detect edges within an image.",
926 " F9 Press to emboss an image.",
928 " F10 Press to displace pixels by a random amount.",
930 " F11 Press to negate all pixels above the threshold level.",
932 " F12 Press to shade the image using a distant light source.",
934 " F13 Press to lighten or darken image edges to create a 3-D effect.",
936 " F14 Press to segment the image by color.",
938 " Meta-S Press to swirl image pixels about the center.",
940 " Meta-I Press to implode image pixels about the center.",
942 " Meta-W Press to alter an image along a sine wave.",
944 " Meta-P Press to simulate an oil painting.",
946 " Meta-C Press to simulate a charcoal drawing.",
948 " Alt-A Press to annotate the image with text.",
950 " Alt-D Press to draw on an image.",
952 " Alt-P Press to edit an image pixel color.",
954 " Alt-M Press to edit the image matte information.",
956 " Alt-V Press to composite the image with another.",
958 " Alt-B Press to add a border to the image.",
960 " Alt-F Press to add an ornamental border to the image.",
963 " Press to add an image comment.",
965 " Ctl-A Press to apply image processing techniques to a region",
968 " Shft-? Press to display information about the image.",
970 " Shft-+ Press to map the zoom image window.",
972 " Shft-P Press to preview an image enhancement, effect, or f/x.",
974 " F1 Press to display helpful information about display(1).",
976 " Find Press to browse documentation about ImageMagick.",
978 " 1-9 Press to change the level of magnification.",
980 " Use the arrow keys to move the image one pixel up, down,",
981 " left, or right within the magnify window. Be sure to first",
982 " map the magnify window by pressing button 2.",
984 " Press ALT and one of the arrow keys to trim off one pixel",
985 " from any side of the image.",
988 *ImageMatteEditHelp[] =
990 "Matte information within an image is useful for some",
991 "operations such as image compositing (See IMAGE",
992 "COMPOSITING). This extra channel usually defines a mask",
993 "which represents a sort of a cookie-cutter for the image.",
994 "This the case when matte is opaque (full coverage) for",
995 "pixels inside the shape, zero outside, and between 0 and",
996 "QuantumRange on the boundary.",
998 "A small window appears showing the location of the cursor in",
999 "the image window. You are now in matte edit mode. To exit",
1000 "immediately, press Dismiss. In matte edit mode, the Command",
1001 "widget has these options:",
1035 "Choose a matte editing method from the Method sub-menu of",
1036 "the Command widget. The point method changes the matte value",
1037 "of any pixel selected with the pointer until the button is",
1038 "is released. The replace method changes the matte value of",
1039 "any pixel that matches the color of the pixel you select with",
1040 "a button press. Floodfill changes the matte value of any pixel",
1041 "that matches the color of the pixel you select with a button",
1042 "press and is a neighbor. Whereas filltoborder changes the matte",
1043 "value any neighbor pixel that is not the border color. Finally",
1044 "reset changes the entire image to the designated matte value.",
1046 "Choose Matte Value and pick Opaque or Transarent. For other values",
1047 "select the Dialog entry. Here a dialog appears requesting a matte",
1048 "value. The value you select is assigned as the opacity value of the",
1049 "selected pixel or pixels.",
1051 "Now, press any button to select a pixel within the image",
1052 "window to change its matte value.",
1054 "If the Magnify widget is mapped, it can be helpful in positioning",
1055 "your pointer within the image (refer to button 2).",
1057 "Matte information is only valid in a DirectClass image.",
1058 "Therefore, any PseudoClass image is promoted to DirectClass",
1059 "(see miff(5)). Note that matte information for PseudoClass",
1060 "is not retained for colormapped X server visuals (e.g.",
1061 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1062 "immediately save your image to a file (refer to Write).",
1063 "Correct matte editing behavior may require a TrueColor or",
1064 "DirectColor visual or a Standard Colormap.",
1069 "When an image exceeds the width or height of the X server",
1070 "screen, display maps a small panning icon. The rectangle",
1071 "within the panning icon shows the area that is currently",
1072 "displayed in the image window. To pan about the image,",
1073 "press any button and drag the pointer within the panning",
1074 "icon. The pan rectangle moves with the pointer and the",
1075 "image window is updated to reflect the location of the",
1076 "rectangle within the panning icon. When you have selected",
1077 "the area of the image you wish to view, release the button.",
1079 "Use the arrow keys to pan the image one pixel up, down,",
1080 "left, or right within the image window.",
1082 "The panning icon is withdrawn if the image becomes smaller",
1083 "than the dimensions of the X server screen.",
1088 "A small window appears showing the location of the cursor in",
1089 "the image window. You are now in paste mode. To exit",
1090 "immediately, press Dismiss. In paste mode, the Command",
1091 "widget has these options:",
1108 "Choose a composite operation from the Operators sub-menu of",
1109 "the Command widget. How each operator behaves is described",
1110 "below. Image window is the image currently displayed on",
1111 "your X server and image is the image obtained with the File",
1114 "Over The result is the union of the two image shapes,",
1115 " with image obscuring image window in the region of",
1118 "In The result is simply image cut by the shape of",
1119 " image window. None of the image data of image",
1120 " window is in the result.",
1122 "Out The resulting image is image with the shape of",
1123 " image window cut out.",
1125 "Atop The result is the same shape as image image window,",
1126 " with image obscuring image window where the image",
1127 " shapes overlap. Note this differs from over",
1128 " because the portion of image outside image window's",
1129 " shape does not appear in the result.",
1131 "Xor The result is the image data from both image and",
1132 " image window that is outside the overlap region.",
1133 " The overlap region is blank.",
1135 "Plus The result is just the sum of the image data.",
1136 " Output values are cropped to QuantumRange (no overflow).",
1137 " This operation is independent of the matte",
1140 "Minus The result of image - image window, with underflow",
1141 " cropped to zero.",
1143 "Add The result of image + image window, with overflow",
1144 " wrapping around (mod 256).",
1146 "Subtract The result of image - image window, with underflow",
1147 " wrapping around (mod 256). The add and subtract",
1148 " operators can be used to perform reversible",
1149 " transformations.",
1152 " The result of abs(image - image window). This",
1153 " useful for comparing two very similar images.",
1155 "Copy The resulting image is image window replaced with",
1156 " image. Here the matte information is ignored.",
1158 "CopyRed The red layer of the image window is replace with",
1159 " the red layer of the image. The other layers are",
1163 " The green layer of the image window is replace with",
1164 " the green layer of the image. The other layers are",
1167 "CopyBlue The blue layer of the image window is replace with",
1168 " the blue layer of the image. The other layers are",
1172 " The matte layer of the image window is replace with",
1173 " the matte layer of the image. The other layers are",
1176 "The image compositor requires a matte, or alpha channel in",
1177 "the image for some operations. This extra channel usually",
1178 "defines a mask which represents a sort of a cookie-cutter",
1179 "for the image. This the case when matte is opaque (full",
1180 "coverage) for pixels inside the shape, zero outside, and",
1181 "between 0 and QuantumRange on the boundary. If image does not",
1182 "have a matte channel, it is initialized with 0 for any pixel",
1183 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1185 "Note that matte information for image window is not retained",
1186 "for colormapped X server visuals (e.g. StaticColor,",
1187 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1188 "behavior may require a TrueColor or DirectColor visual or a",
1189 "Standard Colormap.",
1191 "Choosing a composite operator is optional. The default",
1192 "operator is replace. However, you must choose a location to",
1193 "paste your image and press button 1. Press and hold the",
1194 "button before releasing and an outline of the image will",
1195 "appear to help you identify your location.",
1197 "The actual colors of the pasted image is saved. However,",
1198 "the color that appears in image window may be different.",
1199 "For example, on a monochrome screen image window will appear",
1200 "black or white even though your pasted image may have",
1201 "many colors. If the image is saved to a file it is written",
1202 "with the correct colors. To assure the correct colors are",
1203 "saved in the final image, any PseudoClass image is promoted",
1204 "to DirectClass (see miff(5)). To force a PseudoClass image",
1205 "to remain PseudoClass, use -colors.",
1210 "In region of interest mode, the Command widget has these",
1216 "To define a region of interest, press button 1 and drag.",
1217 "The region of interest is defined by a highlighted rectangle",
1218 "that expands or contracts as it follows the pointer. Once",
1219 "you are satisfied with the region of interest, release the",
1220 "button. You are now in apply mode. In apply mode the",
1221 "Command widget has these options:",
1241 " Contrast Stretch",
1242 " Sigmoidal Contrast...",
1269 " Charcoal Drawing...",
1279 "You can make adjustments to the region of interest by moving",
1280 "the pointer to one of the rectangle corners, pressing a",
1281 "button, and dragging. Finally, choose an image processing",
1282 "technique from the Command widget. You can choose more than",
1283 "one image processing technique to apply to an area.",
1284 "Alternatively, you can move the region of interest before",
1285 "applying another image processing technique. To exit, press",
1289 *ImageRotateHelp[] =
1291 "In rotate mode, the Command widget has these options:",
1310 "Choose a background color from the Pixel Color sub-menu.",
1311 "Additional background colors can be specified with the color",
1312 "browser. You can change the menu colors by setting the X",
1313 "resources pen1 through pen9.",
1315 "If you choose the color browser and press Grab, you can",
1316 "select the background color by moving the pointer to the",
1317 "desired color on the screen and press any button.",
1319 "Choose a point in the image window and press this button and",
1320 "hold. Next, move the pointer to another location in the",
1321 "image. As you move a line connects the initial location and",
1322 "the pointer. When you release the button, the degree of",
1323 "image rotation is determined by the slope of the line you",
1324 "just drew. The slope is relative to the direction you",
1325 "choose from the Direction sub-menu of the Command widget.",
1327 "To cancel the image rotation, move the pointer back to the",
1328 "starting point of the line and release the button.",
1333 Enumeration declarations.
1352 VisualDirectoryCommand,
1360 OriginalSizeCommand,
1382 ContrastStretchCommand,
1383 SigmoidalContrastCommand,
1409 CharcoalDrawCommand,
1419 RegionofInterestCommand,
1425 ShowHistogramCommand,
1431 BrowseDocumentationCommand,
1433 SaveToUndoBufferCommand,
1440 AnnotateNameCommand,
1441 AnnotateFontColorCommand,
1442 AnnotateBackgroundColorCommand,
1443 AnnotateRotateCommand,
1444 AnnotateHelpCommand,
1445 AnnotateDismissCommand,
1448 ChopDirectionCommand,
1451 HorizontalChopCommand,
1452 VerticalChopCommand,
1453 ColorEditMethodCommand,
1454 ColorEditColorCommand,
1455 ColorEditBorderCommand,
1456 ColorEditFuzzCommand,
1457 ColorEditUndoCommand,
1458 ColorEditHelpCommand,
1459 ColorEditDismissCommand,
1460 CompositeOperatorsCommand,
1461 CompositeDissolveCommand,
1462 CompositeDisplaceCommand,
1463 CompositeHelpCommand,
1464 CompositeDismissCommand,
1469 RectifyDismissCommand,
1478 MatteEditBorderCommand,
1479 MatteEditFuzzCommand,
1480 MatteEditValueCommand,
1481 MatteEditUndoCommand,
1482 MatteEditHelpCommand,
1483 MatteEditDismissCommand,
1484 PasteOperatorsCommand,
1486 PasteDismissCommand,
1488 RotateDirectionCommand,
1490 RotateSharpenCommand,
1492 RotateDismissCommand,
1493 HorizontalRotateCommand,
1494 VerticalRotateCommand,
1505 #define BricksWidth 20
1506 #define BricksHeight 20
1507 #define DiagonalWidth 16
1508 #define DiagonalHeight 16
1509 #define HighlightWidth 8
1510 #define HighlightHeight 8
1511 #define OpaqueWidth 8
1512 #define OpaqueHeight 8
1513 #define ScalesWidth 16
1514 #define ScalesHeight 16
1515 #define ShadowWidth 8
1516 #define ShadowHeight 8
1517 #define VerticalWidth 16
1518 #define VerticalHeight 16
1519 #define WavyWidth 16
1520 #define WavyHeight 16
1523 Constant declaration.
1528 static const unsigned char
1531 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1532 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1533 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1534 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1535 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1539 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1540 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1541 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1545 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1546 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1547 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1551 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1552 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1553 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1557 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1558 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1559 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1563 Function prototypes.
1566 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1567 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1570 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1571 Image **,ExceptionInfo *),
1572 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1573 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1575 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1578 static MagickBooleanType
1579 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1581 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1583 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1585 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1587 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1589 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1591 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1592 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1594 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1596 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1597 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1598 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1600 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1601 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1602 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1605 XDrawPanRectangle(Display *,XWindows *),
1606 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1608 XMagnifyImage(Display *,XWindows *,XEvent *),
1609 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1610 XPanImage(Display *,XWindows *,XEvent *),
1611 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1613 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1614 XScreenEvent(Display *,XWindows *,XEvent *),
1615 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622 % D i s p l a y I m a g e s %
1626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628 % DisplayImages() displays an image sequence to any X window screen. It
1629 % returns a value other than 0 if successful. Check the exception member
1630 % of image to determine the reason for any failure.
1632 % The format of the DisplayImages method is:
1634 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1635 % Image *images,ExceptionInfo *exception)
1637 % A description of each parameter follows:
1639 % o image_info: the image info.
1641 % o image: the image.
1643 % o exception: return any errors or warnings in this structure.
1646 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1647 Image *images,ExceptionInfo *exception)
1670 assert(image_info != (const ImageInfo *) NULL);
1671 assert(image_info->signature == MagickSignature);
1672 assert(images != (Image *) NULL);
1673 assert(images->signature == MagickSignature);
1674 if (images->debug != MagickFalse)
1675 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1676 display=XOpenDisplay(image_info->server_name);
1677 if (display == (Display *) NULL)
1679 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1680 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1681 return(MagickFalse);
1683 if (exception->severity != UndefinedException)
1684 CatchException(exception);
1685 (void) XSetErrorHandler(XError);
1686 resource_database=XGetResourceDatabase(display,GetClientName());
1687 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1688 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1689 if (image_info->page != (char *) NULL)
1690 resource_info.image_geometry=AcquireString(image_info->page);
1691 resource_info.immutable=MagickTrue;
1692 argv[0]=AcquireString(GetClientName());
1694 for (i=0; (state & ExitState) == 0; i++)
1696 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1698 image=GetImageFromList(images,i % GetImageListLength(images));
1699 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1701 SetErrorHandler((ErrorHandler) NULL);
1702 SetWarningHandler((WarningHandler) NULL);
1703 argv[0]=DestroyString(argv[0]);
1704 (void) XCloseDisplay(display);
1705 XDestroyResourceInfo(&resource_info);
1706 if (exception->severity != UndefinedException)
1707 return(MagickFalse);
1712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1716 % R e m o t e D i s p l a y C o m m a n d %
1720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1722 % RemoteDisplayCommand() encourages a remote display program to display the
1723 % specified image filename.
1725 % The format of the RemoteDisplayCommand method is:
1727 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1728 % const char *window,const char *filename,ExceptionInfo *exception)
1730 % A description of each parameter follows:
1732 % o image_info: the image info.
1734 % o window: Specifies the name or id of an X window.
1736 % o filename: the name of the image filename to display.
1738 % o exception: return any errors or warnings in this structure.
1741 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1742 const char *window,const char *filename,ExceptionInfo *exception)
1750 assert(image_info != (const ImageInfo *) NULL);
1751 assert(image_info->signature == MagickSignature);
1752 assert(filename != (char *) NULL);
1753 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1754 display=XOpenDisplay(image_info->server_name);
1755 if (display == (Display *) NULL)
1757 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1758 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1759 return(MagickFalse);
1761 (void) XSetErrorHandler(XError);
1762 status=XRemoteCommand(display,window,filename);
1763 (void) XCloseDisplay(display);
1764 return(status != 0 ? MagickTrue : MagickFalse);
1768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1772 + X A n n o t a t e E d i t I m a g e %
1776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1778 % XAnnotateEditImage() annotates the image with text.
1780 % The format of the XAnnotateEditImage method is:
1782 % MagickBooleanType XAnnotateEditImage(Display *display,
1783 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1784 % ExceptionInfo *exception)
1786 % A description of each parameter follows:
1788 % o display: Specifies a connection to an X server; returned from
1791 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1793 % o windows: Specifies a pointer to a XWindows structure.
1795 % o image: the image; returned from ReadImage.
1799 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
1806 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
1813 static MagickBooleanType XAnnotateEditImage(Display *display,
1814 XResourceInfo *resource_info,XWindows *windows,Image *image,
1815 ExceptionInfo *exception)
1835 static const ModeType
1836 AnnotateCommands[] =
1838 AnnotateNameCommand,
1839 AnnotateFontColorCommand,
1840 AnnotateBackgroundColorCommand,
1841 AnnotateRotateCommand,
1842 AnnotateHelpCommand,
1843 AnnotateDismissCommand
1851 static MagickBooleanType
1852 transparent_box = MagickTrue,
1853 transparent_pen = MagickFalse;
1855 static MagickRealType
1859 box_id = MaxNumberPens-2,
1864 command[MaxTextExtent],
1865 text[MaxTextExtent];
1868 *ColorMenu[MaxNumberPens+1];
1916 (void) CloneString(&windows->command.name,"Annotate");
1917 windows->command.data=4;
1918 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1919 (void) XMapRaised(display,windows->command.id);
1920 XClientMessage(display,windows->image.id,windows->im_protocols,
1921 windows->im_update_widget,CurrentTime);
1923 Track pointer until button 1 is pressed.
1925 XQueryPosition(display,windows->image.id,&x,&y);
1926 (void) XSelectInput(display,windows->image.id,
1927 windows->image.attributes.event_mask | PointerMotionMask);
1928 cursor=XCreateFontCursor(display,XC_left_side);
1929 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1933 if (windows->info.mapped != MagickFalse)
1936 Display pointer position.
1938 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
1939 x+windows->image.x,y+windows->image.y);
1940 XInfoWidget(display,windows,text);
1943 Wait for next event.
1945 XScreenEvent(display,windows,&event);
1946 if (event.xany.window == windows->command.id)
1949 Select a command from the Command widget.
1951 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1952 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1955 switch (AnnotateCommands[id])
1957 case AnnotateNameCommand:
1960 *FontMenu[MaxNumberFonts];
1966 Initialize menu selections.
1968 for (i=0; i < MaxNumberFonts; i++)
1969 FontMenu[i]=resource_info->font_name[i];
1970 FontMenu[MaxNumberFonts-2]="Browser...";
1971 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1973 Select a font name from the pop-up menu.
1975 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1976 (const char **) FontMenu,command);
1977 if (font_number < 0)
1979 if (font_number == (MaxNumberFonts-2))
1982 font_name[MaxTextExtent] = "fixed";
1985 Select a font name from a browser.
1987 resource_info->font_name[font_number]=font_name;
1988 XFontBrowserWidget(display,windows,"Select",font_name);
1989 if (*font_name == '\0')
1993 Initialize font info.
1995 font_info=XLoadQueryFont(display,resource_info->font_name[
1997 if (font_info == (XFontStruct *) NULL)
1999 XNoticeWidget(display,windows,"Unable to load font:",
2000 resource_info->font_name[font_number]);
2003 font_id=(unsigned int) font_number;
2004 (void) XFreeFont(display,font_info);
2007 case AnnotateFontColorCommand:
2010 Initialize menu selections.
2012 for (i=0; i < (int) (MaxNumberPens-2); i++)
2013 ColorMenu[i]=resource_info->pen_colors[i];
2014 ColorMenu[MaxNumberPens-2]="transparent";
2015 ColorMenu[MaxNumberPens-1]="Browser...";
2016 ColorMenu[MaxNumberPens]=(const char *) NULL;
2018 Select a pen color from the pop-up menu.
2020 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2021 (const char **) ColorMenu,command);
2024 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2026 if (transparent_pen != MagickFalse)
2028 if (pen_number == (MaxNumberPens-1))
2031 color_name[MaxTextExtent] = "gray";
2034 Select a pen color from a dialog.
2036 resource_info->pen_colors[pen_number]=color_name;
2037 XColorBrowserWidget(display,windows,"Select",color_name);
2038 if (*color_name == '\0')
2044 (void) XParseColor(display,windows->map_info->colormap,
2045 resource_info->pen_colors[pen_number],&color);
2046 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2047 (unsigned int) MaxColors,&color);
2048 windows->pixel_info->pen_colors[pen_number]=color;
2049 pen_id=(unsigned int) pen_number;
2052 case AnnotateBackgroundColorCommand:
2055 Initialize menu selections.
2057 for (i=0; i < (int) (MaxNumberPens-2); i++)
2058 ColorMenu[i]=resource_info->pen_colors[i];
2059 ColorMenu[MaxNumberPens-2]="transparent";
2060 ColorMenu[MaxNumberPens-1]="Browser...";
2061 ColorMenu[MaxNumberPens]=(const char *) NULL;
2063 Select a pen color from the pop-up menu.
2065 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2066 (const char **) ColorMenu,command);
2069 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2071 if (transparent_box != MagickFalse)
2073 if (pen_number == (MaxNumberPens-1))
2076 color_name[MaxTextExtent] = "gray";
2079 Select a pen color from a dialog.
2081 resource_info->pen_colors[pen_number]=color_name;
2082 XColorBrowserWidget(display,windows,"Select",color_name);
2083 if (*color_name == '\0')
2089 (void) XParseColor(display,windows->map_info->colormap,
2090 resource_info->pen_colors[pen_number],&color);
2091 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2092 (unsigned int) MaxColors,&color);
2093 windows->pixel_info->pen_colors[pen_number]=color;
2094 box_id=(unsigned int) pen_number;
2097 case AnnotateRotateCommand:
2103 angle[MaxTextExtent] = "30.0";
2121 Select a command from the pop-up menu.
2123 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2129 degrees=InterpretLocaleValue(RotateMenu[entry],(char **) NULL);
2132 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2136 degrees=InterpretLocaleValue(angle,(char **) NULL);
2139 case AnnotateHelpCommand:
2141 XTextViewWidget(display,resource_info,windows,MagickFalse,
2142 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2145 case AnnotateDismissCommand:
2163 if (event.xbutton.button != Button1)
2165 if (event.xbutton.window != windows->image.id)
2168 Change to text entering mode.
2181 if (event.xkey.window != windows->image.id)
2184 Respond to a user key press.
2186 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2187 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2188 switch ((int) key_symbol)
2203 XTextViewWidget(display,resource_info,windows,MagickFalse,
2204 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2209 (void) XBell(display,0);
2218 Map and unmap Info widget as cursor crosses its boundaries.
2222 if (windows->info.mapped != MagickFalse)
2224 if ((x < (int) (windows->info.x+windows->info.width)) &&
2225 (y < (int) (windows->info.y+windows->info.height)))
2226 (void) XWithdrawWindow(display,windows->info.id,
2227 windows->info.screen);
2230 if ((x > (int) (windows->info.x+windows->info.width)) ||
2231 (y > (int) (windows->info.y+windows->info.height)))
2232 (void) XMapWindow(display,windows->info.id);
2238 } while ((state & ExitState) == 0);
2239 (void) XSelectInput(display,windows->image.id,
2240 windows->image.attributes.event_mask);
2241 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2242 if ((state & EscapeState) != 0)
2245 Set font info and check boundary conditions.
2247 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2248 if (font_info == (XFontStruct *) NULL)
2250 XNoticeWidget(display,windows,"Unable to load font:",
2251 resource_info->font_name[font_id]);
2252 font_info=windows->font_info;
2254 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2255 x=(int) windows->image.width-font_info->max_bounds.width;
2256 if (y < (int) (font_info->ascent+font_info->descent))
2257 y=(int) font_info->ascent+font_info->descent;
2258 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2259 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2260 return(MagickFalse);
2262 Initialize annotate structure.
2264 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2265 if (annotate_info == (XAnnotateInfo *) NULL)
2266 return(MagickFalse);
2267 XGetAnnotateInfo(annotate_info);
2270 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
2271 annotate_info->stencil=OpaqueStencil;
2273 if (transparent_box == MagickFalse)
2274 annotate_info->stencil=BackgroundStencil;
2276 annotate_info->stencil=ForegroundStencil;
2277 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2278 annotate_info->degrees=degrees;
2279 annotate_info->font_info=font_info;
2280 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2281 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2282 sizeof(*annotate_info->text));
2283 if (annotate_info->text == (char *) NULL)
2284 return(MagickFalse);
2286 Create cursor and set graphic context.
2288 cursor=XCreateFontCursor(display,XC_pencil);
2289 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2290 annotate_context=windows->image.annotate_context;
2291 (void) XSetFont(display,annotate_context,font_info->fid);
2292 (void) XSetBackground(display,annotate_context,
2293 windows->pixel_info->pen_colors[box_id].pixel);
2294 (void) XSetForeground(display,annotate_context,
2295 windows->pixel_info->pen_colors[pen_id].pixel);
2297 Begin annotating the image with text.
2299 (void) CloneString(&windows->command.name,"Text");
2300 windows->command.data=0;
2301 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2303 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2304 text_event.xexpose.width=(int) font_info->max_bounds.width;
2305 text_event.xexpose.height=font_info->max_bounds.ascent+
2306 font_info->max_bounds.descent;
2307 p=annotate_info->text;
2311 Display text cursor.
2314 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2316 Wait for next event.
2318 XScreenEvent(display,windows,&event);
2319 if (event.xany.window == windows->command.id)
2322 Select a command from the Command widget.
2324 (void) XSetBackground(display,annotate_context,
2325 windows->pixel_info->background_color.pixel);
2326 (void) XSetForeground(display,annotate_context,
2327 windows->pixel_info->foreground_color.pixel);
2328 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2329 (void) XSetBackground(display,annotate_context,
2330 windows->pixel_info->pen_colors[box_id].pixel);
2331 (void) XSetForeground(display,annotate_context,
2332 windows->pixel_info->pen_colors[pen_id].pixel);
2335 switch (TextCommands[id])
2337 case TextHelpCommand:
2339 XTextViewWidget(display,resource_info,windows,MagickFalse,
2340 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2341 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2344 case TextApplyCommand:
2347 Finished annotating.
2349 annotate_info->width=(unsigned int) XTextWidth(font_info,
2350 annotate_info->text,(int) strlen(annotate_info->text));
2351 XRefreshWindow(display,&windows->image,&text_event);
2363 text_event.xexpose.x=x;
2364 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2365 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2366 (unsigned int) text_event.xexpose.width,(unsigned int)
2367 text_event.xexpose.height,MagickFalse);
2368 XRefreshWindow(display,&windows->image,&text_event);
2373 if (event.xbutton.window != windows->image.id)
2375 if (event.xbutton.button == Button2)
2378 Request primary selection.
2380 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2381 windows->image.id,CurrentTime);
2388 if (event.xexpose.count == 0)
2394 Refresh Image window.
2396 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2397 text_info=annotate_info;
2398 while (text_info != (XAnnotateInfo *) NULL)
2400 if (annotate_info->stencil == ForegroundStencil)
2401 (void) XDrawString(display,windows->image.id,annotate_context,
2402 text_info->x,text_info->y,text_info->text,
2403 (int) strlen(text_info->text));
2405 (void) XDrawImageString(display,windows->image.id,
2406 annotate_context,text_info->x,text_info->y,text_info->text,
2407 (int) strlen(text_info->text));
2408 text_info=text_info->previous;
2410 (void) XDrawString(display,windows->image.id,annotate_context,
2420 if (event.xkey.window != windows->image.id)
2423 Respond to a user key press.
2425 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2426 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2427 *(command+length)='\0';
2428 if (((event.xkey.state & ControlMask) != 0) ||
2429 ((event.xkey.state & Mod1Mask) != 0))
2430 state|=ModifierState;
2431 if ((state & ModifierState) != 0)
2432 switch ((int) key_symbol)
2437 key_symbol=DeleteCommand;
2443 switch ((int) key_symbol)
2448 Erase one character.
2450 if (p == annotate_info->text)
2452 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2457 Go to end of the previous line of text.
2459 annotate_info=annotate_info->previous;
2460 p=annotate_info->text;
2461 x=annotate_info->x+annotate_info->width;
2463 if (annotate_info->width != 0)
2464 p+=strlen(annotate_info->text);
2469 x-=XTextWidth(font_info,p,1);
2470 text_event.xexpose.x=x;
2471 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2472 XRefreshWindow(display,&windows->image,&text_event);
2475 case XK_bracketleft:
2477 key_symbol=XK_Escape;
2483 Erase the entire line of text.
2485 while (p != annotate_info->text)
2488 x-=XTextWidth(font_info,p,1);
2489 text_event.xexpose.x=x;
2490 XRefreshWindow(display,&windows->image,&text_event);
2498 Finished annotating.
2500 annotate_info->width=(unsigned int) XTextWidth(font_info,
2501 annotate_info->text,(int) strlen(annotate_info->text));
2502 XRefreshWindow(display,&windows->image,&text_event);
2509 Draw a single character on the Image window.
2511 if ((state & ModifierState) != 0)
2513 if (*command == '\0')
2516 if (annotate_info->stencil == ForegroundStencil)
2517 (void) XDrawString(display,windows->image.id,annotate_context,
2520 (void) XDrawImageString(display,windows->image.id,
2521 annotate_context,x,y,p,1);
2522 x+=XTextWidth(font_info,p,1);
2524 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2531 Advance to the next line of text.
2534 annotate_info->width=(unsigned int) XTextWidth(font_info,
2535 annotate_info->text,(int) strlen(annotate_info->text));
2536 if (annotate_info->next != (XAnnotateInfo *) NULL)
2539 Line of text already exists.
2541 annotate_info=annotate_info->next;
2544 p=annotate_info->text;
2547 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2548 sizeof(*annotate_info->next));
2549 if (annotate_info->next == (XAnnotateInfo *) NULL)
2550 return(MagickFalse);
2551 *annotate_info->next=(*annotate_info);
2552 annotate_info->next->previous=annotate_info;
2553 annotate_info=annotate_info->next;
2554 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2555 windows->image.width/MagickMax((ssize_t)
2556 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2557 if (annotate_info->text == (char *) NULL)
2558 return(MagickFalse);
2559 annotate_info->y+=annotate_info->height;
2560 if (annotate_info->y > (int) windows->image.height)
2561 annotate_info->y=(int) annotate_info->height;
2562 annotate_info->next=(XAnnotateInfo *) NULL;
2565 p=annotate_info->text;
2574 Respond to a user key release.
2576 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2577 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2578 state&=(~ModifierState);
2581 case SelectionNotify:
2597 Obtain response from primary selection.
2599 if (event.xselection.property == (Atom) None)
2601 status=XGetWindowProperty(display,event.xselection.requestor,
2602 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2603 &type,&format,&length,&after,&data);
2604 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2608 Annotate Image window with primary selection.
2610 for (i=0; i < (ssize_t) length; i++)
2612 if ((char) data[i] != '\n')
2615 Draw a single character on the Image window.
2618 (void) XDrawString(display,windows->image.id,annotate_context,
2620 x+=XTextWidth(font_info,p,1);
2622 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2626 Advance to the next line of text.
2629 annotate_info->width=(unsigned int) XTextWidth(font_info,
2630 annotate_info->text,(int) strlen(annotate_info->text));
2631 if (annotate_info->next != (XAnnotateInfo *) NULL)
2634 Line of text already exists.
2636 annotate_info=annotate_info->next;
2639 p=annotate_info->text;
2642 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2643 sizeof(*annotate_info->next));
2644 if (annotate_info->next == (XAnnotateInfo *) NULL)
2645 return(MagickFalse);
2646 *annotate_info->next=(*annotate_info);
2647 annotate_info->next->previous=annotate_info;
2648 annotate_info=annotate_info->next;
2649 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2650 windows->image.width/MagickMax((ssize_t)
2651 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2652 if (annotate_info->text == (char *) NULL)
2653 return(MagickFalse);
2654 annotate_info->y+=annotate_info->height;
2655 if (annotate_info->y > (int) windows->image.height)
2656 annotate_info->y=(int) annotate_info->height;
2657 annotate_info->next=(XAnnotateInfo *) NULL;
2660 p=annotate_info->text;
2662 (void) XFree((void *) data);
2668 } while ((state & ExitState) == 0);
2669 (void) XFreeCursor(display,cursor);
2671 Annotation is relative to image configuration.
2673 width=(unsigned int) image->columns;
2674 height=(unsigned int) image->rows;
2677 if (windows->image.crop_geometry != (char *) NULL)
2678 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2680 Initialize annotated image.
2682 XSetCursorState(display,windows,MagickTrue);
2683 XCheckRefreshWindows(display,windows);
2684 while (annotate_info != (XAnnotateInfo *) NULL)
2686 if (annotate_info->width == 0)
2689 No text on this line-- go to the next line of text.
2691 previous_info=annotate_info->previous;
2692 annotate_info->text=(char *)
2693 RelinquishMagickMemory(annotate_info->text);
2694 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2695 annotate_info=previous_info;
2699 Determine pixel index for box and pen color.
2701 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2702 if (windows->pixel_info->colors != 0)
2703 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2704 if (windows->pixel_info->pixels[i] ==
2705 windows->pixel_info->pen_colors[box_id].pixel)
2707 windows->pixel_info->box_index=(unsigned short) i;
2710 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2711 if (windows->pixel_info->colors != 0)
2712 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2713 if (windows->pixel_info->pixels[i] ==
2714 windows->pixel_info->pen_colors[pen_id].pixel)
2716 windows->pixel_info->pen_index=(unsigned short) i;
2720 Define the annotate geometry string.
2722 annotate_info->x=(int)
2723 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2724 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2725 windows->image.y)/windows->image.ximage->height;
2726 (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent,
2727 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2728 height*annotate_info->height/windows->image.ximage->height,
2729 annotate_info->x+x,annotate_info->y+y);
2731 Annotate image with text.
2733 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image);
2735 return(MagickFalse);
2739 previous_info=annotate_info->previous;
2740 annotate_info->text=DestroyString(annotate_info->text);
2741 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2742 annotate_info=previous_info;
2744 (void) XSetForeground(display,annotate_context,
2745 windows->pixel_info->foreground_color.pixel);
2746 (void) XSetBackground(display,annotate_context,
2747 windows->pixel_info->background_color.pixel);
2748 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2749 XSetCursorState(display,windows,MagickFalse);
2750 (void) XFreeFont(display,font_info);
2752 Update image configuration.
2754 XConfigureImageColormap(display,resource_info,windows,image);
2755 (void) XConfigureImage(display,resource_info,windows,image,exception);
2760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2764 + X B a c k g r o u n d I m a g e %
2768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2770 % XBackgroundImage() displays the image in the background of a window.
2772 % The format of the XBackgroundImage method is:
2774 % MagickBooleanType XBackgroundImage(Display *display,
2775 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2776 % ExceptionInfo *exception)
2778 % A description of each parameter follows:
2780 % o display: Specifies a connection to an X server; returned from
2783 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2785 % o windows: Specifies a pointer to a XWindows structure.
2787 % o image: the image.
2789 % o exception: return any errors or warnings in this structure.
2792 static MagickBooleanType XBackgroundImage(Display *display,
2793 XResourceInfo *resource_info,XWindows *windows,Image **image,
2794 ExceptionInfo *exception)
2796 #define BackgroundImageTag "Background/Image"
2802 window_id[MaxTextExtent] = "root";
2805 background_resources;
2808 Put image in background.
2810 status=XDialogWidget(display,windows,"Background",
2811 "Enter window id (id 0x00 selects window with pointer):",window_id);
2812 if (*window_id == '\0')
2813 return(MagickFalse);
2814 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2816 XInfoWidget(display,windows,BackgroundImageTag);
2817 XSetCursorState(display,windows,MagickTrue);
2818 XCheckRefreshWindows(display,windows);
2819 background_resources=(*resource_info);
2820 background_resources.window_id=window_id;
2821 background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse;
2822 status=XDisplayBackgroundImage(display,&background_resources,*image,
2824 if (status != MagickFalse)
2825 XClientMessage(display,windows->image.id,windows->im_protocols,
2826 windows->im_retain_colors,CurrentTime);
2827 XSetCursorState(display,windows,MagickFalse);
2828 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2838 + X C h o p I m a g e %
2842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2844 % XChopImage() chops the X image.
2846 % The format of the XChopImage method is:
2848 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2849 % XWindows *windows,Image **image,ExceptionInfo *exception)
2851 % A description of each parameter follows:
2853 % o display: Specifies a connection to an X server; returned from
2856 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2858 % o windows: Specifies a pointer to a XWindows structure.
2860 % o image: the image.
2862 % o exception: return any errors or warnings in this structure.
2865 static MagickBooleanType XChopImage(Display *display,
2866 XResourceInfo *resource_info,XWindows *windows,Image **image,
2867 ExceptionInfo *exception)
2879 direction = HorizontalChopCommand;
2881 static const ModeType
2884 ChopDirectionCommand,
2888 DirectionCommands[] =
2890 HorizontalChopCommand,
2895 text[MaxTextExtent];
2928 (void) CloneString(&windows->command.name,"Chop");
2929 windows->command.data=1;
2930 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2931 (void) XMapRaised(display,windows->command.id);
2932 XClientMessage(display,windows->image.id,windows->im_protocols,
2933 windows->im_update_widget,CurrentTime);
2935 Track pointer until button 1 is pressed.
2937 XQueryPosition(display,windows->image.id,&x,&y);
2938 (void) XSelectInput(display,windows->image.id,
2939 windows->image.attributes.event_mask | PointerMotionMask);
2943 if (windows->info.mapped != MagickFalse)
2946 Display pointer position.
2948 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
2949 x+windows->image.x,y+windows->image.y);
2950 XInfoWidget(display,windows,text);
2953 Wait for next event.
2955 XScreenEvent(display,windows,&event);
2956 if (event.xany.window == windows->command.id)
2959 Select a command from the Command widget.
2961 id=XCommandWidget(display,windows,ChopMenu,&event);
2964 switch (ChopCommands[id])
2966 case ChopDirectionCommand:
2969 command[MaxTextExtent];
2980 Select a command from the pop-up menu.
2982 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2984 direction=DirectionCommands[id];
2987 case ChopHelpCommand:
2989 XTextViewWidget(display,resource_info,windows,MagickFalse,
2990 "Help Viewer - Image Chop",ImageChopHelp);
2993 case ChopDismissCommand:
3011 if (event.xbutton.button != Button1)
3013 if (event.xbutton.window != windows->image.id)
3016 User has committed to start point of chopping line.
3018 segment_info.x1=(short int) event.xbutton.x;
3019 segment_info.x2=(short int) event.xbutton.x;
3020 segment_info.y1=(short int) event.xbutton.y;
3021 segment_info.y2=(short int) event.xbutton.y;
3032 command[MaxTextExtent];
3037 if (event.xkey.window != windows->image.id)
3040 Respond to a user key press.
3042 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3043 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3044 switch ((int) key_symbol)
3059 (void) XSetFunction(display,windows->image.highlight_context,
3061 XTextViewWidget(display,resource_info,windows,MagickFalse,
3062 "Help Viewer - Image Chop",ImageChopHelp);
3063 (void) XSetFunction(display,windows->image.highlight_context,
3069 (void) XBell(display,0);
3078 Map and unmap Info widget as text cursor crosses its boundaries.
3082 if (windows->info.mapped != MagickFalse)
3084 if ((x < (int) (windows->info.x+windows->info.width)) &&
3085 (y < (int) (windows->info.y+windows->info.height)))
3086 (void) XWithdrawWindow(display,windows->info.id,
3087 windows->info.screen);
3090 if ((x > (int) (windows->info.x+windows->info.width)) ||
3091 (y > (int) (windows->info.y+windows->info.height)))
3092 (void) XMapWindow(display,windows->info.id);
3095 } while ((state & ExitState) == 0);
3096 (void) XSelectInput(display,windows->image.id,
3097 windows->image.attributes.event_mask);
3098 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3099 if ((state & EscapeState) != 0)
3102 Draw line as pointer moves until the mouse button is released.
3109 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3116 Display info and draw chopping line.
3118 if (windows->info.mapped == MagickFalse)
3119 (void) XMapWindow(display,windows->info.id);
3120 (void) FormatLocaleString(text,MaxTextExtent,
3121 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3122 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3123 XInfoWidget(display,windows,text);
3124 XHighlightLine(display,windows->image.id,
3125 windows->image.highlight_context,&segment_info);
3128 if (windows->info.mapped != MagickFalse)
3129 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3131 Wait for next event.
3133 XScreenEvent(display,windows,&event);
3135 XHighlightLine(display,windows->image.id,
3136 windows->image.highlight_context,&segment_info);
3141 segment_info.x2=(short int) event.xmotion.x;
3142 segment_info.y2=(short int) event.xmotion.y;
3148 User has committed to chopping line.
3150 segment_info.x2=(short int) event.xbutton.x;
3151 segment_info.y2=(short int) event.xbutton.y;
3159 segment_info.x2=(short int) event.xmotion.x;
3160 segment_info.y2=(short int) event.xmotion.y;
3166 Check boundary conditions.
3168 if (segment_info.x2 < 0)
3171 if (segment_info.x2 > windows->image.ximage->width)
3172 segment_info.x2=windows->image.ximage->width;
3173 if (segment_info.y2 < 0)
3176 if (segment_info.y2 > windows->image.ximage->height)
3177 segment_info.y2=windows->image.ximage->height;
3178 distance=(unsigned int)
3179 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3180 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3182 Compute chopping geometry.
3184 if (direction == HorizontalChopCommand)
3186 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3187 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3190 if (segment_info.x1 > (int) segment_info.x2)
3192 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3193 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3199 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3201 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3202 if (segment_info.y1 > segment_info.y2)
3204 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3205 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3208 } while ((state & ExitState) == 0);
3209 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3210 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3214 Image chopping is relative to image configuration.
3216 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3218 XSetCursorState(display,windows,MagickTrue);
3219 XCheckRefreshWindows(display,windows);
3220 windows->image.window_changes.width=windows->image.ximage->width-
3221 (unsigned int) chop_info.width;
3222 windows->image.window_changes.height=windows->image.ximage->height-
3223 (unsigned int) chop_info.height;
3224 width=(unsigned int) (*image)->columns;
3225 height=(unsigned int) (*image)->rows;
3228 if (windows->image.crop_geometry != (char *) NULL)
3229 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3230 scale_factor=(MagickRealType) width/windows->image.ximage->width;
3232 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3233 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3234 scale_factor=(MagickRealType) height/windows->image.ximage->height;
3236 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3237 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3241 chop_image=ChopImage(*image,&chop_info,exception);
3242 XSetCursorState(display,windows,MagickFalse);
3243 if (chop_image == (Image *) NULL)
3244 return(MagickFalse);
3245 *image=DestroyImage(*image);
3248 Update image configuration.
3250 XConfigureImageColormap(display,resource_info,windows,*image);
3251 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3260 + X C o l o r E d i t I m a g e %
3264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3266 % XColorEditImage() allows the user to interactively change the color of one
3267 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3269 % The format of the XColorEditImage method is:
3271 % MagickBooleanType XColorEditImage(Display *display,
3272 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3273 % ExceptionInfo *exception)
3275 % A description of each parameter follows:
3277 % o display: Specifies a connection to an X server; returned from
3280 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3282 % o windows: Specifies a pointer to a XWindows structure.
3284 % o image: the image; returned from ReadImage.
3286 % o exception: return any errors or warnings in this structure.
3289 static MagickBooleanType XColorEditImage(Display *display,
3290 XResourceInfo *resource_info,XWindows *windows,Image **image,
3291 ExceptionInfo *exception)
3306 static const ModeType
3307 ColorEditCommands[] =
3309 ColorEditMethodCommand,
3310 ColorEditColorCommand,
3311 ColorEditBorderCommand,
3312 ColorEditFuzzCommand,
3313 ColorEditUndoCommand,
3314 ColorEditHelpCommand,
3315 ColorEditDismissCommand
3319 method = PointMethod;
3325 border_color = { 0, 0, 0, 0, 0, 0 };
3328 command[MaxTextExtent],
3329 text[MaxTextExtent];
3364 (void) CloneString(&windows->command.name,"Color Edit");
3365 windows->command.data=4;
3366 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3367 (void) XMapRaised(display,windows->command.id);
3368 XClientMessage(display,windows->image.id,windows->im_protocols,
3369 windows->im_update_widget,CurrentTime);
3373 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3374 resource_info->background_color,resource_info->foreground_color);
3375 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3377 Track pointer until button 1 is pressed.
3379 XQueryPosition(display,windows->image.id,&x,&y);
3380 (void) XSelectInput(display,windows->image.id,
3381 windows->image.attributes.event_mask | PointerMotionMask);
3385 if (windows->info.mapped != MagickFalse)
3388 Display pointer position.
3390 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
3391 x+windows->image.x,y+windows->image.y);
3392 XInfoWidget(display,windows,text);
3395 Wait for next event.
3397 XScreenEvent(display,windows,&event);
3398 if (event.xany.window == windows->command.id)
3401 Select a command from the Command widget.
3403 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3406 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3409 switch (ColorEditCommands[id])
3411 case ColorEditMethodCommand:
3417 Select a method from the pop-up menu.
3419 methods=(char **) GetCommandOptions(MagickMethodOptions);
3420 if (methods == (char **) NULL)
3422 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3423 (const char **) methods,command);
3425 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3426 MagickFalse,methods[entry]);
3427 methods=DestroyStringList(methods);
3430 case ColorEditColorCommand:
3433 *ColorMenu[MaxNumberPens];
3439 Initialize menu selections.
3441 for (i=0; i < (int) (MaxNumberPens-2); i++)
3442 ColorMenu[i]=resource_info->pen_colors[i];
3443 ColorMenu[MaxNumberPens-2]="Browser...";
3444 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3446 Select a pen color from the pop-up menu.
3448 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3449 (const char **) ColorMenu,command);
3452 if (pen_number == (MaxNumberPens-2))
3455 color_name[MaxTextExtent] = "gray";
3458 Select a pen color from a dialog.
3460 resource_info->pen_colors[pen_number]=color_name;
3461 XColorBrowserWidget(display,windows,"Select",color_name);
3462 if (*color_name == '\0')
3468 (void) XParseColor(display,windows->map_info->colormap,
3469 resource_info->pen_colors[pen_number],&color);
3470 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3471 (unsigned int) MaxColors,&color);
3472 windows->pixel_info->pen_colors[pen_number]=color;
3473 pen_id=(unsigned int) pen_number;
3476 case ColorEditBorderCommand:
3479 *ColorMenu[MaxNumberPens];
3485 Initialize menu selections.
3487 for (i=0; i < (int) (MaxNumberPens-2); i++)
3488 ColorMenu[i]=resource_info->pen_colors[i];
3489 ColorMenu[MaxNumberPens-2]="Browser...";
3490 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3492 Select a pen color from the pop-up menu.
3494 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3495 (const char **) ColorMenu,command);
3498 if (pen_number == (MaxNumberPens-2))
3501 color_name[MaxTextExtent] = "gray";
3504 Select a pen color from a dialog.
3506 resource_info->pen_colors[pen_number]=color_name;
3507 XColorBrowserWidget(display,windows,"Select",color_name);
3508 if (*color_name == '\0')
3514 (void) XParseColor(display,windows->map_info->colormap,
3515 resource_info->pen_colors[pen_number],&border_color);
3518 case ColorEditFuzzCommand:
3521 fuzz[MaxTextExtent];
3536 Select a command from the pop-up menu.
3538 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3544 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*
3548 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3549 (void) XDialogWidget(display,windows,"Ok",
3550 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3553 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3554 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
3557 case ColorEditUndoCommand:
3559 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3563 case ColorEditHelpCommand:
3566 XTextViewWidget(display,resource_info,windows,MagickFalse,
3567 "Help Viewer - Image Annotation",ImageColorEditHelp);
3570 case ColorEditDismissCommand:
3580 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3587 if (event.xbutton.button != Button1)
3589 if ((event.xbutton.window != windows->image.id) &&
3590 (event.xbutton.window != windows->magnify.id))
3597 (void) XMagickCommand(display,resource_info,windows,
3598 SaveToUndoBufferCommand,image,exception);
3599 state|=UpdateConfigurationState;
3604 if (event.xbutton.button != Button1)
3606 if ((event.xbutton.window != windows->image.id) &&
3607 (event.xbutton.window != windows->magnify.id))
3610 Update colormap information.
3614 XConfigureImageColormap(display,resource_info,windows,*image);
3615 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3616 XInfoWidget(display,windows,text);
3617 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3618 state&=(~UpdateConfigurationState);
3628 if (event.xkey.window == windows->magnify.id)
3633 window=windows->magnify.id;
3634 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3636 if (event.xkey.window != windows->image.id)
3639 Respond to a user key press.
3641 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3642 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3643 switch ((int) key_symbol)
3657 XTextViewWidget(display,resource_info,windows,MagickFalse,
3658 "Help Viewer - Image Annotation",ImageColorEditHelp);
3663 (void) XBell(display,0);
3672 Map and unmap Info widget as cursor crosses its boundaries.
3676 if (windows->info.mapped != MagickFalse)
3678 if ((x < (int) (windows->info.x+windows->info.width)) &&
3679 (y < (int) (windows->info.y+windows->info.height)))
3680 (void) XWithdrawWindow(display,windows->info.id,
3681 windows->info.screen);
3684 if ((x > (int) (windows->info.x+windows->info.width)) ||
3685 (y > (int) (windows->info.y+windows->info.height)))
3686 (void) XMapWindow(display,windows->info.id);
3692 if (event.xany.window == windows->magnify.id)
3694 x=windows->magnify.x-windows->image.x;
3695 y=windows->magnify.y-windows->image.y;
3699 if ((state & UpdateConfigurationState) != 0)
3709 Pixel edit is relative to image configuration.
3711 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3713 color=windows->pixel_info->pen_colors[pen_id];
3714 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3715 width=(unsigned int) (*image)->columns;
3716 height=(unsigned int) (*image)->rows;
3719 if (windows->image.crop_geometry != (char *) NULL)
3720 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3723 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3725 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3726 if ((x_offset < 0) || (y_offset < 0))
3728 if ((x_offset >= (int) (*image)->columns) ||
3729 (y_offset >= (int) (*image)->rows))
3731 image_view=AcquireCacheView(*image);
3738 Update color information using point algorithm.
3740 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3741 return(MagickFalse);
3742 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3743 (ssize_t) y_offset,1,1,exception);
3744 if (q == (Quantum *) NULL)
3746 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3747 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3748 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3749 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3759 virtual_pixel[MaxPixelChannels];
3762 Update color information using replace algorithm.
3764 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
3765 (ssize_t) y_offset,virtual_pixel,exception);
3766 target.red=virtual_pixel[RedPixelChannel];
3767 target.green=virtual_pixel[GreenPixelChannel];
3768 target.blue=virtual_pixel[BluePixelChannel];
3769 target.alpha=virtual_pixel[AlphaPixelChannel];
3770 if ((*image)->storage_class == DirectClass)
3772 for (y=0; y < (int) (*image)->rows; y++)
3774 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3775 (*image)->columns,1,exception);
3776 if (q == (Quantum *) NULL)
3778 for (x=0; x < (int) (*image)->columns; x++)
3780 GetPixelPacketPixel(*image,q,&pixel);
3781 if (IsFuzzyEquivalencePixelPacket(*image,&pixel,&target))
3783 SetPixelRed(*image,ScaleShortToQuantum(
3785 SetPixelGreen(*image,ScaleShortToQuantum(
3787 SetPixelBlue(*image,ScaleShortToQuantum(
3790 q+=GetPixelChannels(*image);
3792 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3798 for (i=0; i < (ssize_t) (*image)->colors; i++)
3799 if (IsFuzzyEquivalencePixelPacket(*image,(*image)->colormap+i,&target))
3801 (*image)->colormap[i].red=ScaleShortToQuantum(
3803 (*image)->colormap[i].green=ScaleShortToQuantum(
3805 (*image)->colormap[i].blue=ScaleShortToQuantum(
3808 (void) SyncImage(*image);
3812 case FloodfillMethod:
3813 case FillToBorderMethod:
3822 Update color information using floodfill algorithm.
3824 (void) GetOneVirtualMagickPixel(*image,(ssize_t) x_offset,
3825 (ssize_t) y_offset,&target,exception);
3826 if (method == FillToBorderMethod)
3828 target.red=(MagickRealType)
3829 ScaleShortToQuantum(border_color.red);
3830 target.green=(MagickRealType)
3831 ScaleShortToQuantum(border_color.green);
3832 target.blue=(MagickRealType)
3833 ScaleShortToQuantum(border_color.blue);
3835 draw_info=CloneDrawInfo(resource_info->image_info,
3837 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3838 AllCompliance,&draw_info->fill,exception);
3839 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
3840 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
3841 MagickFalse : MagickTrue,exception);
3842 draw_info=DestroyDrawInfo(draw_info);
3848 Update color information using reset algorithm.
3850 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3851 return(MagickFalse);
3852 for (y=0; y < (int) (*image)->rows; y++)
3854 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3855 (*image)->columns,1,exception);
3856 if (q == (Quantum *) NULL)
3858 for (x=0; x < (int) (*image)->columns; x++)
3860 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3861 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3862 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3863 q+=GetPixelChannels(*image);
3865 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3871 image_view=DestroyCacheView(image_view);
3872 state&=(~UpdateConfigurationState);
3874 } while ((state & ExitState) == 0);
3875 (void) XSelectInput(display,windows->image.id,
3876 windows->image.attributes.event_mask);
3877 XSetCursorState(display,windows,MagickFalse);
3878 (void) XFreeCursor(display,cursor);
3883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3887 + X C o m p o s i t e I m a g e %
3891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3893 % XCompositeImage() requests an image name from the user, reads the image and
3894 % composites it with the X window image at a location the user chooses with
3897 % The format of the XCompositeImage method is:
3899 % MagickBooleanType XCompositeImage(Display *display,
3900 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3901 % ExceptionInfo *exception)
3903 % A description of each parameter follows:
3905 % o display: Specifies a connection to an X server; returned from
3908 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3910 % o windows: Specifies a pointer to a XWindows structure.
3912 % o image: the image; returned from ReadImage.
3914 % o exception: return any errors or warnings in this structure.
3917 static MagickBooleanType XCompositeImage(Display *display,
3918 XResourceInfo *resource_info,XWindows *windows,Image *image,
3919 ExceptionInfo *exception)
3922 displacement_geometry[MaxTextExtent] = "30x30",
3923 filename[MaxTextExtent] = "\0";
3936 static CompositeOperator
3937 compose = CopyCompositeOp;
3939 static const ModeType
3940 CompositeCommands[] =
3942 CompositeOperatorsCommand,
3943 CompositeDissolveCommand,
3944 CompositeDisplaceCommand,
3945 CompositeHelpCommand,
3946 CompositeDismissCommand
3950 text[MaxTextExtent];
3983 Request image file name from user.
3985 XFileBrowserWidget(display,windows,"Composite",filename);
3986 if (*filename == '\0')
3991 XSetCursorState(display,windows,MagickTrue);
3992 XCheckRefreshWindows(display,windows);
3993 (void) CopyMagickString(resource_info->image_info->filename,filename,
3995 composite_image=ReadImage(resource_info->image_info,exception);
3996 CatchException(exception);
3997 XSetCursorState(display,windows,MagickFalse);
3998 if (composite_image == (Image *) NULL)
3999 return(MagickFalse);
4003 (void) CloneString(&windows->command.name,"Composite");
4004 windows->command.data=1;
4005 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
4006 (void) XMapRaised(display,windows->command.id);
4007 XClientMessage(display,windows->image.id,windows->im_protocols,
4008 windows->im_update_widget,CurrentTime);
4010 Track pointer until button 1 is pressed.
4012 XQueryPosition(display,windows->image.id,&x,&y);
4013 (void) XSelectInput(display,windows->image.id,
4014 windows->image.attributes.event_mask | PointerMotionMask);
4015 composite_info.x=(ssize_t) windows->image.x+x;
4016 composite_info.y=(ssize_t) windows->image.y+y;
4017 composite_info.width=0;
4018 composite_info.height=0;
4019 cursor=XCreateFontCursor(display,XC_ul_angle);
4020 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4025 if (windows->info.mapped != MagickFalse)
4028 Display pointer position.
4030 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4031 (long) composite_info.x,(long) composite_info.y);
4032 XInfoWidget(display,windows,text);
4034 highlight_info=composite_info;
4035 highlight_info.x=composite_info.x-windows->image.x;
4036 highlight_info.y=composite_info.y-windows->image.y;
4037 XHighlightRectangle(display,windows->image.id,
4038 windows->image.highlight_context,&highlight_info);
4040 Wait for next event.
4042 XScreenEvent(display,windows,&event);
4043 XHighlightRectangle(display,windows->image.id,
4044 windows->image.highlight_context,&highlight_info);
4045 if (event.xany.window == windows->command.id)
4048 Select a command from the Command widget.
4050 id=XCommandWidget(display,windows,CompositeMenu,&event);
4053 switch (CompositeCommands[id])
4055 case CompositeOperatorsCommand:
4058 command[MaxTextExtent],
4062 Select a command from the pop-up menu.
4064 operators=GetCommandOptions(MagickComposeOptions);
4065 if (operators == (char **) NULL)
4067 entry=XMenuWidget(display,windows,CompositeMenu[id],
4068 (const char **) operators,command);
4070 compose=(CompositeOperator) ParseCommandOption(
4071 MagickComposeOptions,MagickFalse,operators[entry]);
4072 operators=DestroyStringList(operators);
4075 case CompositeDissolveCommand:
4078 factor[MaxTextExtent] = "20.0";
4081 Dissolve the two images a given percent.
4083 (void) XSetFunction(display,windows->image.highlight_context,
4085 (void) XDialogWidget(display,windows,"Dissolve",
4086 "Enter the blend factor (0.0 - 99.9%):",factor);
4087 (void) XSetFunction(display,windows->image.highlight_context,
4089 if (*factor == '\0')
4091 blend=InterpretLocaleValue(factor,(char **) NULL);
4092 compose=DissolveCompositeOp;
4095 case CompositeDisplaceCommand:
4098 Get horizontal and vertical scale displacement geometry.
4100 (void) XSetFunction(display,windows->image.highlight_context,
4102 (void) XDialogWidget(display,windows,"Displace",
4103 "Enter the horizontal and vertical scale:",displacement_geometry);
4104 (void) XSetFunction(display,windows->image.highlight_context,
4106 if (*displacement_geometry == '\0')
4108 compose=DisplaceCompositeOp;
4111 case CompositeHelpCommand:
4113 (void) XSetFunction(display,windows->image.highlight_context,
4115 XTextViewWidget(display,resource_info,windows,MagickFalse,
4116 "Help Viewer - Image Composite",ImageCompositeHelp);
4117 (void) XSetFunction(display,windows->image.highlight_context,
4121 case CompositeDismissCommand:
4139 if (image->debug != MagickFalse)
4140 (void) LogMagickEvent(X11Event,GetMagickModule(),
4141 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4142 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4143 if (event.xbutton.button != Button1)
4145 if (event.xbutton.window != windows->image.id)
4150 composite_info.width=composite_image->columns;
4151 composite_info.height=composite_image->rows;
4152 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4153 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4154 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4159 if (image->debug != MagickFalse)
4160 (void) LogMagickEvent(X11Event,GetMagickModule(),
4161 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4162 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4163 if (event.xbutton.button != Button1)
4165 if (event.xbutton.window != windows->image.id)
4167 if ((composite_info.width != 0) && (composite_info.height != 0))
4170 User has selected the location of the composite image.
4172 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4173 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4183 command[MaxTextExtent];
4191 if (event.xkey.window != windows->image.id)
4194 Respond to a user key press.
4196 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4197 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4198 *(command+length)='\0';
4199 if (image->debug != MagickFalse)
4200 (void) LogMagickEvent(X11Event,GetMagickModule(),
4201 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4202 switch ((int) key_symbol)
4210 composite_image=DestroyImage(composite_image);
4218 (void) XSetFunction(display,windows->image.highlight_context,
4220 XTextViewWidget(display,resource_info,windows,MagickFalse,
4221 "Help Viewer - Image Composite",ImageCompositeHelp);
4222 (void) XSetFunction(display,windows->image.highlight_context,
4228 (void) XBell(display,0);
4237 Map and unmap Info widget as text cursor crosses its boundaries.
4241 if (windows->info.mapped != MagickFalse)
4243 if ((x < (int) (windows->info.x+windows->info.width)) &&
4244 (y < (int) (windows->info.y+windows->info.height)))
4245 (void) XWithdrawWindow(display,windows->info.id,
4246 windows->info.screen);
4249 if ((x > (int) (windows->info.x+windows->info.width)) ||
4250 (y > (int) (windows->info.y+windows->info.height)))
4251 (void) XMapWindow(display,windows->info.id);
4252 composite_info.x=(ssize_t) windows->image.x+x;
4253 composite_info.y=(ssize_t) windows->image.y+y;
4258 if (image->debug != MagickFalse)
4259 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4264 } while ((state & ExitState) == 0);
4265 (void) XSelectInput(display,windows->image.id,
4266 windows->image.attributes.event_mask);
4267 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4268 XSetCursorState(display,windows,MagickFalse);
4269 (void) XFreeCursor(display,cursor);
4270 if ((state & EscapeState) != 0)
4273 Image compositing is relative to image configuration.
4275 XSetCursorState(display,windows,MagickTrue);
4276 XCheckRefreshWindows(display,windows);
4277 width=(unsigned int) image->columns;
4278 height=(unsigned int) image->rows;
4281 if (windows->image.crop_geometry != (char *) NULL)
4282 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4283 scale_factor=(MagickRealType) width/windows->image.ximage->width;
4284 composite_info.x+=x;
4285 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4286 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4287 scale_factor=(MagickRealType) height/windows->image.ximage->height;
4288 composite_info.y+=y;
4289 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4290 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4291 if ((composite_info.width != composite_image->columns) ||
4292 (composite_info.height != composite_image->rows))
4298 Scale composite image.
4300 resize_image=ResizeImage(composite_image,composite_info.width,
4301 composite_info.height,composite_image->filter,composite_image->blur,
4303 composite_image=DestroyImage(composite_image);
4304 if (resize_image == (Image *) NULL)
4306 XSetCursorState(display,windows,MagickFalse);
4307 return(MagickFalse);
4309 composite_image=resize_image;
4311 if (compose == DisplaceCompositeOp)
4312 (void) SetImageArtifact(composite_image,"compose:args",
4313 displacement_geometry);
4332 Create mattes for blending.
4334 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4335 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
4336 ((ssize_t) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
4337 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4338 return(MagickFalse);
4339 image->matte=MagickTrue;
4340 image_view=AcquireCacheView(image);
4341 for (y=0; y < (int) image->rows; y++)
4343 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4345 if (q == (Quantum *) NULL)
4347 for (x=0; x < (int) image->columns; x++)
4349 SetPixelAlpha(image,opacity,q);
4350 q+=GetPixelChannels(image);
4352 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4355 image_view=DestroyCacheView(image_view);
4358 Composite image with X Image window.
4360 (void) CompositeImage(image,compose,composite_image,composite_info.x,
4362 composite_image=DestroyImage(composite_image);
4363 XSetCursorState(display,windows,MagickFalse);
4365 Update image configuration.
4367 XConfigureImageColormap(display,resource_info,windows,image);
4368 (void) XConfigureImage(display,resource_info,windows,image,exception);
4373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4377 + X C o n f i g u r e I m a g e %
4381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4383 % XConfigureImage() creates a new X image. It also notifies the window
4384 % manager of the new image size and configures the transient widows.
4386 % The format of the XConfigureImage method is:
4388 % MagickBooleanType XConfigureImage(Display *display,
4389 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4390 % ExceptionInfo *exception)
4392 % A description of each parameter follows:
4394 % o display: Specifies a connection to an X server; returned from
4397 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4399 % o windows: Specifies a pointer to a XWindows structure.
4401 % o image: the image.
4403 % o exception: return any errors or warnings in this structure.
4405 % o exception: return any errors or warnings in this structure.
4408 static MagickBooleanType XConfigureImage(Display *display,
4409 XResourceInfo *resource_info,XWindows *windows,Image *image,
4410 ExceptionInfo *exception)
4413 geometry[MaxTextExtent];
4434 Dismiss if window dimensions are zero.
4436 width=(unsigned int) windows->image.window_changes.width;
4437 height=(unsigned int) windows->image.window_changes.height;
4438 if (image->debug != MagickFalse)
4439 (void) LogMagickEvent(X11Event,GetMagickModule(),
4440 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4441 windows->image.ximage->height,(double) width,(double) height);
4442 if ((width*height) == 0)
4447 Resize image to fit Image window dimensions.
4449 XSetCursorState(display,windows,MagickTrue);
4450 (void) XFlush(display);
4451 if (((int) width != windows->image.ximage->width) ||
4452 ((int) height != windows->image.ximage->height))
4453 image->taint=MagickTrue;
4454 windows->magnify.x=(int)
4455 width*windows->magnify.x/windows->image.ximage->width;
4456 windows->magnify.y=(int)
4457 height*windows->magnify.y/windows->image.ximage->height;
4458 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4459 windows->image.y=(int)
4460 (height*windows->image.y/windows->image.ximage->height);
4461 status=XMakeImage(display,resource_info,&windows->image,image,
4462 (unsigned int) width,(unsigned int) height,exception);
4463 if (status == MagickFalse)
4464 XNoticeWidget(display,windows,"Unable to configure X image:",
4465 windows->image.name);
4467 Notify window manager of the new configuration.
4469 if (resource_info->image_geometry != (char *) NULL)
4470 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4471 resource_info->image_geometry);
4473 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4474 XDisplayWidth(display,windows->image.screen),
4475 XDisplayHeight(display,windows->image.screen));
4476 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4477 window_changes.width=(int) width;
4478 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4479 window_changes.width=XDisplayWidth(display,windows->image.screen);
4480 window_changes.height=(int) height;
4481 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4482 window_changes.height=XDisplayHeight(display,windows->image.screen);
4483 mask=(size_t) (CWWidth | CWHeight);
4484 if (resource_info->backdrop)
4487 window_changes.x=(int)
4488 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4489 window_changes.y=(int)
4490 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4492 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4493 (unsigned int) mask,&window_changes);
4494 (void) XClearWindow(display,windows->image.id);
4495 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4497 Update Magnify window configuration.
4499 if (windows->magnify.mapped != MagickFalse)
4500 XMakeMagnifyImage(display,windows);
4501 windows->pan.crop_geometry=windows->image.crop_geometry;
4502 XBestIconSize(display,&windows->pan,image);
4503 while (((windows->pan.width << 1) < MaxIconSize) &&
4504 ((windows->pan.height << 1) < MaxIconSize))
4506 windows->pan.width<<=1;
4507 windows->pan.height<<=1;
4509 if (windows->pan.geometry != (char *) NULL)
4510 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4511 &windows->pan.width,&windows->pan.height);
4512 window_changes.width=(int) windows->pan.width;
4513 window_changes.height=(int) windows->pan.height;
4514 size_hints=XAllocSizeHints();
4515 if (size_hints != (XSizeHints *) NULL)
4520 size_hints->flags=PSize | PMinSize | PMaxSize;
4521 size_hints->width=window_changes.width;
4522 size_hints->height=window_changes.height;
4523 size_hints->min_width=size_hints->width;
4524 size_hints->min_height=size_hints->height;
4525 size_hints->max_width=size_hints->width;
4526 size_hints->max_height=size_hints->height;
4527 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4528 (void) XFree((void *) size_hints);
4530 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4531 (unsigned int) (CWWidth | CWHeight),&window_changes);
4533 Update icon window configuration.
4535 windows->icon.crop_geometry=windows->image.crop_geometry;
4536 XBestIconSize(display,&windows->icon,image);
4537 window_changes.width=(int) windows->icon.width;
4538 window_changes.height=(int) windows->icon.height;
4539 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4540 (unsigned int) (CWWidth | CWHeight),&window_changes);
4541 XSetCursorState(display,windows,MagickFalse);
4542 return(status != 0 ? MagickTrue : MagickFalse);
4546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4550 + X C r o p I m a g e %
4554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4556 % XCropImage() allows the user to select a region of the image and crop, copy,
4557 % or cut it. For copy or cut, the image can subsequently be composited onto
4558 % the image with XPasteImage.
4560 % The format of the XCropImage method is:
4562 % MagickBooleanType XCropImage(Display *display,
4563 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4564 % const ClipboardMode mode,ExceptionInfo *exception)
4566 % A description of each parameter follows:
4568 % o display: Specifies a connection to an X server; returned from
4571 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4573 % o windows: Specifies a pointer to a XWindows structure.
4575 % o image: the image; returned from ReadImage.
4577 % o mode: This unsigned value specified whether the image should be
4578 % cropped, copied, or cut.
4580 % o exception: return any errors or warnings in this structure.
4583 static MagickBooleanType XCropImage(Display *display,
4584 XResourceInfo *resource_info,XWindows *windows,Image *image,
4585 const ClipboardMode mode,ExceptionInfo *exception)
4594 *RectifyModeMenu[] =
4602 static const ModeType
4612 RectifyDismissCommand
4619 command[MaxTextExtent],
4620 text[MaxTextExtent];
4663 (void) CloneString(&windows->command.name,"Copy");
4668 (void) CloneString(&windows->command.name,"Crop");
4673 (void) CloneString(&windows->command.name,"Cut");
4677 RectifyModeMenu[0]=windows->command.name;
4678 windows->command.data=0;
4679 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4680 (void) XMapRaised(display,windows->command.id);
4681 XClientMessage(display,windows->image.id,windows->im_protocols,
4682 windows->im_update_widget,CurrentTime);
4684 Track pointer until button 1 is pressed.
4686 XQueryPosition(display,windows->image.id,&x,&y);
4687 (void) XSelectInput(display,windows->image.id,
4688 windows->image.attributes.event_mask | PointerMotionMask);
4689 crop_info.x=(ssize_t) windows->image.x+x;
4690 crop_info.y=(ssize_t) windows->image.y+y;
4693 cursor=XCreateFontCursor(display,XC_fleur);
4697 if (windows->info.mapped != MagickFalse)
4700 Display pointer position.
4702 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4703 (long) crop_info.x,(long) crop_info.y);
4704 XInfoWidget(display,windows,text);
4707 Wait for next event.
4709 XScreenEvent(display,windows,&event);
4710 if (event.xany.window == windows->command.id)
4713 Select a command from the Command widget.
4715 id=XCommandWidget(display,windows,CropModeMenu,&event);
4718 switch (CropCommands[id])
4720 case CropHelpCommand:
4726 XTextViewWidget(display,resource_info,windows,MagickFalse,
4727 "Help Viewer - Image Copy",ImageCopyHelp);
4732 XTextViewWidget(display,resource_info,windows,MagickFalse,
4733 "Help Viewer - Image Crop",ImageCropHelp);
4738 XTextViewWidget(display,resource_info,windows,MagickFalse,
4739 "Help Viewer - Image Cut",ImageCutHelp);
4745 case CropDismissCommand:
4763 if (event.xbutton.button != Button1)
4765 if (event.xbutton.window != windows->image.id)
4768 Note first corner of cropping rectangle-- exit loop.
4770 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4771 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4772 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4782 if (event.xkey.window != windows->image.id)
4785 Respond to a user key press.
4787 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4788 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4789 switch ((int) key_symbol)
4808 XTextViewWidget(display,resource_info,windows,MagickFalse,
4809 "Help Viewer - Image Copy",ImageCopyHelp);
4814 XTextViewWidget(display,resource_info,windows,MagickFalse,
4815 "Help Viewer - Image Crop",ImageCropHelp);
4820 XTextViewWidget(display,resource_info,windows,MagickFalse,
4821 "Help Viewer - Image Cut",ImageCutHelp);
4829 (void) XBell(display,0);
4837 if (event.xmotion.window != windows->image.id)
4840 Map and unmap Info widget as text cursor crosses its boundaries.
4844 if (windows->info.mapped != MagickFalse)
4846 if ((x < (int) (windows->info.x+windows->info.width)) &&
4847 (y < (int) (windows->info.y+windows->info.height)))
4848 (void) XWithdrawWindow(display,windows->info.id,
4849 windows->info.screen);
4852 if ((x > (int) (windows->info.x+windows->info.width)) ||
4853 (y > (int) (windows->info.y+windows->info.height)))
4854 (void) XMapWindow(display,windows->info.id);
4855 crop_info.x=(ssize_t) windows->image.x+x;
4856 crop_info.y=(ssize_t) windows->image.y+y;
4862 } while ((state & ExitState) == 0);
4863 (void) XSelectInput(display,windows->image.id,
4864 windows->image.attributes.event_mask);
4865 if ((state & EscapeState) != 0)
4868 User want to exit without cropping.
4870 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4871 (void) XFreeCursor(display,cursor);
4874 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4878 Size rectangle as pointer moves until the mouse button is released.
4880 x=(int) crop_info.x;
4881 y=(int) crop_info.y;
4887 highlight_info=crop_info;
4888 highlight_info.x=crop_info.x-windows->image.x;
4889 highlight_info.y=crop_info.y-windows->image.y;
4890 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4893 Display info and draw cropping rectangle.
4895 if (windows->info.mapped == MagickFalse)
4896 (void) XMapWindow(display,windows->info.id);
4897 (void) FormatLocaleString(text,MaxTextExtent,
4898 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4899 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4900 XInfoWidget(display,windows,text);
4901 XHighlightRectangle(display,windows->image.id,
4902 windows->image.highlight_context,&highlight_info);
4905 if (windows->info.mapped != MagickFalse)
4906 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4908 Wait for next event.
4910 XScreenEvent(display,windows,&event);
4911 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4912 XHighlightRectangle(display,windows->image.id,
4913 windows->image.highlight_context,&highlight_info);
4918 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4919 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4925 User has committed to cropping rectangle.
4927 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4928 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4929 XSetCursorState(display,windows,MagickFalse);
4931 windows->command.data=0;
4932 (void) XCommandWidget(display,windows,RectifyModeMenu,
4940 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4941 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4946 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4947 ((state & ExitState) != 0))
4950 Check boundary conditions.
4952 if (crop_info.x < 0)
4955 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4956 crop_info.x=(ssize_t) windows->image.ximage->width;
4957 if ((int) crop_info.x < x)
4958 crop_info.width=(unsigned int) (x-crop_info.x);
4961 crop_info.width=(unsigned int) (crop_info.x-x);
4962 crop_info.x=(ssize_t) x;
4964 if (crop_info.y < 0)
4967 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4968 crop_info.y=(ssize_t) windows->image.ximage->height;
4969 if ((int) crop_info.y < y)
4970 crop_info.height=(unsigned int) (y-crop_info.y);
4973 crop_info.height=(unsigned int) (crop_info.y-y);
4974 crop_info.y=(ssize_t) y;
4977 } while ((state & ExitState) == 0);
4979 Wait for user to grab a corner of the rectangle or press return.
4982 (void) XMapWindow(display,windows->info.id);
4985 if (windows->info.mapped != MagickFalse)
4988 Display pointer position.
4990 (void) FormatLocaleString(text,MaxTextExtent,
4991 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4992 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4993 XInfoWidget(display,windows,text);
4995 highlight_info=crop_info;
4996 highlight_info.x=crop_info.x-windows->image.x;
4997 highlight_info.y=crop_info.y-windows->image.y;
4998 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
5004 XHighlightRectangle(display,windows->image.id,
5005 windows->image.highlight_context,&highlight_info);
5006 XScreenEvent(display,windows,&event);
5007 if (event.xany.window == windows->command.id)
5010 Select a command from the Command widget.
5012 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5013 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5014 (void) XSetFunction(display,windows->image.highlight_context,
5016 XHighlightRectangle(display,windows->image.id,
5017 windows->image.highlight_context,&highlight_info);
5019 switch (RectifyCommands[id])
5021 case RectifyCopyCommand:
5026 case RectifyHelpCommand:
5028 (void) XSetFunction(display,windows->image.highlight_context,
5034 XTextViewWidget(display,resource_info,windows,MagickFalse,
5035 "Help Viewer - Image Copy",ImageCopyHelp);
5040 XTextViewWidget(display,resource_info,windows,MagickFalse,
5041 "Help Viewer - Image Crop",ImageCropHelp);
5046 XTextViewWidget(display,resource_info,windows,MagickFalse,
5047 "Help Viewer - Image Cut",ImageCutHelp);
5051 (void) XSetFunction(display,windows->image.highlight_context,
5055 case RectifyDismissCommand:
5069 XHighlightRectangle(display,windows->image.id,
5070 windows->image.highlight_context,&highlight_info);
5075 if (event.xbutton.button != Button1)
5077 if (event.xbutton.window != windows->image.id)
5079 x=windows->image.x+event.xbutton.x;
5080 y=windows->image.y+event.xbutton.y;
5081 if ((x < (int) (crop_info.x+RoiDelta)) &&
5082 (x > (int) (crop_info.x-RoiDelta)) &&
5083 (y < (int) (crop_info.y+RoiDelta)) &&
5084 (y > (int) (crop_info.y-RoiDelta)))
5086 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5087 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5088 state|=UpdateConfigurationState;
5091 if ((x < (int) (crop_info.x+RoiDelta)) &&
5092 (x > (int) (crop_info.x-RoiDelta)) &&
5093 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5094 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5096 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5097 state|=UpdateConfigurationState;
5100 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5101 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5102 (y < (int) (crop_info.y+RoiDelta)) &&
5103 (y > (int) (crop_info.y-RoiDelta)))
5105 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5106 state|=UpdateConfigurationState;
5109 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5110 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5111 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5112 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5114 state|=UpdateConfigurationState;
5120 if (event.xbutton.window == windows->pan.id)
5121 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5122 (highlight_info.y != crop_info.y-windows->image.y))
5123 XHighlightRectangle(display,windows->image.id,
5124 windows->image.highlight_context,&highlight_info);
5125 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5126 event.xbutton.time);
5131 if (event.xexpose.window == windows->image.id)
5132 if (event.xexpose.count == 0)
5134 event.xexpose.x=(int) highlight_info.x;
5135 event.xexpose.y=(int) highlight_info.y;
5136 event.xexpose.width=(int) highlight_info.width;
5137 event.xexpose.height=(int) highlight_info.height;
5138 XRefreshWindow(display,&windows->image,&event);
5140 if (event.xexpose.window == windows->info.id)
5141 if (event.xexpose.count == 0)
5142 XInfoWidget(display,windows,text);
5147 if (event.xkey.window != windows->image.id)
5150 Respond to a user key press.
5152 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5153 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5154 switch ((int) key_symbol)
5167 crop_info.x=(ssize_t) (windows->image.width/2L-
5168 crop_info.width/2L);
5169 crop_info.y=(ssize_t) (windows->image.height/2L-
5170 crop_info.height/2L);
5202 (void) XSetFunction(display,windows->image.highlight_context,
5208 XTextViewWidget(display,resource_info,windows,MagickFalse,
5209 "Help Viewer - Image Copy",ImageCopyHelp);
5214 XTextViewWidget(display,resource_info,windows,MagickFalse,
5215 "Help Viewer - Image Cropg",ImageCropHelp);
5220 XTextViewWidget(display,resource_info,windows,MagickFalse,
5221 "Help Viewer - Image Cutg",ImageCutHelp);
5225 (void) XSetFunction(display,windows->image.highlight_context,
5231 (void) XBell(display,0);
5235 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5243 if (event.xmotion.window != windows->image.id)
5246 Map and unmap Info widget as text cursor crosses its boundaries.
5250 if (windows->info.mapped != MagickFalse)
5252 if ((x < (int) (windows->info.x+windows->info.width)) &&
5253 (y < (int) (windows->info.y+windows->info.height)))
5254 (void) XWithdrawWindow(display,windows->info.id,
5255 windows->info.screen);
5258 if ((x > (int) (windows->info.x+windows->info.width)) ||
5259 (y > (int) (windows->info.y+windows->info.height)))
5260 (void) XMapWindow(display,windows->info.id);
5261 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5262 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5265 case SelectionRequest:
5270 XSelectionRequestEvent
5274 Set primary selection.
5276 (void) FormatLocaleString(text,MaxTextExtent,
5277 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5278 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5279 request=(&(event.xselectionrequest));
5280 (void) XChangeProperty(request->display,request->requestor,
5281 request->property,request->target,8,PropModeReplace,
5282 (unsigned char *) text,(int) strlen(text));
5283 notify.type=SelectionNotify;
5284 notify.display=request->display;
5285 notify.requestor=request->requestor;
5286 notify.selection=request->selection;
5287 notify.target=request->target;
5288 notify.time=request->time;
5289 if (request->property == None)
5290 notify.property=request->target;
5292 notify.property=request->property;
5293 (void) XSendEvent(request->display,request->requestor,False,0,
5294 (XEvent *) ¬ify);
5299 if ((state & UpdateConfigurationState) != 0)
5301 (void) XPutBackEvent(display,&event);
5302 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5305 } while ((state & ExitState) == 0);
5306 } while ((state & ExitState) == 0);
5307 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5308 XSetCursorState(display,windows,MagickFalse);
5309 if ((state & EscapeState) != 0)
5311 if (mode == CropMode)
5312 if (((int) crop_info.width != windows->image.ximage->width) ||
5313 ((int) crop_info.height != windows->image.ximage->height))
5316 Reconfigure Image window as defined by cropping rectangle.
5318 XSetCropGeometry(display,windows,&crop_info,image);
5319 windows->image.window_changes.width=(int) crop_info.width;
5320 windows->image.window_changes.height=(int) crop_info.height;
5321 (void) XConfigureImage(display,resource_info,windows,image,exception);
5325 Copy image before applying image transforms.
5327 XSetCursorState(display,windows,MagickTrue);
5328 XCheckRefreshWindows(display,windows);
5329 width=(unsigned int) image->columns;
5330 height=(unsigned int) image->rows;
5333 if (windows->image.crop_geometry != (char *) NULL)
5334 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5335 scale_factor=(MagickRealType) width/windows->image.ximage->width;
5337 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5338 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5339 scale_factor=(MagickRealType) height/windows->image.ximage->height;
5341 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5342 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5343 crop_image=CropImage(image,&crop_info,exception);
5344 XSetCursorState(display,windows,MagickFalse);
5345 if (crop_image == (Image *) NULL)
5346 return(MagickFalse);
5347 if (resource_info->copy_image != (Image *) NULL)
5348 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5349 resource_info->copy_image=crop_image;
5350 if (mode == CopyMode)
5352 (void) XConfigureImage(display,resource_info,windows,image,exception);
5358 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
5359 return(MagickFalse);
5360 image->matte=MagickTrue;
5361 image_view=AcquireCacheView(image);
5362 for (y=0; y < (int) crop_info.height; y++)
5364 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5365 crop_info.width,1,exception);
5366 if (q == (Quantum *) NULL)
5368 for (x=0; x < (int) crop_info.width; x++)
5370 SetPixelAlpha(image,TransparentAlpha,q);
5371 q+=GetPixelChannels(image);
5373 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
5376 image_view=DestroyCacheView(image_view);
5378 Update image configuration.
5380 XConfigureImageColormap(display,resource_info,windows,image);
5381 (void) XConfigureImage(display,resource_info,windows,image,exception);
5386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5390 + X D r a w I m a g e %
5394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5396 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5399 % The format of the XDrawEditImage method is:
5401 % MagickBooleanType XDrawEditImage(Display *display,
5402 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5403 % ExceptionInfo *exception)
5405 % A description of each parameter follows:
5407 % o display: Specifies a connection to an X server; returned from
5410 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5412 % o windows: Specifies a pointer to a XWindows structure.
5414 % o image: the image.
5416 % o exception: return any errors or warnings in this structure.
5419 static MagickBooleanType XDrawEditImage(Display *display,
5420 XResourceInfo *resource_info,XWindows *windows,Image **image,
5421 ExceptionInfo *exception)
5437 element = PointElement;
5439 static const ModeType
5452 stipple = (Pixmap) NULL;
5459 command[MaxTextExtent],
5460 text[MaxTextExtent];
5509 Allocate polygon info.
5511 max_coordinates=2048;
5512 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5513 sizeof(*coordinate_info));
5514 if (coordinate_info == (XPoint *) NULL)
5516 (void) ThrowMagickException(exception,GetMagickModule(),
5517 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5518 return(MagickFalse);
5523 (void) CloneString(&windows->command.name,"Draw");
5524 windows->command.data=4;
5525 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5526 (void) XMapRaised(display,windows->command.id);
5527 XClientMessage(display,windows->image.id,windows->im_protocols,
5528 windows->im_update_widget,CurrentTime);
5530 Wait for first button press.
5532 root_window=XRootWindow(display,XDefaultScreen(display));
5533 draw_info.stencil=OpaqueStencil;
5535 cursor=XCreateFontCursor(display,XC_tcross);
5538 XQueryPosition(display,windows->image.id,&x,&y);
5539 (void) XSelectInput(display,windows->image.id,
5540 windows->image.attributes.event_mask | PointerMotionMask);
5541 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5545 if (windows->info.mapped != MagickFalse)
5548 Display pointer position.
5550 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5551 x+windows->image.x,y+windows->image.y);
5552 XInfoWidget(display,windows,text);
5555 Wait for next event.
5557 XScreenEvent(display,windows,&event);
5558 if (event.xany.window == windows->command.id)
5561 Select a command from the Command widget.
5563 id=XCommandWidget(display,windows,DrawMenu,&event);
5566 switch (DrawCommands[id])
5568 case DrawElementCommand:
5587 Select a command from the pop-up menu.
5589 element=(ElementType) (XMenuWidget(display,windows,
5590 DrawMenu[id],Elements,command)+1);
5593 case DrawColorCommand:
5596 *ColorMenu[MaxNumberPens+1];
5608 Initialize menu selections.
5610 for (i=0; i < (int) (MaxNumberPens-2); i++)
5611 ColorMenu[i]=resource_info->pen_colors[i];
5612 ColorMenu[MaxNumberPens-2]="transparent";
5613 ColorMenu[MaxNumberPens-1]="Browser...";
5614 ColorMenu[MaxNumberPens]=(char *) NULL;
5616 Select a pen color from the pop-up menu.
5618 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5619 (const char **) ColorMenu,command);
5622 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5624 if (transparent != MagickFalse)
5626 draw_info.stencil=TransparentStencil;
5629 if (pen_number == (MaxNumberPens-1))
5632 color_name[MaxTextExtent] = "gray";
5635 Select a pen color from a dialog.
5637 resource_info->pen_colors[pen_number]=color_name;
5638 XColorBrowserWidget(display,windows,"Select",color_name);
5639 if (*color_name == '\0')
5645 (void) XParseColor(display,windows->map_info->colormap,
5646 resource_info->pen_colors[pen_number],&color);
5647 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5648 (unsigned int) MaxColors,&color);
5649 windows->pixel_info->pen_colors[pen_number]=color;
5650 pen_id=(unsigned int) pen_number;
5651 draw_info.stencil=OpaqueStencil;
5654 case DrawStippleCommand:
5666 filename[MaxTextExtent] = "\0";
5683 Select a command from the pop-up menu.
5685 StipplesMenu[7]="Open...";
5686 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5690 if (stipple != (Pixmap) NULL)
5691 (void) XFreePixmap(display,stipple);
5692 stipple=(Pixmap) NULL;
5699 stipple=XCreateBitmapFromData(display,root_window,
5700 (char *) BricksBitmap,BricksWidth,BricksHeight);
5705 stipple=XCreateBitmapFromData(display,root_window,
5706 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5711 stipple=XCreateBitmapFromData(display,root_window,
5712 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5717 stipple=XCreateBitmapFromData(display,root_window,
5718 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5723 stipple=XCreateBitmapFromData(display,root_window,
5724 (char *) WavyBitmap,WavyWidth,WavyHeight);
5729 stipple=XCreateBitmapFromData(display,root_window,
5730 (char *) HighlightBitmap,HighlightWidth,
5737 stipple=XCreateBitmapFromData(display,root_window,
5738 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5744 XFileBrowserWidget(display,windows,"Stipple",filename);
5745 if (*filename == '\0')
5750 XSetCursorState(display,windows,MagickTrue);
5751 XCheckRefreshWindows(display,windows);
5752 image_info=AcquireImageInfo();
5753 (void) CopyMagickString(image_info->filename,filename,
5755 stipple_image=ReadImage(image_info,exception);
5756 CatchException(exception);
5757 XSetCursorState(display,windows,MagickFalse);
5758 if (stipple_image == (Image *) NULL)
5760 (void) AcquireUniqueFileResource(filename);
5761 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5763 (void) WriteImage(image_info,stipple_image,exception);
5764 stipple_image=DestroyImage(stipple_image);
5765 image_info=DestroyImageInfo(image_info);
5766 status=XReadBitmapFile(display,root_window,filename,&width,
5767 &height,&stipple,&x,&y);
5768 (void) RelinquishUniqueFileResource(filename);
5769 if ((status != BitmapSuccess) != 0)
5770 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5774 case DrawWidthCommand:
5777 width[MaxTextExtent] = "0";
5792 Select a command from the pop-up menu.
5794 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5800 line_width=(unsigned int) StringToUnsignedLong(
5804 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5808 line_width=(unsigned int) StringToUnsignedLong(width);
5811 case DrawUndoCommand:
5813 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5817 case DrawHelpCommand:
5819 XTextViewWidget(display,resource_info,windows,MagickFalse,
5820 "Help Viewer - Image Rotation",ImageDrawHelp);
5821 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5824 case DrawDismissCommand:
5836 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5843 if (event.xbutton.button != Button1)
5845 if (event.xbutton.window != windows->image.id)
5864 if (event.xkey.window != windows->image.id)
5867 Respond to a user key press.
5869 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5870 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5871 switch ((int) key_symbol)
5886 XTextViewWidget(display,resource_info,windows,MagickFalse,
5887 "Help Viewer - Image Rotation",ImageDrawHelp);
5892 (void) XBell(display,0);
5901 Map and unmap Info widget as text cursor crosses its boundaries.
5905 if (windows->info.mapped != MagickFalse)
5907 if ((x < (int) (windows->info.x+windows->info.width)) &&
5908 (y < (int) (windows->info.y+windows->info.height)))
5909 (void) XWithdrawWindow(display,windows->info.id,
5910 windows->info.screen);
5913 if ((x > (int) (windows->info.x+windows->info.width)) ||
5914 (y > (int) (windows->info.y+windows->info.height)))
5915 (void) XMapWindow(display,windows->info.id);
5919 } while ((state & ExitState) == 0);
5920 (void) XSelectInput(display,windows->image.id,
5921 windows->image.attributes.event_mask);
5922 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5923 if ((state & EscapeState) != 0)
5926 Draw element as pointer moves until the button is released.
5934 rectangle_info.x=(ssize_t) x;
5935 rectangle_info.y=(ssize_t) y;
5936 rectangle_info.width=0;
5937 rectangle_info.height=0;
5938 number_coordinates=1;
5939 coordinate_info->x=x;
5940 coordinate_info->y=y;
5941 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5950 if (number_coordinates > 1)
5952 (void) XDrawLines(display,windows->image.id,
5953 windows->image.highlight_context,coordinate_info,
5954 number_coordinates,CoordModeOrigin);
5955 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5956 coordinate_info[number_coordinates-1].x,
5957 coordinate_info[number_coordinates-1].y);
5958 XInfoWidget(display,windows,text);
5967 Display angle of the line.
5969 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5970 line_info.y1),(double) (line_info.x2-line_info.x1)));
5971 (void) FormatLocaleString(text,MaxTextExtent," %g",
5973 XInfoWidget(display,windows,text);
5974 XHighlightLine(display,windows->image.id,
5975 windows->image.highlight_context,&line_info);
5978 if (windows->info.mapped != MagickFalse)
5979 (void) XWithdrawWindow(display,windows->info.id,
5980 windows->info.screen);
5983 case RectangleElement:
5984 case FillRectangleElement:
5986 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5989 Display info and draw drawing rectangle.
5991 (void) FormatLocaleString(text,MaxTextExtent,
5992 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5993 (double) rectangle_info.height,(double) rectangle_info.x,
5994 (double) rectangle_info.y);
5995 XInfoWidget(display,windows,text);
5996 XHighlightRectangle(display,windows->image.id,
5997 windows->image.highlight_context,&rectangle_info);
6000 if (windows->info.mapped != MagickFalse)
6001 (void) XWithdrawWindow(display,windows->info.id,
6002 windows->info.screen);
6006 case FillCircleElement:
6007 case EllipseElement:
6008 case FillEllipseElement:
6010 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6013 Display info and draw drawing rectangle.
6015 (void) FormatLocaleString(text,MaxTextExtent,
6016 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6017 (double) rectangle_info.height,(double) rectangle_info.x,
6018 (double) rectangle_info.y);
6019 XInfoWidget(display,windows,text);
6020 XHighlightEllipse(display,windows->image.id,
6021 windows->image.highlight_context,&rectangle_info);
6024 if (windows->info.mapped != MagickFalse)
6025 (void) XWithdrawWindow(display,windows->info.id,
6026 windows->info.screen);
6029 case PolygonElement:
6030 case FillPolygonElement:
6032 if (number_coordinates > 1)
6033 (void) XDrawLines(display,windows->image.id,
6034 windows->image.highlight_context,coordinate_info,
6035 number_coordinates,CoordModeOrigin);
6039 Display angle of the line.
6041 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6042 line_info.y1),(double) (line_info.x2-line_info.x1)));
6043 (void) FormatLocaleString(text,MaxTextExtent," %g",
6045 XInfoWidget(display,windows,text);
6046 XHighlightLine(display,windows->image.id,
6047 windows->image.highlight_context,&line_info);
6050 if (windows->info.mapped != MagickFalse)
6051 (void) XWithdrawWindow(display,windows->info.id,
6052 windows->info.screen);
6057 Wait for next event.
6059 XScreenEvent(display,windows,&event);
6065 if (number_coordinates > 1)
6066 (void) XDrawLines(display,windows->image.id,
6067 windows->image.highlight_context,coordinate_info,
6068 number_coordinates,CoordModeOrigin);
6074 XHighlightLine(display,windows->image.id,
6075 windows->image.highlight_context,&line_info);
6078 case RectangleElement:
6079 case FillRectangleElement:
6081 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6082 XHighlightRectangle(display,windows->image.id,
6083 windows->image.highlight_context,&rectangle_info);
6087 case FillCircleElement:
6088 case EllipseElement:
6089 case FillEllipseElement:
6091 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6092 XHighlightEllipse(display,windows->image.id,
6093 windows->image.highlight_context,&rectangle_info);
6096 case PolygonElement:
6097 case FillPolygonElement:
6099 if (number_coordinates > 1)
6100 (void) XDrawLines(display,windows->image.id,
6101 windows->image.highlight_context,coordinate_info,
6102 number_coordinates,CoordModeOrigin);
6104 XHighlightLine(display,windows->image.id,
6105 windows->image.highlight_context,&line_info);
6116 User has committed to element.
6118 line_info.x2=event.xbutton.x;
6119 line_info.y2=event.xbutton.y;
6120 rectangle_info.x=(ssize_t) event.xbutton.x;
6121 rectangle_info.y=(ssize_t) event.xbutton.y;
6122 coordinate_info[number_coordinates].x=event.xbutton.x;
6123 coordinate_info[number_coordinates].y=event.xbutton.y;
6124 if (((element != PolygonElement) &&
6125 (element != FillPolygonElement)) || (distance <= 9))
6130 number_coordinates++;
6131 if (number_coordinates < (int) max_coordinates)
6133 line_info.x1=event.xbutton.x;
6134 line_info.y1=event.xbutton.y;
6137 max_coordinates<<=1;
6138 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6139 max_coordinates,sizeof(*coordinate_info));
6140 if (coordinate_info == (XPoint *) NULL)
6141 (void) ThrowMagickException(exception,GetMagickModule(),
6142 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6149 if (event.xmotion.window != windows->image.id)
6151 if (element != PointElement)
6153 line_info.x2=event.xmotion.x;
6154 line_info.y2=event.xmotion.y;
6155 rectangle_info.x=(ssize_t) event.xmotion.x;
6156 rectangle_info.y=(ssize_t) event.xmotion.y;
6159 coordinate_info[number_coordinates].x=event.xbutton.x;
6160 coordinate_info[number_coordinates].y=event.xbutton.y;
6161 number_coordinates++;
6162 if (number_coordinates < (int) max_coordinates)
6164 max_coordinates<<=1;
6165 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6166 max_coordinates,sizeof(*coordinate_info));
6167 if (coordinate_info == (XPoint *) NULL)
6168 (void) ThrowMagickException(exception,GetMagickModule(),
6169 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6176 Check boundary conditions.
6178 if (line_info.x2 < 0)
6181 if (line_info.x2 > (int) windows->image.width)
6182 line_info.x2=(short) windows->image.width;
6183 if (line_info.y2 < 0)
6186 if (line_info.y2 > (int) windows->image.height)
6187 line_info.y2=(short) windows->image.height;
6188 distance=(unsigned int)
6189 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6190 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6191 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6192 ((state & ExitState) != 0))
6194 if (rectangle_info.x < 0)
6197 if (rectangle_info.x > (ssize_t) windows->image.width)
6198 rectangle_info.x=(ssize_t) windows->image.width;
6199 if ((int) rectangle_info.x < x)
6200 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6203 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6204 rectangle_info.x=(ssize_t) x;
6206 if (rectangle_info.y < 0)
6209 if (rectangle_info.y > (ssize_t) windows->image.height)
6210 rectangle_info.y=(ssize_t) windows->image.height;
6211 if ((int) rectangle_info.y < y)
6212 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6215 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6216 rectangle_info.y=(ssize_t) y;
6219 } while ((state & ExitState) == 0);
6220 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6221 if ((element == PointElement) || (element == PolygonElement) ||
6222 (element == FillPolygonElement))
6225 Determine polygon bounding box.
6227 rectangle_info.x=(ssize_t) coordinate_info->x;
6228 rectangle_info.y=(ssize_t) coordinate_info->y;
6229 x=coordinate_info->x;
6230 y=coordinate_info->y;
6231 for (i=1; i < number_coordinates; i++)
6233 if (coordinate_info[i].x > x)
6234 x=coordinate_info[i].x;
6235 if (coordinate_info[i].y > y)
6236 y=coordinate_info[i].y;
6237 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6238 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6239 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6240 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6242 rectangle_info.width=(size_t) (x-rectangle_info.x);
6243 rectangle_info.height=(size_t) (y-rectangle_info.y);
6244 for (i=0; i < number_coordinates; i++)
6246 coordinate_info[i].x-=rectangle_info.x;
6247 coordinate_info[i].y-=rectangle_info.y;
6254 if ((element == RectangleElement) ||
6255 (element == CircleElement) || (element == EllipseElement))
6257 rectangle_info.width--;
6258 rectangle_info.height--;
6261 Drawing is relative to image configuration.
6263 draw_info.x=(int) rectangle_info.x;
6264 draw_info.y=(int) rectangle_info.y;
6265 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6267 width=(unsigned int) (*image)->columns;
6268 height=(unsigned int) (*image)->rows;
6271 if (windows->image.crop_geometry != (char *) NULL)
6272 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6273 draw_info.x+=windows->image.x-(line_width/2);
6274 if (draw_info.x < 0)
6276 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6277 draw_info.y+=windows->image.y-(line_width/2);
6278 if (draw_info.y < 0)
6280 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6281 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6282 if (draw_info.width > (unsigned int) (*image)->columns)
6283 draw_info.width=(unsigned int) (*image)->columns;
6284 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6285 if (draw_info.height > (unsigned int) (*image)->rows)
6286 draw_info.height=(unsigned int) (*image)->rows;
6287 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6288 width*draw_info.width/windows->image.ximage->width,
6289 height*draw_info.height/windows->image.ximage->height,
6290 draw_info.x+x,draw_info.y+y);
6292 Initialize drawing attributes.
6294 draw_info.degrees=0.0;
6295 draw_info.element=element;
6296 draw_info.stipple=stipple;
6297 draw_info.line_width=line_width;
6298 draw_info.line_info=line_info;
6299 if (line_info.x1 > (int) (line_width/2))
6300 draw_info.line_info.x1=(short) line_width/2;
6301 if (line_info.y1 > (int) (line_width/2))
6302 draw_info.line_info.y1=(short) line_width/2;
6303 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6304 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6305 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6307 draw_info.line_info.x2=(-draw_info.line_info.x2);
6308 draw_info.line_info.y2=(-draw_info.line_info.y2);
6310 if (draw_info.line_info.x2 < 0)
6312 draw_info.line_info.x2=(-draw_info.line_info.x2);
6313 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6315 if (draw_info.line_info.y2 < 0)
6317 draw_info.line_info.y2=(-draw_info.line_info.y2);
6318 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6320 draw_info.rectangle_info=rectangle_info;
6321 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6322 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6323 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6324 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6325 draw_info.number_coordinates=(unsigned int) number_coordinates;
6326 draw_info.coordinate_info=coordinate_info;
6327 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6329 Draw element on image.
6331 XSetCursorState(display,windows,MagickTrue);
6332 XCheckRefreshWindows(display,windows);
6333 status=XDrawImage(display,windows->pixel_info,&draw_info,*image);
6334 XSetCursorState(display,windows,MagickFalse);
6336 Update image colormap and return to image drawing.
6338 XConfigureImageColormap(display,resource_info,windows,*image);
6339 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6341 XSetCursorState(display,windows,MagickFalse);
6342 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6343 return(status != 0 ? MagickTrue : MagickFalse);
6347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6351 + X D r a w P a n R e c t a n g l e %
6355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6357 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6358 % displays a zoom image and the rectangle shows which portion of the image is
6359 % displayed in the Image window.
6361 % The format of the XDrawPanRectangle method is:
6363 % XDrawPanRectangle(Display *display,XWindows *windows)
6365 % A description of each parameter follows:
6367 % o display: Specifies a connection to an X server; returned from
6370 % o windows: Specifies a pointer to a XWindows structure.
6373 static void XDrawPanRectangle(Display *display,XWindows *windows)
6382 Determine dimensions of the panning rectangle.
6384 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
6385 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6386 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6387 scale_factor=(MagickRealType)
6388 windows->pan.height/windows->image.ximage->height;
6389 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6390 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6392 Display the panning rectangle.
6394 (void) XClearWindow(display,windows->pan.id);
6395 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6404 + X I m a g e C a c h e %
6408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6410 % XImageCache() handles the creation, manipulation, and destruction of the
6411 % image cache (undo and redo buffers).
6413 % The format of the XImageCache method is:
6415 % void XImageCache(Display *display,XResourceInfo *resource_info,
6416 % XWindows *windows,const CommandType command,Image **image,
6417 % ExceptionInfo *exception)
6419 % A description of each parameter follows:
6421 % o display: Specifies a connection to an X server; returned from
6424 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6426 % o windows: Specifies a pointer to a XWindows structure.
6428 % o command: Specifies a command to perform.
6430 % o image: the image; XImageCache may transform the image and return a new
6433 % o exception: return any errors or warnings in this structure.
6436 static void XImageCache(Display *display,XResourceInfo *resource_info,
6437 XWindows *windows,const CommandType command,Image **image,
6438 ExceptionInfo *exception)
6444 *redo_image = (Image *) NULL,
6445 *undo_image = (Image *) NULL;
6449 case FreeBuffersCommand:
6452 Free memory from the undo and redo cache.
6454 while (undo_image != (Image *) NULL)
6456 cache_image=undo_image;
6457 undo_image=GetPreviousImageInList(undo_image);
6458 cache_image->list=DestroyImage(cache_image->list);
6459 cache_image=DestroyImage(cache_image);
6461 undo_image=NewImageList();
6462 if (redo_image != (Image *) NULL)
6463 redo_image=DestroyImage(redo_image);
6464 redo_image=NewImageList();
6470 image_geometry[MaxTextExtent];
6473 Undo the last image transformation.
6475 if (undo_image == (Image *) NULL)
6477 (void) XBell(display,0);
6480 cache_image=undo_image;
6481 undo_image=GetPreviousImageInList(undo_image);
6482 windows->image.window_changes.width=(int) cache_image->columns;
6483 windows->image.window_changes.height=(int) cache_image->rows;
6484 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6485 windows->image.ximage->width,windows->image.ximage->height);
6486 (void) TransformImage(image,windows->image.crop_geometry,image_geometry);
6487 if (windows->image.crop_geometry != (char *) NULL)
6488 windows->image.crop_geometry=(char *)
6489 RelinquishMagickMemory(windows->image.crop_geometry);
6490 windows->image.crop_geometry=cache_image->geometry;
6491 if (redo_image != (Image *) NULL)
6492 redo_image=DestroyImage(redo_image);
6493 redo_image=(*image);
6494 *image=cache_image->list;
6495 cache_image=DestroyImage(cache_image);
6496 if (windows->image.orphan != MagickFalse)
6498 XConfigureImageColormap(display,resource_info,windows,*image);
6499 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6505 case HalfSizeCommand:
6506 case OriginalSizeCommand:
6507 case DoubleSizeCommand:
6514 case RotateRightCommand:
6515 case RotateLeftCommand:
6520 case ContrastStretchCommand:
6521 case SigmoidalContrastCommand:
6522 case NormalizeCommand:
6523 case EqualizeCommand:
6525 case SaturationCommand:
6526 case BrightnessCommand:
6530 case GrayscaleCommand:
6532 case QuantizeCommand:
6533 case DespeckleCommand:
6535 case ReduceNoiseCommand:
6536 case AddNoiseCommand:
6537 case SharpenCommand:
6539 case ThresholdCommand:
6540 case EdgeDetectCommand:
6544 case SegmentCommand:
6545 case SolarizeCommand:
6546 case SepiaToneCommand:
6548 case ImplodeCommand:
6549 case VignetteCommand:
6551 case OilPaintCommand:
6552 case CharcoalDrawCommand:
6553 case AnnotateCommand:
6554 case AddBorderCommand:
6555 case AddFrameCommand:
6556 case CompositeCommand:
6557 case CommentCommand:
6559 case RegionofInterestCommand:
6560 case SaveToUndoBufferCommand:
6569 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelPacket));
6570 if (undo_image != (Image *) NULL)
6573 Ensure the undo cache has enough memory available.
6575 previous_image=undo_image;
6576 while (previous_image != (Image *) NULL)
6578 bytes+=previous_image->list->columns*previous_image->list->rows*
6579 sizeof(PixelPacket);
6580 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6582 previous_image=GetPreviousImageInList(previous_image);
6585 bytes-=previous_image->list->columns*previous_image->list->rows*
6586 sizeof(PixelPacket);
6587 if (previous_image == undo_image)
6588 undo_image=NewImageList();
6590 previous_image->next->previous=NewImageList();
6593 while (previous_image != (Image *) NULL)
6596 Delete any excess memory from undo cache.
6598 cache_image=previous_image;
6599 previous_image=GetPreviousImageInList(previous_image);
6600 cache_image->list=DestroyImage(cache_image->list);
6601 cache_image=DestroyImage(cache_image);
6604 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6607 Save image before transformations are applied.
6609 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6610 if (cache_image == (Image *) NULL)
6612 XSetCursorState(display,windows,MagickTrue);
6613 XCheckRefreshWindows(display,windows);
6614 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6615 XSetCursorState(display,windows,MagickFalse);
6616 if (cache_image->list == (Image *) NULL)
6618 cache_image=DestroyImage(cache_image);
6621 cache_image->columns=(size_t) windows->image.ximage->width;
6622 cache_image->rows=(size_t) windows->image.ximage->height;
6623 cache_image->geometry=windows->image.crop_geometry;
6624 if (windows->image.crop_geometry != (char *) NULL)
6626 cache_image->geometry=AcquireString((char *) NULL);
6627 (void) CopyMagickString(cache_image->geometry,
6628 windows->image.crop_geometry,MaxTextExtent);
6630 if (undo_image == (Image *) NULL)
6632 undo_image=cache_image;
6635 undo_image->next=cache_image;
6636 undo_image->next->previous=undo_image;
6637 undo_image=undo_image->next;
6643 if (command == RedoCommand)
6646 Redo the last image transformation.
6648 if (redo_image == (Image *) NULL)
6650 (void) XBell(display,0);
6653 windows->image.window_changes.width=(int) redo_image->columns;
6654 windows->image.window_changes.height=(int) redo_image->rows;
6655 if (windows->image.crop_geometry != (char *) NULL)
6656 windows->image.crop_geometry=(char *)
6657 RelinquishMagickMemory(windows->image.crop_geometry);
6658 windows->image.crop_geometry=redo_image->geometry;
6659 *image=DestroyImage(*image);
6661 redo_image=NewImageList();
6662 if (windows->image.orphan != MagickFalse)
6664 XConfigureImageColormap(display,resource_info,windows,*image);
6665 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6668 if (command != InfoCommand)
6673 XSetCursorState(display,windows,MagickTrue);
6674 XCheckRefreshWindows(display,windows);
6675 XDisplayImageInfo(display,resource_info,windows,undo_image,*image);
6676 XSetCursorState(display,windows,MagickFalse);
6680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6684 + X I m a g e W i n d o w C o m m a n d %
6688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6690 % XImageWindowCommand() makes a transform to the image or Image window as
6691 % specified by a user menu button or keyboard command.
6693 % The format of the XImageWindowCommand method is:
6695 % CommandType XImageWindowCommand(Display *display,
6696 % XResourceInfo *resource_info,XWindows *windows,
6697 % const MagickStatusType state,KeySym key_symbol,Image **image,
6698 % ExceptionInfo *exception)
6700 % A description of each parameter follows:
6702 % o nexus: Method XImageWindowCommand returns an image when the
6703 % user chooses 'Open Image' from the command menu. Otherwise a null
6704 % image is returned.
6706 % o display: Specifies a connection to an X server; returned from
6709 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6711 % o windows: Specifies a pointer to a XWindows structure.
6713 % o state: key mask.
6715 % o key_symbol: Specifies a command to perform.
6717 % o image: the image; XImageWIndowCommand may transform the image and
6718 % return a new image pointer.
6720 % o exception: return any errors or warnings in this structure.
6723 static CommandType XImageWindowCommand(Display *display,
6724 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6725 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6728 delta[MaxTextExtent] = "";
6731 Digits[] = "01234567890";
6736 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6738 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6741 resource_info->quantum=1;
6743 last_symbol=key_symbol;
6744 delta[strlen(delta)+1]='\0';
6745 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6746 resource_info->quantum=StringToLong(delta);
6747 return(NullCommand);
6749 last_symbol=key_symbol;
6750 if (resource_info->immutable)
6753 Virtual image window has a restricted command set.
6758 return(InfoCommand);
6761 return(PrintCommand);
6763 return(NextCommand);
6766 return(QuitCommand);
6770 return(NullCommand);
6772 switch ((int) key_symbol)
6776 if ((state & ControlMask) == 0)
6778 return(OpenCommand);
6781 return(NextCommand);
6783 return(FormerCommand);
6786 if ((state & Mod1Mask) != 0)
6787 return(SwirlCommand);
6788 if ((state & ControlMask) == 0)
6789 return(ShearCommand);
6790 return(SaveCommand);
6795 if ((state & Mod1Mask) != 0)
6796 return(OilPaintCommand);
6797 if ((state & Mod4Mask) != 0)
6798 return(ColorCommand);
6799 if ((state & ControlMask) == 0)
6800 return(NullCommand);
6801 return(PrintCommand);
6805 if ((state & Mod4Mask) != 0)
6806 return(DrawCommand);
6807 if ((state & ControlMask) == 0)
6808 return(NullCommand);
6809 return(DeleteCommand);
6813 if ((state & ControlMask) == 0)
6814 return(NullCommand);
6815 return(SelectCommand);
6819 if ((state & ControlMask) == 0)
6820 return(NullCommand);
6825 return(QuitCommand);
6829 if ((state & ControlMask) == 0)
6830 return(NullCommand);
6831 return(UndoCommand);
6836 if ((state & ControlMask) == 0)
6837 return(RollCommand);
6838 return(RedoCommand);
6842 if ((state & ControlMask) == 0)
6843 return(NullCommand);
6848 if ((state & Mod1Mask) != 0)
6849 return(CharcoalDrawCommand);
6850 if ((state & ControlMask) == 0)
6851 return(CropCommand);
6852 return(CopyCommand);
6857 if ((state & Mod4Mask) != 0)
6858 return(CompositeCommand);
6859 if ((state & ControlMask) == 0)
6860 return(FlipCommand);
6861 return(PasteCommand);
6864 return(HalfSizeCommand);
6866 return(OriginalSizeCommand);
6868 return(DoubleSizeCommand);
6870 return(ResizeCommand);
6872 return(RefreshCommand);
6873 case XK_bracketleft:
6874 return(ChopCommand);
6876 return(FlopCommand);
6878 return(RotateRightCommand);
6880 return(RotateLeftCommand);
6882 return(RotateCommand);
6884 return(TrimCommand);
6888 return(SaturationCommand);
6890 return(BrightnessCommand);
6892 return(GammaCommand);
6894 return(SpiffCommand);
6896 return(DullCommand);
6898 return(NormalizeCommand);
6900 return(EqualizeCommand);
6902 return(NegateCommand);
6904 return(GrayscaleCommand);
6906 return(QuantizeCommand);
6908 return(DespeckleCommand);
6910 return(EmbossCommand);
6912 return(ReduceNoiseCommand);
6914 return(AddNoiseCommand);
6916 return(SharpenCommand);
6918 return(BlurCommand);
6920 return(ThresholdCommand);
6922 return(EdgeDetectCommand);
6924 return(SpreadCommand);
6926 return(ShadeCommand);
6928 return(RaiseCommand);
6930 return(SegmentCommand);
6933 if ((state & Mod1Mask) == 0)
6934 return(NullCommand);
6935 return(ImplodeCommand);
6939 if ((state & Mod1Mask) == 0)
6940 return(NullCommand);
6941 return(WaveCommand);
6945 if ((state & Mod4Mask) == 0)
6946 return(NullCommand);
6947 return(MatteCommand);
6951 if ((state & Mod4Mask) == 0)
6952 return(NullCommand);
6953 return(AddBorderCommand);
6957 if ((state & Mod4Mask) == 0)
6958 return(NullCommand);
6959 return(AddFrameCommand);
6963 if ((state & Mod4Mask) == 0)
6964 return(NullCommand);
6965 return(CommentCommand);
6969 if ((state & Mod1Mask) != 0)
6970 return(ApplyCommand);
6971 if ((state & Mod4Mask) != 0)
6972 return(AnnotateCommand);
6973 if ((state & ControlMask) == 0)
6974 return(NullCommand);
6975 return(RegionofInterestCommand);
6978 return(InfoCommand);
6980 return(ZoomCommand);
6983 if ((state & ShiftMask) == 0)
6984 return(NullCommand);
6985 return(ShowPreviewCommand);
6988 return(LaunchCommand);
6990 return(HelpCommand);
6992 return(BrowseDocumentationCommand);
6995 (void) XMapRaised(display,windows->command.id);
6996 return(NullCommand);
7003 XTranslateImage(display,windows,*image,key_symbol);
7004 return(NullCommand);
7015 if ((state & Mod1Mask) != 0)
7021 Trim one pixel from edge of image.
7025 crop_info.width=(size_t) windows->image.ximage->width;
7026 crop_info.height=(size_t) windows->image.ximage->height;
7027 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7029 if (resource_info->quantum >= (int) crop_info.height)
7030 resource_info->quantum=(int) crop_info.height-1;
7031 crop_info.height-=resource_info->quantum;
7033 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7035 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7036 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7037 crop_info.y+=resource_info->quantum;
7038 crop_info.height-=resource_info->quantum;
7040 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7042 if (resource_info->quantum >= (int) crop_info.width)
7043 resource_info->quantum=(int) crop_info.width-1;
7044 crop_info.width-=resource_info->quantum;
7046 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7048 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7049 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7050 crop_info.x+=resource_info->quantum;
7051 crop_info.width-=resource_info->quantum;
7053 if ((int) (windows->image.x+windows->image.width) >
7054 (int) crop_info.width)
7055 windows->image.x=(int) (crop_info.width-windows->image.width);
7056 if ((int) (windows->image.y+windows->image.height) >
7057 (int) crop_info.height)
7058 windows->image.y=(int) (crop_info.height-windows->image.height);
7059 XSetCropGeometry(display,windows,&crop_info,*image);
7060 windows->image.window_changes.width=(int) crop_info.width;
7061 windows->image.window_changes.height=(int) crop_info.height;
7062 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7063 (void) XConfigureImage(display,resource_info,windows,*image,
7065 return(NullCommand);
7067 XTranslateImage(display,windows,*image,key_symbol);
7068 return(NullCommand);
7071 return(NullCommand);
7073 return(NullCommand);
7077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7081 + X M a g i c k C o m m a n d %
7085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7087 % XMagickCommand() makes a transform to the image or Image window as
7088 % specified by a user menu button or keyboard command.
7090 % The format of the XMagickCommand method is:
7092 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7093 % XWindows *windows,const CommandType command,Image **image,
7094 % ExceptionInfo *exception)
7096 % A description of each parameter follows:
7098 % o display: Specifies a connection to an X server; returned from
7101 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7103 % o windows: Specifies a pointer to a XWindows structure.
7105 % o command: Specifies a command to perform.
7107 % o image: the image; XMagickCommand may transform the image and return a
7108 % new image pointer.
7110 % o exception: return any errors or warnings in this structure.
7113 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7114 XWindows *windows,const CommandType command,Image **image,
7115 ExceptionInfo *exception)
7118 filename[MaxTextExtent],
7119 geometry[MaxTextExtent],
7120 modulate_factors[MaxTextExtent];
7149 color[MaxTextExtent] = "gray";
7156 Process user command.
7158 XCheckRefreshWindows(display,windows);
7159 XImageCache(display,resource_info,windows,command,image,exception);
7160 nexus=NewImageList();
7161 windows->image.window_changes.width=windows->image.ximage->width;
7162 windows->image.window_changes.height=windows->image.ximage->height;
7163 image_info=CloneImageInfo(resource_info->image_info);
7164 SetGeometryInfo(&geometry_info);
7165 GetQuantizeInfo(&quantize_info);
7173 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7181 for (i=0; i < resource_info->quantum; i++)
7182 XClientMessage(display,windows->image.id,windows->im_protocols,
7183 windows->im_next_image,CurrentTime);
7189 Display former image.
7191 for (i=0; i < resource_info->quantum; i++)
7192 XClientMessage(display,windows->image.id,windows->im_protocols,
7193 windows->im_former_image,CurrentTime);
7204 status=chdir(resource_info->home_directory);
7206 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7207 "UnableToOpenFile","%s",resource_info->home_directory);
7208 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7216 status=XSaveImage(display,resource_info,windows,*image,exception);
7217 if (status == MagickFalse)
7220 message[MaxTextExtent];
7222 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7223 exception->reason != (char *) NULL ? exception->reason : "",
7224 exception->description != (char *) NULL ? exception->description :
7226 XNoticeWidget(display,windows,"Unable to save file:",message);
7236 status=XPrintImage(display,resource_info,windows,*image,exception);
7237 if (status == MagickFalse)
7240 message[MaxTextExtent];
7242 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7243 exception->reason != (char *) NULL ? exception->reason : "",
7244 exception->description != (char *) NULL ? exception->description :
7246 XNoticeWidget(display,windows,"Unable to print file:",message);
7254 filename[MaxTextExtent] = "\0";
7259 XFileBrowserWidget(display,windows,"Delete",filename);
7260 if (*filename == '\0')
7262 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
7263 if (status != MagickFalse)
7264 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7273 color[MaxTextExtent] = "gray",
7274 geometry[MaxTextExtent] = "640x480";
7277 *format = "gradient";
7280 Query user for canvas geometry.
7282 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7284 if (*geometry == '\0')
7288 XColorBrowserWidget(display,windows,"Select",color);
7294 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7295 "%s:%s",format,color);
7296 (void) CloneString(&image_info->size,geometry);
7297 nexus=ReadImage(image_info,exception);
7298 CatchException(exception);
7299 XClientMessage(display,windows->image.id,windows->im_protocols,
7300 windows->im_next_image,CurrentTime);
7303 case VisualDirectoryCommand:
7306 Visual Image directory.
7308 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7316 if (resource_info->confirm_exit == MagickFalse)
7317 XClientMessage(display,windows->image.id,windows->im_protocols,
7318 windows->im_exit,CurrentTime);
7325 Confirm program exit.
7327 status=XConfirmWidget(display,windows,"Do you really want to exit",
7328 resource_info->client_name);
7330 XClientMessage(display,windows->image.id,windows->im_protocols,
7331 windows->im_exit,CurrentTime);
7340 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7348 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7357 status=XPasteImage(display,resource_info,windows,*image,exception);
7358 if (status == MagickFalse)
7360 XNoticeWidget(display,windows,"Unable to paste X image",
7361 (*image)->filename);
7366 case HalfSizeCommand:
7371 windows->image.window_changes.width=windows->image.ximage->width/2;
7372 windows->image.window_changes.height=windows->image.ximage->height/2;
7373 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7376 case OriginalSizeCommand:
7379 Original image size.
7381 windows->image.window_changes.width=(int) (*image)->columns;
7382 windows->image.window_changes.height=(int) (*image)->rows;
7383 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7386 case DoubleSizeCommand:
7389 Double the image size.
7391 windows->image.window_changes.width=windows->image.ximage->width << 1;
7392 windows->image.window_changes.height=windows->image.ximage->height << 1;
7393 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7412 width=(size_t) windows->image.ximage->width;
7413 height=(size_t) windows->image.ximage->height;
7416 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7417 (double) width,(double) height);
7418 status=XDialogWidget(display,windows,"Resize",
7419 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7420 if (*geometry == '\0')
7423 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7424 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7425 windows->image.window_changes.width=(int) width;
7426 windows->image.window_changes.height=(int) height;
7427 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7433 image_geometry[MaxTextExtent];
7435 if ((windows->image.crop_geometry == (char *) NULL) &&
7436 ((int) (*image)->columns == windows->image.ximage->width) &&
7437 ((int) (*image)->rows == windows->image.ximage->height))
7440 Apply size transforms to image.
7442 XSetCursorState(display,windows,MagickTrue);
7443 XCheckRefreshWindows(display,windows);
7445 Crop and/or scale displayed image.
7447 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7448 windows->image.ximage->width,windows->image.ximage->height);
7449 (void) TransformImage(image,windows->image.crop_geometry,image_geometry);
7450 if (windows->image.crop_geometry != (char *) NULL)
7451 windows->image.crop_geometry=(char *)
7452 RelinquishMagickMemory(windows->image.crop_geometry);
7455 XConfigureImageColormap(display,resource_info,windows,*image);
7456 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7459 case RefreshCommand:
7461 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7464 case RestoreCommand:
7467 Restore Image window to its original size.
7469 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7470 (windows->image.height == (unsigned int) (*image)->rows) &&
7471 (windows->image.crop_geometry == (char *) NULL))
7473 (void) XBell(display,0);
7476 windows->image.window_changes.width=(int) (*image)->columns;
7477 windows->image.window_changes.height=(int) (*image)->rows;
7478 if (windows->image.crop_geometry != (char *) NULL)
7480 windows->image.crop_geometry=(char *)
7481 RelinquishMagickMemory(windows->image.crop_geometry);
7482 windows->image.crop_geometry=(char *) NULL;
7486 XConfigureImageColormap(display,resource_info,windows,*image);
7487 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7495 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7504 status=XChopImage(display,resource_info,windows,image,exception);
7505 if (status == MagickFalse)
7507 XNoticeWidget(display,windows,"Unable to cut X image",
7508 (*image)->filename);
7519 Flop image scanlines.
7521 XSetCursorState(display,windows,MagickTrue);
7522 XCheckRefreshWindows(display,windows);
7523 flop_image=FlopImage(*image,exception);
7524 if (flop_image != (Image *) NULL)
7526 *image=DestroyImage(*image);
7529 CatchException(exception);
7530 XSetCursorState(display,windows,MagickFalse);
7531 if (windows->image.crop_geometry != (char *) NULL)
7536 width=(unsigned int) (*image)->columns;
7537 height=(unsigned int) (*image)->rows;
7538 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7540 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7541 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7543 if (windows->image.orphan != MagickFalse)
7545 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7554 Flip image scanlines.
7556 XSetCursorState(display,windows,MagickTrue);
7557 XCheckRefreshWindows(display,windows);
7558 flip_image=FlipImage(*image,exception);
7559 if (flip_image != (Image *) NULL)
7561 *image=DestroyImage(*image);
7564 CatchException(exception);
7565 XSetCursorState(display,windows,MagickFalse);
7566 if (windows->image.crop_geometry != (char *) NULL)
7571 width=(unsigned int) (*image)->columns;
7572 height=(unsigned int) (*image)->rows;
7573 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7575 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7576 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7578 if (windows->image.orphan != MagickFalse)
7580 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7583 case RotateRightCommand:
7586 Rotate image 90 degrees clockwise.
7588 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7589 if (status == MagickFalse)
7591 XNoticeWidget(display,windows,"Unable to rotate X image",
7592 (*image)->filename);
7597 case RotateLeftCommand:
7600 Rotate image 90 degrees counter-clockwise.
7602 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7603 if (status == MagickFalse)
7605 XNoticeWidget(display,windows,"Unable to rotate X image",
7606 (*image)->filename);
7616 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7617 if (status == MagickFalse)
7619 XNoticeWidget(display,windows,"Unable to rotate X image",
7620 (*image)->filename);
7631 geometry[MaxTextExtent] = "45.0x45.0";
7634 Query user for shear color and geometry.
7636 XColorBrowserWidget(display,windows,"Select",color);
7639 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7641 if (*geometry == '\0')
7646 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7648 XSetCursorState(display,windows,MagickTrue);
7649 XCheckRefreshWindows(display,windows);
7650 (void) QueryColorCompliance(color,AllCompliance,
7651 &(*image)->background_color,exception);
7652 flags=ParseGeometry(geometry,&geometry_info);
7653 if ((flags & SigmaValue) == 0)
7654 geometry_info.sigma=geometry_info.rho;
7655 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7657 if (shear_image != (Image *) NULL)
7659 *image=DestroyImage(*image);
7662 CatchException(exception);
7663 XSetCursorState(display,windows,MagickFalse);
7664 if (windows->image.orphan != MagickFalse)
7666 windows->image.window_changes.width=(int) (*image)->columns;
7667 windows->image.window_changes.height=(int) (*image)->rows;
7668 XConfigureImageColormap(display,resource_info,windows,*image);
7669 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7678 geometry[MaxTextExtent] = "+2+2";
7681 Query user for the roll geometry.
7683 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7685 if (*geometry == '\0')
7690 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7692 XSetCursorState(display,windows,MagickTrue);
7693 XCheckRefreshWindows(display,windows);
7694 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7696 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7698 if (roll_image != (Image *) NULL)
7700 *image=DestroyImage(*image);
7703 CatchException(exception);
7704 XSetCursorState(display,windows,MagickFalse);
7705 if (windows->image.orphan != MagickFalse)
7707 windows->image.window_changes.width=(int) (*image)->columns;
7708 windows->image.window_changes.height=(int) (*image)->rows;
7709 XConfigureImageColormap(display,resource_info,windows,*image);
7710 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7716 fuzz[MaxTextExtent];
7719 Query user for the fuzz factor.
7721 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7722 (*image)->fuzz/(QuantumRange+1.0));
7723 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7726 (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0);
7730 status=XTrimImage(display,resource_info,windows,*image,exception);
7731 if (status == MagickFalse)
7733 XNoticeWidget(display,windows,"Unable to trim X image",
7734 (*image)->filename);
7742 hue_percent[MaxTextExtent] = "110";
7745 Query user for percent hue change.
7747 (void) XDialogWidget(display,windows,"Apply",
7748 "Enter percent change in image hue (0-200):",hue_percent);
7749 if (*hue_percent == '\0')
7754 XSetCursorState(display,windows,MagickTrue);
7755 XCheckRefreshWindows(display,windows);
7756 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7757 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7759 (void) ModulateImage(*image,modulate_factors,exception);
7760 XSetCursorState(display,windows,MagickFalse);
7761 if (windows->image.orphan != MagickFalse)
7763 XConfigureImageColormap(display,resource_info,windows,*image);
7764 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7767 case SaturationCommand:
7770 saturation_percent[MaxTextExtent] = "110";
7773 Query user for percent saturation change.
7775 (void) XDialogWidget(display,windows,"Apply",
7776 "Enter percent change in color saturation (0-200):",saturation_percent);
7777 if (*saturation_percent == '\0')
7780 Vary color saturation.
7782 XSetCursorState(display,windows,MagickTrue);
7783 XCheckRefreshWindows(display,windows);
7784 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7785 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7787 (void) ModulateImage(*image,modulate_factors,exception);
7788 XSetCursorState(display,windows,MagickFalse);
7789 if (windows->image.orphan != MagickFalse)
7791 XConfigureImageColormap(display,resource_info,windows,*image);
7792 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7795 case BrightnessCommand:
7798 brightness_percent[MaxTextExtent] = "110";
7801 Query user for percent brightness change.
7803 (void) XDialogWidget(display,windows,"Apply",
7804 "Enter percent change in color brightness (0-200):",brightness_percent);
7805 if (*brightness_percent == '\0')
7808 Vary the color brightness.
7810 XSetCursorState(display,windows,MagickTrue);
7811 XCheckRefreshWindows(display,windows);
7812 (void) CopyMagickString(modulate_factors,brightness_percent,
7814 (void) ModulateImage(*image,modulate_factors,exception);
7815 XSetCursorState(display,windows,MagickFalse);
7816 if (windows->image.orphan != MagickFalse)
7818 XConfigureImageColormap(display,resource_info,windows,*image);
7819 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7825 factor[MaxTextExtent] = "1.6";
7828 Query user for gamma value.
7830 (void) XDialogWidget(display,windows,"Gamma",
7831 "Enter gamma value (e.g. 1.2):",factor);
7832 if (*factor == '\0')
7835 Gamma correct image.
7837 XSetCursorState(display,windows,MagickTrue);
7838 XCheckRefreshWindows(display,windows);
7839 (void) GammaImage(*image,atof(factor),exception);
7840 XSetCursorState(display,windows,MagickFalse);
7841 if (windows->image.orphan != MagickFalse)
7843 XConfigureImageColormap(display,resource_info,windows,*image);
7844 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7850 Sharpen the image contrast.
7852 XSetCursorState(display,windows,MagickTrue);
7853 XCheckRefreshWindows(display,windows);
7854 (void) ContrastImage(*image,MagickTrue,exception);
7855 XSetCursorState(display,windows,MagickFalse);
7856 if (windows->image.orphan != MagickFalse)
7858 XConfigureImageColormap(display,resource_info,windows,*image);
7859 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7865 Dull the image contrast.
7867 XSetCursorState(display,windows,MagickTrue);
7868 XCheckRefreshWindows(display,windows);
7869 (void) ContrastImage(*image,MagickFalse,exception);
7870 XSetCursorState(display,windows,MagickFalse);
7871 if (windows->image.orphan != MagickFalse)
7873 XConfigureImageColormap(display,resource_info,windows,*image);
7874 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7877 case ContrastStretchCommand:
7884 levels[MaxTextExtent] = "1%";
7887 Query user for gamma value.
7889 (void) XDialogWidget(display,windows,"Contrast Stretch",
7890 "Enter black and white points:",levels);
7891 if (*levels == '\0')
7894 Contrast stretch image.
7896 XSetCursorState(display,windows,MagickTrue);
7897 XCheckRefreshWindows(display,windows);
7898 flags=ParseGeometry(levels,&geometry_info);
7899 black_point=geometry_info.rho;
7900 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7901 if ((flags & PercentValue) != 0)
7903 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7904 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7906 white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point;
7907 (void) ContrastStretchImage(*image,black_point,white_point,
7909 XSetCursorState(display,windows,MagickFalse);
7910 if (windows->image.orphan != MagickFalse)
7912 XConfigureImageColormap(display,resource_info,windows,*image);
7913 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7916 case SigmoidalContrastCommand:
7925 levels[MaxTextExtent] = "3x50%";
7928 Query user for gamma value.
7930 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7931 "Enter contrast and midpoint:",levels);
7932 if (*levels == '\0')
7935 Contrast stretch image.
7937 XSetCursorState(display,windows,MagickTrue);
7938 XCheckRefreshWindows(display,windows);
7939 flags=ParseGeometry(levels,&geometry_info);
7940 if ((flags & SigmaValue) == 0)
7941 geometry_info.sigma=1.0*QuantumRange/2.0;
7942 if ((flags & PercentValue) != 0)
7943 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7944 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7945 geometry_info.sigma,exception);
7946 XSetCursorState(display,windows,MagickFalse);
7947 if (windows->image.orphan != MagickFalse)
7949 XConfigureImageColormap(display,resource_info,windows,*image);
7950 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7953 case NormalizeCommand:
7956 Perform histogram normalization on the image.
7958 XSetCursorState(display,windows,MagickTrue);
7959 XCheckRefreshWindows(display,windows);
7960 (void) NormalizeImage(*image,exception);
7961 XSetCursorState(display,windows,MagickFalse);
7962 if (windows->image.orphan != MagickFalse)
7964 XConfigureImageColormap(display,resource_info,windows,*image);
7965 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7968 case EqualizeCommand:
7971 Perform histogram equalization on the image.
7973 XSetCursorState(display,windows,MagickTrue);
7974 XCheckRefreshWindows(display,windows);
7975 (void) EqualizeImage(*image,exception);
7976 XSetCursorState(display,windows,MagickFalse);
7977 if (windows->image.orphan != MagickFalse)
7979 XConfigureImageColormap(display,resource_info,windows,*image);
7980 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7986 Negate colors in image.
7988 XSetCursorState(display,windows,MagickTrue);
7989 XCheckRefreshWindows(display,windows);
7990 (void) NegateImage(*image,MagickFalse,exception);
7991 XSetCursorState(display,windows,MagickFalse);
7992 if (windows->image.orphan != MagickFalse)
7994 XConfigureImageColormap(display,resource_info,windows,*image);
7995 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7998 case GrayscaleCommand:
8001 Convert image to grayscale.
8003 XSetCursorState(display,windows,MagickTrue);
8004 XCheckRefreshWindows(display,windows);
8005 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
8006 GrayscaleType : GrayscaleMatteType,exception);
8007 XSetCursorState(display,windows,MagickFalse);
8008 if (windows->image.orphan != MagickFalse)
8010 XConfigureImageColormap(display,resource_info,windows,*image);
8011 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8020 filename[MaxTextExtent] = "\0";
8023 Request image file name from user.
8025 XFileBrowserWidget(display,windows,"Map",filename);
8026 if (*filename == '\0')
8031 XSetCursorState(display,windows,MagickTrue);
8032 XCheckRefreshWindows(display,windows);
8033 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8034 affinity_image=ReadImage(image_info,exception);
8035 if (affinity_image != (Image *) NULL)
8037 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8038 affinity_image=DestroyImage(affinity_image);
8040 CatchException(exception);
8041 XSetCursorState(display,windows,MagickFalse);
8042 if (windows->image.orphan != MagickFalse)
8044 XConfigureImageColormap(display,resource_info,windows,*image);
8045 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8048 case QuantizeCommand:
8054 colors[MaxTextExtent] = "256";
8057 Query user for maximum number of colors.
8059 status=XDialogWidget(display,windows,"Quantize",
8060 "Maximum number of colors:",colors);
8061 if (*colors == '\0')
8064 Color reduce the image.
8066 XSetCursorState(display,windows,MagickTrue);
8067 XCheckRefreshWindows(display,windows);
8068 quantize_info.number_colors=StringToUnsignedLong(colors);
8069 quantize_info.dither=status != 0 ? MagickTrue : MagickFalse;
8070 (void) QuantizeImage(&quantize_info,*image,exception);
8071 XSetCursorState(display,windows,MagickFalse);
8072 if (windows->image.orphan != MagickFalse)
8074 XConfigureImageColormap(display,resource_info,windows,*image);
8075 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8078 case DespeckleCommand:
8086 XSetCursorState(display,windows,MagickTrue);
8087 XCheckRefreshWindows(display,windows);
8088 despeckle_image=DespeckleImage(*image,exception);
8089 if (despeckle_image != (Image *) NULL)
8091 *image=DestroyImage(*image);
8092 *image=despeckle_image;
8094 CatchException(exception);
8095 XSetCursorState(display,windows,MagickFalse);
8096 if (windows->image.orphan != MagickFalse)
8098 XConfigureImageColormap(display,resource_info,windows,*image);
8099 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8108 radius[MaxTextExtent] = "0.0x1.0";
8111 Query user for emboss radius.
8113 (void) XDialogWidget(display,windows,"Emboss",
8114 "Enter the emboss radius and standard deviation:",radius);
8115 if (*radius == '\0')
8118 Reduce noise in the image.
8120 XSetCursorState(display,windows,MagickTrue);
8121 XCheckRefreshWindows(display,windows);
8122 flags=ParseGeometry(radius,&geometry_info);
8123 if ((flags & SigmaValue) == 0)
8124 geometry_info.sigma=1.0;
8125 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8127 if (emboss_image != (Image *) NULL)
8129 *image=DestroyImage(*image);
8130 *image=emboss_image;
8132 CatchException(exception);
8133 XSetCursorState(display,windows,MagickFalse);
8134 if (windows->image.orphan != MagickFalse)
8136 XConfigureImageColormap(display,resource_info,windows,*image);
8137 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8140 case ReduceNoiseCommand:
8146 radius[MaxTextExtent] = "0";
8149 Query user for noise radius.
8151 (void) XDialogWidget(display,windows,"Reduce Noise",
8152 "Enter the noise radius:",radius);
8153 if (*radius == '\0')
8156 Reduce noise in the image.
8158 XSetCursorState(display,windows,MagickTrue);
8159 XCheckRefreshWindows(display,windows);
8160 flags=ParseGeometry(radius,&geometry_info);
8161 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8162 geometry_info.rho,(size_t) geometry_info.rho,exception);
8163 if (noise_image != (Image *) NULL)
8165 *image=DestroyImage(*image);
8168 CatchException(exception);
8169 XSetCursorState(display,windows,MagickFalse);
8170 if (windows->image.orphan != MagickFalse)
8172 XConfigureImageColormap(display,resource_info,windows,*image);
8173 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8176 case AddNoiseCommand:
8185 noise_type[MaxTextExtent] = "Gaussian";
8188 Add noise to the image.
8190 noises=GetCommandOptions(MagickNoiseOptions);
8191 if (noises == (char **) NULL)
8193 XListBrowserWidget(display,windows,&windows->widget,
8194 (const char **) noises,"Add Noise",
8195 "Select a type of noise to add to your image:",noise_type);
8196 noises=DestroyStringList(noises);
8197 if (*noise_type == '\0')
8199 XSetCursorState(display,windows,MagickTrue);
8200 XCheckRefreshWindows(display,windows);
8201 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8202 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8203 if (noise_image != (Image *) NULL)
8205 *image=DestroyImage(*image);
8208 CatchException(exception);
8209 XSetCursorState(display,windows,MagickFalse);
8210 if (windows->image.orphan != MagickFalse)
8212 XConfigureImageColormap(display,resource_info,windows,*image);
8213 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8216 case SharpenCommand:
8222 radius[MaxTextExtent] = "0.0x1.0";
8225 Query user for sharpen radius.
8227 (void) XDialogWidget(display,windows,"Sharpen",
8228 "Enter the sharpen radius and standard deviation:",radius);
8229 if (*radius == '\0')
8232 Sharpen image scanlines.
8234 XSetCursorState(display,windows,MagickTrue);
8235 XCheckRefreshWindows(display,windows);
8236 flags=ParseGeometry(radius,&geometry_info);
8237 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8238 geometry_info.xi,exception);
8239 if (sharp_image != (Image *) NULL)
8241 *image=DestroyImage(*image);
8244 CatchException(exception);
8245 XSetCursorState(display,windows,MagickFalse);
8246 if (windows->image.orphan != MagickFalse)
8248 XConfigureImageColormap(display,resource_info,windows,*image);
8249 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8258 radius[MaxTextExtent] = "0.0x1.0";
8261 Query user for blur radius.
8263 (void) XDialogWidget(display,windows,"Blur",
8264 "Enter the blur radius and standard deviation:",radius);
8265 if (*radius == '\0')
8270 XSetCursorState(display,windows,MagickTrue);
8271 XCheckRefreshWindows(display,windows);
8272 flags=ParseGeometry(radius,&geometry_info);
8273 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8274 geometry_info.xi,exception);
8275 if (blur_image != (Image *) NULL)
8277 *image=DestroyImage(*image);
8280 CatchException(exception);
8281 XSetCursorState(display,windows,MagickFalse);
8282 if (windows->image.orphan != MagickFalse)
8284 XConfigureImageColormap(display,resource_info,windows,*image);
8285 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8288 case ThresholdCommand:
8294 factor[MaxTextExtent] = "128";
8297 Query user for threshold value.
8299 (void) XDialogWidget(display,windows,"Threshold",
8300 "Enter threshold value:",factor);
8301 if (*factor == '\0')
8304 Gamma correct image.
8306 XSetCursorState(display,windows,MagickTrue);
8307 XCheckRefreshWindows(display,windows);
8308 threshold=SiPrefixToDouble(factor,QuantumRange);
8309 (void) BilevelImage(*image,threshold);
8310 XSetCursorState(display,windows,MagickFalse);
8311 if (windows->image.orphan != MagickFalse)
8313 XConfigureImageColormap(display,resource_info,windows,*image);
8314 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8317 case EdgeDetectCommand:
8323 radius[MaxTextExtent] = "0";
8326 Query user for edge factor.
8328 (void) XDialogWidget(display,windows,"Detect Edges",
8329 "Enter the edge detect radius:",radius);
8330 if (*radius == '\0')
8333 Detect edge in image.
8335 XSetCursorState(display,windows,MagickTrue);
8336 XCheckRefreshWindows(display,windows);
8337 flags=ParseGeometry(radius,&geometry_info);
8338 edge_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8340 if (edge_image != (Image *) NULL)
8342 *image=DestroyImage(*image);
8345 CatchException(exception);
8346 XSetCursorState(display,windows,MagickFalse);
8347 if (windows->image.orphan != MagickFalse)
8349 XConfigureImageColormap(display,resource_info,windows,*image);
8350 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8359 amount[MaxTextExtent] = "2";
8362 Query user for spread amount.
8364 (void) XDialogWidget(display,windows,"Spread",
8365 "Enter the displacement amount:",amount);
8366 if (*amount == '\0')
8369 Displace image pixels by a random amount.
8371 XSetCursorState(display,windows,MagickTrue);
8372 XCheckRefreshWindows(display,windows);
8373 flags=ParseGeometry(amount,&geometry_info);
8374 spread_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8376 if (spread_image != (Image *) NULL)
8378 *image=DestroyImage(*image);
8379 *image=spread_image;
8381 CatchException(exception);
8382 XSetCursorState(display,windows,MagickFalse);
8383 if (windows->image.orphan != MagickFalse)
8385 XConfigureImageColormap(display,resource_info,windows,*image);
8386 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8398 geometry[MaxTextExtent] = "30x30";
8401 Query user for the shade geometry.
8403 status=XDialogWidget(display,windows,"Shade",
8404 "Enter the azimuth and elevation of the light source:",geometry);
8405 if (*geometry == '\0')
8410 XSetCursorState(display,windows,MagickTrue);
8411 XCheckRefreshWindows(display,windows);
8412 flags=ParseGeometry(geometry,&geometry_info);
8413 if ((flags & SigmaValue) == 0)
8414 geometry_info.sigma=1.0;
8415 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
8416 geometry_info.rho,geometry_info.sigma,exception);
8417 if (shade_image != (Image *) NULL)
8419 *image=DestroyImage(*image);
8422 CatchException(exception);
8423 XSetCursorState(display,windows,MagickFalse);
8424 if (windows->image.orphan != MagickFalse)
8426 XConfigureImageColormap(display,resource_info,windows,*image);
8427 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8433 bevel_width[MaxTextExtent] = "10";
8436 Query user for bevel width.
8438 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8439 if (*bevel_width == '\0')
8444 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8446 XSetCursorState(display,windows,MagickTrue);
8447 XCheckRefreshWindows(display,windows);
8448 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8450 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8451 XSetCursorState(display,windows,MagickFalse);
8452 if (windows->image.orphan != MagickFalse)
8454 XConfigureImageColormap(display,resource_info,windows,*image);
8455 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8458 case SegmentCommand:
8461 threshold[MaxTextExtent] = "1.0x1.5";
8464 Query user for smoothing threshold.
8466 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8468 if (*threshold == '\0')
8473 XSetCursorState(display,windows,MagickTrue);
8474 XCheckRefreshWindows(display,windows);
8475 flags=ParseGeometry(threshold,&geometry_info);
8476 if ((flags & SigmaValue) == 0)
8477 geometry_info.sigma=1.0;
8478 (void) SegmentImage(*image,RGBColorspace,MagickFalse,geometry_info.rho,
8479 geometry_info.sigma,exception);
8480 XSetCursorState(display,windows,MagickFalse);
8481 if (windows->image.orphan != MagickFalse)
8483 XConfigureImageColormap(display,resource_info,windows,*image);
8484 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8487 case SepiaToneCommand:
8496 factor[MaxTextExtent] = "80%";
8499 Query user for sepia-tone factor.
8501 (void) XDialogWidget(display,windows,"Sepia Tone",
8502 "Enter the sepia tone factor (0 - 99.9%):",factor);
8503 if (*factor == '\0')
8506 Sepia tone image pixels.
8508 XSetCursorState(display,windows,MagickTrue);
8509 XCheckRefreshWindows(display,windows);
8510 threshold=SiPrefixToDouble(factor,QuantumRange);
8511 sepia_image=SepiaToneImage(*image,threshold,exception);
8512 if (sepia_image != (Image *) NULL)
8514 *image=DestroyImage(*image);
8517 CatchException(exception);
8518 XSetCursorState(display,windows,MagickFalse);
8519 if (windows->image.orphan != MagickFalse)
8521 XConfigureImageColormap(display,resource_info,windows,*image);
8522 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8525 case SolarizeCommand:
8531 factor[MaxTextExtent] = "60%";
8534 Query user for solarize factor.
8536 (void) XDialogWidget(display,windows,"Solarize",
8537 "Enter the solarize factor (0 - 99.9%):",factor);
8538 if (*factor == '\0')
8541 Solarize image pixels.
8543 XSetCursorState(display,windows,MagickTrue);
8544 XCheckRefreshWindows(display,windows);
8545 threshold=SiPrefixToDouble(factor,QuantumRange);
8546 (void) SolarizeImage(*image,threshold,exception);
8547 XSetCursorState(display,windows,MagickFalse);
8548 if (windows->image.orphan != MagickFalse)
8550 XConfigureImageColormap(display,resource_info,windows,*image);
8551 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8560 degrees[MaxTextExtent] = "60";
8563 Query user for swirl angle.
8565 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8567 if (*degrees == '\0')
8570 Swirl image pixels about the center.
8572 XSetCursorState(display,windows,MagickTrue);
8573 XCheckRefreshWindows(display,windows);
8574 flags=ParseGeometry(degrees,&geometry_info);
8575 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8577 if (swirl_image != (Image *) NULL)
8579 *image=DestroyImage(*image);
8582 CatchException(exception);
8583 XSetCursorState(display,windows,MagickFalse);
8584 if (windows->image.orphan != MagickFalse)
8586 XConfigureImageColormap(display,resource_info,windows,*image);
8587 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8590 case ImplodeCommand:
8596 factor[MaxTextExtent] = "0.3";
8599 Query user for implode factor.
8601 (void) XDialogWidget(display,windows,"Implode",
8602 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8603 if (*factor == '\0')
8606 Implode image pixels about the center.
8608 XSetCursorState(display,windows,MagickTrue);
8609 XCheckRefreshWindows(display,windows);
8610 flags=ParseGeometry(factor,&geometry_info);
8611 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8613 if (implode_image != (Image *) NULL)
8615 *image=DestroyImage(*image);
8616 *image=implode_image;
8618 CatchException(exception);
8619 XSetCursorState(display,windows,MagickFalse);
8620 if (windows->image.orphan != MagickFalse)
8622 XConfigureImageColormap(display,resource_info,windows,*image);
8623 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8626 case VignetteCommand:
8632 geometry[MaxTextExtent] = "0x20";
8635 Query user for the vignette geometry.
8637 (void) XDialogWidget(display,windows,"Vignette",
8638 "Enter the radius, sigma, and x and y offsets:",geometry);
8639 if (*geometry == '\0')
8642 Soften the edges of the image in vignette style
8644 XSetCursorState(display,windows,MagickTrue);
8645 XCheckRefreshWindows(display,windows);
8646 flags=ParseGeometry(geometry,&geometry_info);
8647 if ((flags & SigmaValue) == 0)
8648 geometry_info.sigma=1.0;
8649 if ((flags & XiValue) == 0)
8650 geometry_info.xi=0.1*(*image)->columns;
8651 if ((flags & PsiValue) == 0)
8652 geometry_info.psi=0.1*(*image)->rows;
8653 vignette_image=VignetteImage(*image,geometry_info.rho,geometry_info.sigma,
8654 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
8656 if (vignette_image != (Image *) NULL)
8658 *image=DestroyImage(*image);
8659 *image=vignette_image;
8661 CatchException(exception);
8662 XSetCursorState(display,windows,MagickFalse);
8663 if (windows->image.orphan != MagickFalse)
8665 XConfigureImageColormap(display,resource_info,windows,*image);
8666 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8675 geometry[MaxTextExtent] = "25x150";
8678 Query user for the wave geometry.
8680 (void) XDialogWidget(display,windows,"Wave",
8681 "Enter the amplitude and length of the wave:",geometry);
8682 if (*geometry == '\0')
8685 Alter an image along a sine wave.
8687 XSetCursorState(display,windows,MagickTrue);
8688 XCheckRefreshWindows(display,windows);
8689 flags=ParseGeometry(geometry,&geometry_info);
8690 if ((flags & SigmaValue) == 0)
8691 geometry_info.sigma=1.0;
8692 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8693 (*image)->interpolate,exception);
8694 if (wave_image != (Image *) NULL)
8696 *image=DestroyImage(*image);
8699 CatchException(exception);
8700 XSetCursorState(display,windows,MagickFalse);
8701 if (windows->image.orphan != MagickFalse)
8703 XConfigureImageColormap(display,resource_info,windows,*image);
8704 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8707 case OilPaintCommand:
8713 radius[MaxTextExtent] = "0";
8716 Query user for circular neighborhood radius.
8718 (void) XDialogWidget(display,windows,"Oil Paint",
8719 "Enter the mask radius:",radius);
8720 if (*radius == '\0')
8723 OilPaint image scanlines.
8725 XSetCursorState(display,windows,MagickTrue);
8726 XCheckRefreshWindows(display,windows);
8727 flags=ParseGeometry(radius,&geometry_info);
8728 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8730 if (paint_image != (Image *) NULL)
8732 *image=DestroyImage(*image);
8735 CatchException(exception);
8736 XSetCursorState(display,windows,MagickFalse);
8737 if (windows->image.orphan != MagickFalse)
8739 XConfigureImageColormap(display,resource_info,windows,*image);
8740 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8743 case CharcoalDrawCommand:
8749 radius[MaxTextExtent] = "0x1";
8752 Query user for charcoal radius.
8754 (void) XDialogWidget(display,windows,"Charcoal Draw",
8755 "Enter the charcoal radius and sigma:",radius);
8756 if (*radius == '\0')
8761 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8763 XSetCursorState(display,windows,MagickTrue);
8764 XCheckRefreshWindows(display,windows);
8765 flags=ParseGeometry(radius,&geometry_info);
8766 if ((flags & SigmaValue) == 0)
8767 geometry_info.sigma=geometry_info.rho;
8768 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8769 geometry_info.xi,exception);
8770 if (charcoal_image != (Image *) NULL)
8772 *image=DestroyImage(*image);
8773 *image=charcoal_image;
8775 CatchException(exception);
8776 XSetCursorState(display,windows,MagickFalse);
8777 if (windows->image.orphan != MagickFalse)
8779 XConfigureImageColormap(display,resource_info,windows,*image);
8780 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8783 case AnnotateCommand:
8786 Annotate the image with text.
8788 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8789 if (status == MagickFalse)
8791 XNoticeWidget(display,windows,"Unable to annotate X image",
8792 (*image)->filename);
8802 status=XDrawEditImage(display,resource_info,windows,image,exception);
8803 if (status == MagickFalse)
8805 XNoticeWidget(display,windows,"Unable to draw on the X image",
8806 (*image)->filename);
8816 status=XColorEditImage(display,resource_info,windows,image,exception);
8817 if (status == MagickFalse)
8819 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8820 (*image)->filename);
8830 status=XMatteEditImage(display,resource_info,windows,image,exception);
8831 if (status == MagickFalse)
8833 XNoticeWidget(display,windows,"Unable to matte edit X image",
8834 (*image)->filename);
8839 case CompositeCommand:
8844 status=XCompositeImage(display,resource_info,windows,*image,
8846 if (status == MagickFalse)
8848 XNoticeWidget(display,windows,"Unable to composite X image",
8849 (*image)->filename);
8854 case AddBorderCommand:
8860 geometry[MaxTextExtent] = "6x6";
8863 Query user for border color and geometry.
8865 XColorBrowserWidget(display,windows,"Select",color);
8868 (void) XDialogWidget(display,windows,"Add Border",
8869 "Enter border geometry:",geometry);
8870 if (*geometry == '\0')
8873 Add a border to the image.
8875 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8877 XSetCursorState(display,windows,MagickTrue);
8878 XCheckRefreshWindows(display,windows);
8879 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8881 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8883 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8885 if (border_image != (Image *) NULL)
8887 *image=DestroyImage(*image);
8888 *image=border_image;
8890 CatchException(exception);
8891 XSetCursorState(display,windows,MagickFalse);
8892 if (windows->image.orphan != MagickFalse)
8894 windows->image.window_changes.width=(int) (*image)->columns;
8895 windows->image.window_changes.height=(int) (*image)->rows;
8896 XConfigureImageColormap(display,resource_info,windows,*image);
8897 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8900 case AddFrameCommand:
8909 geometry[MaxTextExtent] = "6x6";
8912 Query user for frame color and geometry.
8914 XColorBrowserWidget(display,windows,"Select",color);
8917 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8919 if (*geometry == '\0')
8922 Surround image with an ornamental border.
8924 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8926 XSetCursorState(display,windows,MagickTrue);
8927 XCheckRefreshWindows(display,windows);
8928 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8930 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8932 frame_info.width=page_geometry.width;
8933 frame_info.height=page_geometry.height;
8934 frame_info.outer_bevel=page_geometry.x;
8935 frame_info.inner_bevel=page_geometry.y;
8936 frame_info.x=(ssize_t) frame_info.width;
8937 frame_info.y=(ssize_t) frame_info.height;
8938 frame_info.width=(*image)->columns+2*frame_info.width;
8939 frame_info.height=(*image)->rows+2*frame_info.height;
8940 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8941 if (frame_image != (Image *) NULL)
8943 *image=DestroyImage(*image);
8946 CatchException(exception);
8947 XSetCursorState(display,windows,MagickFalse);
8948 if (windows->image.orphan != MagickFalse)
8950 windows->image.window_changes.width=(int) (*image)->columns;
8951 windows->image.window_changes.height=(int) (*image)->rows;
8952 XConfigureImageColormap(display,resource_info,windows,*image);
8953 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8956 case CommentCommand:
8970 unique_file=AcquireUniqueFileResource(image_info->filename);
8971 if (unique_file == -1)
8972 XNoticeWidget(display,windows,"Unable to edit image comment",
8973 image_info->filename);
8974 value=GetImageProperty(*image,"comment");
8975 if (value == (char *) NULL)
8976 unique_file=close(unique_file)-1;
8982 file=fdopen(unique_file,"w");
8983 if (file == (FILE *) NULL)
8985 XNoticeWidget(display,windows,"Unable to edit image comment",
8986 image_info->filename);
8989 for (p=value; *p != '\0'; p++)
8990 (void) fputc((int) *p,file);
8991 (void) fputc('\n',file);
8992 (void) fclose(file);
8994 XSetCursorState(display,windows,MagickTrue);
8995 XCheckRefreshWindows(display,windows);
8996 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
8998 if (status == MagickFalse)
8999 XNoticeWidget(display,windows,"Unable to edit image comment",
9006 comment=FileToString(image_info->filename,~0UL,exception);
9007 if (comment != (char *) NULL)
9009 (void) SetImageProperty(*image,"comment",comment);
9010 (*image)->taint=MagickTrue;
9013 (void) RelinquishUniqueFileResource(image_info->filename);
9014 XSetCursorState(display,windows,MagickFalse);
9022 XSetCursorState(display,windows,MagickTrue);
9023 XCheckRefreshWindows(display,windows);
9024 (void) AcquireUniqueFilename(filename);
9025 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9027 status=WriteImage(image_info,*image,exception);
9028 if (status == MagickFalse)
9029 XNoticeWidget(display,windows,"Unable to launch image editor",
9033 nexus=ReadImage(resource_info->image_info,exception);
9034 CatchException(exception);
9035 XClientMessage(display,windows->image.id,windows->im_protocols,
9036 windows->im_next_image,CurrentTime);
9038 (void) RelinquishUniqueFileResource(filename);
9039 XSetCursorState(display,windows,MagickFalse);
9042 case RegionofInterestCommand:
9045 Apply an image processing technique to a region of interest.
9047 (void) XROIImage(display,resource_info,windows,image,exception);
9057 if (windows->magnify.mapped != MagickFalse)
9058 (void) XRaiseWindow(display,windows->magnify.id);
9064 XSetCursorState(display,windows,MagickTrue);
9065 (void) XMapRaised(display,windows->magnify.id);
9066 XSetCursorState(display,windows,MagickFalse);
9070 case ShowPreviewCommand:
9079 preview_type[MaxTextExtent] = "Gamma";
9082 Select preview type from menu.
9084 previews=GetCommandOptions(MagickPreviewOptions);
9085 if (previews == (char **) NULL)
9087 XListBrowserWidget(display,windows,&windows->widget,
9088 (const char **) previews,"Preview",
9089 "Select an enhancement, effect, or F/X:",preview_type);
9090 previews=DestroyStringList(previews);
9091 if (*preview_type == '\0')
9096 XSetCursorState(display,windows,MagickTrue);
9097 XCheckRefreshWindows(display,windows);
9098 image_info->preview_type=(PreviewType)
9099 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9100 image_info->group=(ssize_t) windows->image.id;
9101 (void) DeleteImageProperty(*image,"label");
9102 (void) SetImageProperty(*image,"label","Preview");
9103 (void) AcquireUniqueFilename(filename);
9104 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9106 status=WriteImage(image_info,*image,exception);
9107 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9108 preview_image=ReadImage(image_info,exception);
9109 (void) RelinquishUniqueFileResource(filename);
9110 if (preview_image == (Image *) NULL)
9112 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9114 status=WriteImage(image_info,preview_image,exception);
9115 preview_image=DestroyImage(preview_image);
9116 if (status == MagickFalse)
9117 XNoticeWidget(display,windows,"Unable to show image preview",
9118 (*image)->filename);
9119 XDelay(display,1500);
9120 XSetCursorState(display,windows,MagickFalse);
9123 case ShowHistogramCommand:
9129 Show image histogram.
9131 XSetCursorState(display,windows,MagickTrue);
9132 XCheckRefreshWindows(display,windows);
9133 image_info->group=(ssize_t) windows->image.id;
9134 (void) DeleteImageProperty(*image,"label");
9135 (void) SetImageProperty(*image,"label","Histogram");
9136 (void) AcquireUniqueFilename(filename);
9137 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9139 status=WriteImage(image_info,*image,exception);
9140 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9141 histogram_image=ReadImage(image_info,exception);
9142 (void) RelinquishUniqueFileResource(filename);
9143 if (histogram_image == (Image *) NULL)
9145 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9146 "show:%s",filename);
9147 status=WriteImage(image_info,histogram_image,exception);
9148 histogram_image=DestroyImage(histogram_image);
9149 if (status == MagickFalse)
9150 XNoticeWidget(display,windows,"Unable to show histogram",
9151 (*image)->filename);
9152 XDelay(display,1500);
9153 XSetCursorState(display,windows,MagickFalse);
9156 case ShowMatteCommand:
9161 if ((*image)->matte == MagickFalse)
9163 XNoticeWidget(display,windows,
9164 "Image does not have any matte information",(*image)->filename);
9170 XSetCursorState(display,windows,MagickTrue);
9171 XCheckRefreshWindows(display,windows);
9172 image_info->group=(ssize_t) windows->image.id;
9173 (void) DeleteImageProperty(*image,"label");
9174 (void) SetImageProperty(*image,"label","Matte");
9175 (void) AcquireUniqueFilename(filename);
9176 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9178 status=WriteImage(image_info,*image,exception);
9179 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9180 matte_image=ReadImage(image_info,exception);
9181 (void) RelinquishUniqueFileResource(filename);
9182 if (matte_image == (Image *) NULL)
9184 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9186 status=WriteImage(image_info,matte_image,exception);
9187 matte_image=DestroyImage(matte_image);
9188 if (status == MagickFalse)
9189 XNoticeWidget(display,windows,"Unable to show matte",
9190 (*image)->filename);
9191 XDelay(display,1500);
9192 XSetCursorState(display,windows,MagickFalse);
9195 case BackgroundCommand:
9200 status=XBackgroundImage(display,resource_info,windows,image,exception);
9201 if (status == MagickFalse)
9203 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9204 if (nexus != (Image *) NULL)
9205 XClientMessage(display,windows->image.id,windows->im_protocols,
9206 windows->im_next_image,CurrentTime);
9209 case SlideShowCommand:
9212 delay[MaxTextExtent] = "5";
9215 Display next image after pausing.
9217 (void) XDialogWidget(display,windows,"Slide Show",
9218 "Pause how many 1/100ths of a second between images:",delay);
9221 resource_info->delay=StringToUnsignedLong(delay);
9222 XClientMessage(display,windows->image.id,windows->im_protocols,
9223 windows->im_next_image,CurrentTime);
9226 case PreferencesCommand:
9229 Set user preferences.
9231 status=XPreferencesWidget(display,resource_info,windows);
9232 if (status == MagickFalse)
9234 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9235 if (nexus != (Image *) NULL)
9236 XClientMessage(display,windows->image.id,windows->im_protocols,
9237 windows->im_next_image,CurrentTime);
9243 User requested help.
9245 XTextViewWidget(display,resource_info,windows,MagickFalse,
9246 "Help Viewer - Display",DisplayHelp);
9249 case BrowseDocumentationCommand:
9259 Browse the ImageMagick documentation.
9261 root_window=XRootWindow(display,XDefaultScreen(display));
9262 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9263 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9264 if (mozilla_window != (Window) NULL)
9267 command[MaxTextExtent],
9271 Display documentation using Netscape remote control.
9273 url=GetMagickHomeURL();
9274 (void) FormatLocaleString(command,MaxTextExtent,
9275 "openurl(%s,new-tab)",url);
9276 url=DestroyString(url);
9277 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9278 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9279 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9280 XSetCursorState(display,windows,MagickFalse);
9283 XSetCursorState(display,windows,MagickTrue);
9284 XCheckRefreshWindows(display,windows);
9285 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9287 if (status == MagickFalse)
9288 XNoticeWidget(display,windows,"Unable to browse documentation",
9290 XDelay(display,1500);
9291 XSetCursorState(display,windows,MagickFalse);
9294 case VersionCommand:
9296 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9297 GetMagickCopyright());
9300 case SaveToUndoBufferCommand:
9304 (void) XBell(display,0);
9308 image_info=DestroyImageInfo(image_info);
9313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9317 + X M a g n i f y I m a g e %
9321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9323 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9324 % The magnified portion is displayed in a separate window.
9326 % The format of the XMagnifyImage method is:
9328 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
9330 % A description of each parameter follows:
9332 % o display: Specifies a connection to an X server; returned from
9335 % o windows: Specifies a pointer to a XWindows structure.
9337 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9338 % the entire image is refreshed.
9341 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
9344 text[MaxTextExtent];
9354 Update magnified image until the mouse button is released.
9356 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9360 windows->magnify.x=(int) windows->image.x+x;
9361 windows->magnify.y=(int) windows->image.y+y;
9365 Map and unmap Info widget as text cursor crosses its boundaries.
9367 if (windows->info.mapped != MagickFalse)
9369 if ((x < (int) (windows->info.x+windows->info.width)) &&
9370 (y < (int) (windows->info.y+windows->info.height)))
9371 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9374 if ((x > (int) (windows->info.x+windows->info.width)) ||
9375 (y > (int) (windows->info.y+windows->info.height)))
9376 (void) XMapWindow(display,windows->info.id);
9377 if (windows->info.mapped != MagickFalse)
9380 Display pointer position.
9382 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9383 windows->magnify.x,windows->magnify.y);
9384 XInfoWidget(display,windows,text);
9387 Wait for next event.
9389 XScreenEvent(display,windows,event);
9390 switch (event->type)
9397 User has finished magnifying image.
9416 Check boundary conditions.
9421 if (x >= (int) windows->image.width)
9422 x=(int) windows->image.width-1;
9426 if (y >= (int) windows->image.height)
9427 y=(int) windows->image.height-1;
9428 } while ((state & ExitState) == 0);
9430 Display magnified image.
9432 XSetCursorState(display,windows,MagickFalse);
9436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9440 + X M a g n i f y W i n d o w C o m m a n d %
9444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9446 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9447 % pixel as specified by the key symbol.
9449 % The format of the XMagnifyWindowCommand method is:
9451 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9452 % const MagickStatusType state,const KeySym key_symbol)
9454 % A description of each parameter follows:
9456 % o display: Specifies a connection to an X server; returned from
9459 % o windows: Specifies a pointer to a XWindows structure.
9461 % o state: key mask.
9463 % o key_symbol: Specifies a KeySym which indicates which side of the image
9467 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9468 const MagickStatusType state,const KeySym key_symbol)
9474 User specified a magnify factor or position.
9477 if ((state & Mod1Mask) != 0)
9479 switch ((int) key_symbol)
9483 (void) XWithdrawWindow(display,windows->magnify.id,
9484 windows->magnify.screen);
9490 windows->magnify.x=(int) windows->image.width/2;
9491 windows->magnify.y=(int) windows->image.height/2;
9497 if (windows->magnify.x > 0)
9498 windows->magnify.x-=quantum;
9504 if (windows->magnify.y > 0)
9505 windows->magnify.y-=quantum;
9511 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9512 windows->magnify.x+=quantum;
9518 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9519 windows->magnify.y+=quantum;
9533 windows->magnify.data=(key_symbol-XK_0);
9547 windows->magnify.data=(key_symbol-XK_KP_0);
9553 XMakeMagnifyImage(display,windows);
9557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9561 + X M a k e P a n I m a g e %
9565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9567 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9570 % The format of the XMakePanImage method is:
9572 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9573 % XWindows *windows,Image *image,ExceptionInfo *exception)
9575 % A description of each parameter follows:
9577 % o display: Specifies a connection to an X server; returned from
9580 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9582 % o windows: Specifies a pointer to a XWindows structure.
9584 % o image: the image.
9586 % o exception: return any errors or warnings in this structure.
9589 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9590 XWindows *windows,Image *image,ExceptionInfo *exception)
9596 Create and display image for panning icon.
9598 XSetCursorState(display,windows,MagickTrue);
9599 XCheckRefreshWindows(display,windows);
9600 windows->pan.x=(int) windows->image.x;
9601 windows->pan.y=(int) windows->image.y;
9602 status=XMakeImage(display,resource_info,&windows->pan,image,
9603 windows->pan.width,windows->pan.height,exception);
9604 if (status == MagickFalse)
9605 ThrowXWindowFatalException(ResourceLimitError,
9606 "MemoryAllocationFailed",image->filename);
9607 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9608 windows->pan.pixmap);
9609 (void) XClearWindow(display,windows->pan.id);
9610 XDrawPanRectangle(display,windows);
9611 XSetCursorState(display,windows,MagickFalse);
9615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9619 + X M a t t a E d i t I m a g e %
9623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9625 % XMatteEditImage() allows the user to interactively change the Matte channel
9626 % of an image. If the image is PseudoClass it is promoted to DirectClass
9627 % before the matte information is stored.
9629 % The format of the XMatteEditImage method is:
9631 % MagickBooleanType XMatteEditImage(Display *display,
9632 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9633 % ExceptionInfo *exception)
9635 % A description of each parameter follows:
9637 % o display: Specifies a connection to an X server; returned from
9640 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9642 % o windows: Specifies a pointer to a XWindows structure.
9644 % o image: the image; returned from ReadImage.
9646 % o exception: return any errors or warnings in this structure.
9649 static MagickBooleanType XMatteEditImage(Display *display,
9650 XResourceInfo *resource_info,XWindows *windows,Image **image,
9651 ExceptionInfo *exception)
9654 matte[MaxTextExtent] = "0";
9669 static const ModeType
9670 MatteEditCommands[] =
9673 MatteEditBorderCommand,
9674 MatteEditFuzzCommand,
9675 MatteEditValueCommand,
9676 MatteEditUndoCommand,
9677 MatteEditHelpCommand,
9678 MatteEditDismissCommand
9682 method = PointMethod;
9685 border_color = { 0, 0, 0, 0, 0, 0 };
9688 command[MaxTextExtent],
9689 text[MaxTextExtent];
9721 (void) CloneString(&windows->command.name,"Matte Edit");
9722 windows->command.data=4;
9723 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9724 (void) XMapRaised(display,windows->command.id);
9725 XClientMessage(display,windows->image.id,windows->im_protocols,
9726 windows->im_update_widget,CurrentTime);
9730 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9731 resource_info->background_color,resource_info->foreground_color);
9732 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9734 Track pointer until button 1 is pressed.
9736 XQueryPosition(display,windows->image.id,&x,&y);
9737 (void) XSelectInput(display,windows->image.id,
9738 windows->image.attributes.event_mask | PointerMotionMask);
9742 if (windows->info.mapped != MagickFalse)
9745 Display pointer position.
9747 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9748 x+windows->image.x,y+windows->image.y);
9749 XInfoWidget(display,windows,text);
9752 Wait for next event.
9754 XScreenEvent(display,windows,&event);
9755 if (event.xany.window == windows->command.id)
9758 Select a command from the Command widget.
9760 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9763 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9766 switch (MatteEditCommands[id])
9768 case MatteEditMethod:
9774 Select a method from the pop-up menu.
9776 methods=GetCommandOptions(MagickMethodOptions);
9777 if (methods == (char **) NULL)
9779 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9780 (const char **) methods,command);
9782 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9783 MagickFalse,methods[entry]);
9784 methods=DestroyStringList(methods);
9787 case MatteEditBorderCommand:
9790 *ColorMenu[MaxNumberPens];
9796 Initialize menu selections.
9798 for (i=0; i < (int) (MaxNumberPens-2); i++)
9799 ColorMenu[i]=resource_info->pen_colors[i];
9800 ColorMenu[MaxNumberPens-2]="Browser...";
9801 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9803 Select a pen color from the pop-up menu.
9805 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9806 (const char **) ColorMenu,command);
9809 if (pen_number == (MaxNumberPens-2))
9812 color_name[MaxTextExtent] = "gray";
9815 Select a pen color from a dialog.
9817 resource_info->pen_colors[pen_number]=color_name;
9818 XColorBrowserWidget(display,windows,"Select",color_name);
9819 if (*color_name == '\0')
9825 (void) XParseColor(display,windows->map_info->colormap,
9826 resource_info->pen_colors[pen_number],&border_color);
9829 case MatteEditFuzzCommand:
9832 fuzz[MaxTextExtent];
9847 Select a command from the pop-up menu.
9849 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9855 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*
9859 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9860 (void) XDialogWidget(display,windows,"Ok",
9861 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9864 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9865 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
9868 case MatteEditValueCommand:
9871 message[MaxTextExtent];
9883 Select a command from the pop-up menu.
9885 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9891 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9893 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9894 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9895 (Quantum) TransparentAlpha);
9898 (void) FormatLocaleString(message,MaxTextExtent,
9899 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9901 (void) XDialogWidget(display,windows,"Matte",message,matte);
9906 case MatteEditUndoCommand:
9908 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9912 case MatteEditHelpCommand:
9914 XTextViewWidget(display,resource_info,windows,MagickFalse,
9915 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9918 case MatteEditDismissCommand:
9930 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9937 if (event.xbutton.button != Button1)
9939 if ((event.xbutton.window != windows->image.id) &&
9940 (event.xbutton.window != windows->magnify.id))
9947 (void) XMagickCommand(display,resource_info,windows,
9948 SaveToUndoBufferCommand,image,exception);
9949 state|=UpdateConfigurationState;
9954 if (event.xbutton.button != Button1)
9956 if ((event.xbutton.window != windows->image.id) &&
9957 (event.xbutton.window != windows->magnify.id))
9960 Update colormap information.
9964 XConfigureImageColormap(display,resource_info,windows,*image);
9965 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9966 XInfoWidget(display,windows,text);
9967 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9968 state&=(~UpdateConfigurationState);
9976 command[MaxTextExtent];
9981 if (event.xkey.window == windows->magnify.id)
9986 window=windows->magnify.id;
9987 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
9989 if (event.xkey.window != windows->image.id)
9992 Respond to a user key press.
9994 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
9995 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9996 switch ((int) key_symbol)
10010 XTextViewWidget(display,resource_info,windows,MagickFalse,
10011 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10016 (void) XBell(display,0);
10025 Map and unmap Info widget as cursor crosses its boundaries.
10029 if (windows->info.mapped != MagickFalse)
10031 if ((x < (int) (windows->info.x+windows->info.width)) &&
10032 (y < (int) (windows->info.y+windows->info.height)))
10033 (void) XWithdrawWindow(display,windows->info.id,
10034 windows->info.screen);
10037 if ((x > (int) (windows->info.x+windows->info.width)) ||
10038 (y > (int) (windows->info.y+windows->info.height)))
10039 (void) XMapWindow(display,windows->info.id);
10045 if (event.xany.window == windows->magnify.id)
10047 x=windows->magnify.x-windows->image.x;
10048 y=windows->magnify.y-windows->image.y;
10052 if ((state & UpdateConfigurationState) != 0)
10062 Matte edit is relative to image configuration.
10064 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10066 XPutPixel(windows->image.ximage,x_offset,y_offset,
10067 windows->pixel_info->background_color.pixel);
10068 width=(unsigned int) (*image)->columns;
10069 height=(unsigned int) (*image)->rows;
10072 if (windows->image.crop_geometry != (char *) NULL)
10073 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10075 x_offset=(int) (width*(windows->image.x+x_offset)/
10076 windows->image.ximage->width+x);
10077 y_offset=(int) (height*(windows->image.y+y_offset)/
10078 windows->image.ximage->height+y);
10079 if ((x_offset < 0) || (y_offset < 0))
10081 if ((x_offset >= (int) (*image)->columns) ||
10082 (y_offset >= (int) (*image)->rows))
10084 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10085 return(MagickFalse);
10086 (*image)->matte=MagickTrue;
10087 image_view=AcquireCacheView(*image);
10094 Update matte information using point algorithm.
10096 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10097 (ssize_t) y_offset,1,1,exception);
10098 if (q == (Quantum *) NULL)
10100 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10101 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10104 case ReplaceMethod:
10111 virtual_pixel[MaxPixelChannels];
10114 Update matte information using replace algorithm.
10116 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
10117 (ssize_t) y_offset,virtual_pixel,exception);
10118 target.red=virtual_pixel[RedPixelChannel];
10119 target.green=virtual_pixel[GreenPixelChannel];
10120 target.blue=virtual_pixel[BluePixelChannel];
10121 target.alpha=virtual_pixel[AlphaPixelChannel];
10122 for (y=0; y < (int) (*image)->rows; y++)
10124 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10125 (*image)->columns,1,exception);
10126 if (q == (Quantum *) NULL)
10128 for (x=0; x < (int) (*image)->columns; x++)
10130 GetPixelPacketPixel(*image,q,&pixel);
10131 if (IsFuzzyEquivalencePixelPacket(*image,&pixel,&target))
10132 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10133 q+=GetPixelChannels(*image);
10135 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10140 case FloodfillMethod:
10141 case FillToBorderMethod:
10153 Update matte information using floodfill algorithm.
10155 (void) GetOneVirtualMagickPixel(*image,(ssize_t) x_offset,
10156 (ssize_t) y_offset,&target,exception);
10157 if (method == FillToBorderMethod)
10159 target.red=(MagickRealType) ScaleShortToQuantum(
10161 target.green=(MagickRealType) ScaleShortToQuantum(
10162 border_color.green);
10163 target.blue=(MagickRealType) ScaleShortToQuantum(
10164 border_color.blue);
10166 draw_info=CloneDrawInfo(resource_info->image_info,
10167 (DrawInfo *) NULL);
10168 draw_info->fill.alpha=ClampToQuantum(InterpretLocaleValue(matte,
10170 channel_mask=SetPixelChannelMask(*image,AlphaChannel);
10171 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10172 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
10173 MagickFalse : MagickTrue,exception);
10174 (void) SetPixelChannelMap(*image,channel_mask);
10175 draw_info=DestroyDrawInfo(draw_info);
10181 Update matte information using reset algorithm.
10183 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10184 return(MagickFalse);
10185 for (y=0; y < (int) (*image)->rows; y++)
10187 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10188 (*image)->columns,1,exception);
10189 if (q == (Quantum *) NULL)
10191 for (x=0; x < (int) (*image)->columns; x++)
10193 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10194 q+=GetPixelChannels(*image);
10196 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10199 if (StringToLong(matte) == (long) OpaqueAlpha)
10200 (*image)->matte=MagickFalse;
10204 image_view=DestroyCacheView(image_view);
10205 state&=(~UpdateConfigurationState);
10207 } while ((state & ExitState) == 0);
10208 (void) XSelectInput(display,windows->image.id,
10209 windows->image.attributes.event_mask);
10210 XSetCursorState(display,windows,MagickFalse);
10211 (void) XFreeCursor(display,cursor);
10212 return(MagickTrue);
10216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10220 + X O p e n I m a g e %
10224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10226 % XOpenImage() loads an image from a file.
10228 % The format of the XOpenImage method is:
10230 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10231 % XWindows *windows,const unsigned int command)
10233 % A description of each parameter follows:
10235 % o display: Specifies a connection to an X server; returned from
10238 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10240 % o windows: Specifies a pointer to a XWindows structure.
10242 % o command: A value other than zero indicates that the file is selected
10243 % from the command line argument list.
10246 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10247 XWindows *windows,const MagickBooleanType command)
10262 filename[MaxTextExtent] = "\0";
10265 Request file name from user.
10267 if (command == MagickFalse)
10268 XFileBrowserWidget(display,windows,"Open",filename);
10284 Select next image from the command line.
10286 status=XGetCommand(display,windows->image.id,&files,&count);
10289 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10290 return((Image *) NULL);
10292 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10293 if (filelist == (char **) NULL)
10295 ThrowXWindowFatalException(ResourceLimitError,
10296 "MemoryAllocationFailed","...");
10297 (void) XFreeStringList(files);
10298 return((Image *) NULL);
10301 for (i=1; i < count; i++)
10302 if (*files[i] != '-')
10303 filelist[j++]=files[i];
10304 filelist[j]=(char *) NULL;
10305 XListBrowserWidget(display,windows,&windows->widget,
10306 (const char **) filelist,"Load","Select Image to Load:",filename);
10307 filelist=(char **) RelinquishMagickMemory(filelist);
10308 (void) XFreeStringList(files);
10310 if (*filename == '\0')
10311 return((Image *) NULL);
10312 image_info=CloneImageInfo(resource_info->image_info);
10313 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10315 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10316 exception=AcquireExceptionInfo();
10317 (void) SetImageInfo(image_info,0,exception);
10318 if (LocaleCompare(image_info->magick,"X") == 0)
10321 seconds[MaxTextExtent];
10324 User may want to delay the X server screen grab.
10326 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10327 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10329 if (*seconds == '\0')
10330 return((Image *) NULL);
10331 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10333 magick_info=GetMagickInfo(image_info->magick,exception);
10334 if ((magick_info != (const MagickInfo *) NULL) &&
10335 (magick_info->raw != MagickFalse))
10338 geometry[MaxTextExtent];
10341 Request image size from the user.
10343 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10344 if (image_info->size != (char *) NULL)
10345 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10346 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10348 (void) CloneString(&image_info->size,geometry);
10353 XSetCursorState(display,windows,MagickTrue);
10354 XCheckRefreshWindows(display,windows);
10355 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10356 nexus=ReadImage(image_info,exception);
10357 CatchException(exception);
10358 XSetCursorState(display,windows,MagickFalse);
10359 if (nexus != (Image *) NULL)
10360 XClientMessage(display,windows->image.id,windows->im_protocols,
10361 windows->im_next_image,CurrentTime);
10369 Unknown image format.
10371 text=FileToString(filename,~0,exception);
10372 if (text == (char *) NULL)
10373 return((Image *) NULL);
10374 textlist=StringToList(text);
10375 if (textlist != (char **) NULL)
10378 title[MaxTextExtent];
10383 (void) FormatLocaleString(title,MaxTextExtent,
10384 "Unknown format: %s",filename);
10385 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10386 (const char **) textlist);
10387 for (i=0; textlist[i] != (char *) NULL; i++)
10388 textlist[i]=DestroyString(textlist[i]);
10389 textlist=(char **) RelinquishMagickMemory(textlist);
10391 text=DestroyString(text);
10393 exception=DestroyExceptionInfo(exception);
10394 image_info=DestroyImageInfo(image_info);
10399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10403 + X P a n I m a g e %
10407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10409 % XPanImage() pans the image until the mouse button is released.
10411 % The format of the XPanImage method is:
10413 % void XPanImage(Display *display,XWindows *windows,XEvent *event)
10415 % A description of each parameter follows:
10417 % o display: Specifies a connection to an X server; returned from
10420 % o windows: Specifies a pointer to a XWindows structure.
10422 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10423 % the entire image is refreshed.
10426 static void XPanImage(Display *display,XWindows *windows,XEvent *event)
10429 text[MaxTextExtent];
10447 if ((windows->image.ximage->width > (int) windows->image.width) &&
10448 (windows->image.ximage->height > (int) windows->image.height))
10449 cursor=XCreateFontCursor(display,XC_fleur);
10451 if (windows->image.ximage->width > (int) windows->image.width)
10452 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10454 if (windows->image.ximage->height > (int) windows->image.height)
10455 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10457 cursor=XCreateFontCursor(display,XC_arrow);
10458 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10460 Pan image as pointer moves until the mouse button is released.
10462 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10463 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10464 pan_info.width=windows->pan.width*windows->image.width/
10465 windows->image.ximage->width;
10466 pan_info.height=windows->pan.height*windows->image.height/
10467 windows->image.ximage->height;
10470 state=UpdateConfigurationState;
10473 switch (event->type)
10478 User choose an initial pan location.
10480 pan_info.x=(ssize_t) event->xbutton.x;
10481 pan_info.y=(ssize_t) event->xbutton.y;
10482 state|=UpdateConfigurationState;
10485 case ButtonRelease:
10488 User has finished panning the image.
10490 pan_info.x=(ssize_t) event->xbutton.x;
10491 pan_info.y=(ssize_t) event->xbutton.y;
10492 state|=UpdateConfigurationState | ExitState;
10497 pan_info.x=(ssize_t) event->xmotion.x;
10498 pan_info.y=(ssize_t) event->xmotion.y;
10499 state|=UpdateConfigurationState;
10504 if ((state & UpdateConfigurationState) != 0)
10507 Check boundary conditions.
10509 if (pan_info.x < (ssize_t) (pan_info.width/2))
10512 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10513 if (pan_info.x < 0)
10516 if ((int) (pan_info.x+windows->image.width) >
10517 windows->image.ximage->width)
10518 pan_info.x=(ssize_t)
10519 (windows->image.ximage->width-windows->image.width);
10520 if (pan_info.y < (ssize_t) (pan_info.height/2))
10523 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10524 if (pan_info.y < 0)
10527 if ((int) (pan_info.y+windows->image.height) >
10528 windows->image.ximage->height)
10529 pan_info.y=(ssize_t)
10530 (windows->image.ximage->height-windows->image.height);
10531 if ((windows->image.x != (int) pan_info.x) ||
10532 (windows->image.y != (int) pan_info.y))
10535 Display image pan offset.
10537 windows->image.x=(int) pan_info.x;
10538 windows->image.y=(int) pan_info.y;
10539 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10540 windows->image.width,windows->image.height,windows->image.x,
10542 XInfoWidget(display,windows,text);
10544 Refresh Image window.
10546 XDrawPanRectangle(display,windows);
10547 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10549 state&=(~UpdateConfigurationState);
10552 Wait for next event.
10554 if ((state & ExitState) == 0)
10555 XScreenEvent(display,windows,event);
10556 } while ((state & ExitState) == 0);
10560 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10561 (void) XFreeCursor(display,cursor);
10562 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10570 + X P a s t e I m a g e %
10574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10576 % XPasteImage() pastes an image previously saved with XCropImage in the X
10577 % window image at a location the user chooses with the pointer.
10579 % The format of the XPasteImage method is:
10581 % MagickBooleanType XPasteImage(Display *display,
10582 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10583 % ExceptionInfo *exception)
10585 % A description of each parameter follows:
10587 % o display: Specifies a connection to an X server; returned from
10590 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10592 % o windows: Specifies a pointer to a XWindows structure.
10594 % o image: the image; returned from ReadImage.
10596 % o exception: return any errors or warnings in this structure.
10599 static MagickBooleanType XPasteImage(Display *display,
10600 XResourceInfo *resource_info,XWindows *windows,Image *image,
10601 ExceptionInfo *exception)
10612 static const ModeType
10615 PasteOperatorsCommand,
10617 PasteDismissCommand
10620 static CompositeOperator
10621 compose = CopyCompositeOp;
10624 text[MaxTextExtent];
10658 if (resource_info->copy_image == (Image *) NULL)
10659 return(MagickFalse);
10660 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10662 Map Command widget.
10664 (void) CloneString(&windows->command.name,"Paste");
10665 windows->command.data=1;
10666 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10667 (void) XMapRaised(display,windows->command.id);
10668 XClientMessage(display,windows->image.id,windows->im_protocols,
10669 windows->im_update_widget,CurrentTime);
10671 Track pointer until button 1 is pressed.
10673 XSetCursorState(display,windows,MagickFalse);
10674 XQueryPosition(display,windows->image.id,&x,&y);
10675 (void) XSelectInput(display,windows->image.id,
10676 windows->image.attributes.event_mask | PointerMotionMask);
10677 paste_info.x=(ssize_t) windows->image.x+x;
10678 paste_info.y=(ssize_t) windows->image.y+y;
10679 paste_info.width=0;
10680 paste_info.height=0;
10681 cursor=XCreateFontCursor(display,XC_ul_angle);
10682 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10683 state=DefaultState;
10686 if (windows->info.mapped != MagickFalse)
10689 Display pointer position.
10691 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10692 (long) paste_info.x,(long) paste_info.y);
10693 XInfoWidget(display,windows,text);
10695 highlight_info=paste_info;
10696 highlight_info.x=paste_info.x-windows->image.x;
10697 highlight_info.y=paste_info.y-windows->image.y;
10698 XHighlightRectangle(display,windows->image.id,
10699 windows->image.highlight_context,&highlight_info);
10701 Wait for next event.
10703 XScreenEvent(display,windows,&event);
10704 XHighlightRectangle(display,windows->image.id,
10705 windows->image.highlight_context,&highlight_info);
10706 if (event.xany.window == windows->command.id)
10709 Select a command from the Command widget.
10711 id=XCommandWidget(display,windows,PasteMenu,&event);
10714 switch (PasteCommands[id])
10716 case PasteOperatorsCommand:
10719 command[MaxTextExtent],
10723 Select a command from the pop-up menu.
10725 operators=GetCommandOptions(MagickComposeOptions);
10726 if (operators == (char **) NULL)
10728 entry=XMenuWidget(display,windows,PasteMenu[id],
10729 (const char **) operators,command);
10731 compose=(CompositeOperator) ParseCommandOption(
10732 MagickComposeOptions,MagickFalse,operators[entry]);
10733 operators=DestroyStringList(operators);
10736 case PasteHelpCommand:
10738 XTextViewWidget(display,resource_info,windows,MagickFalse,
10739 "Help Viewer - Image Composite",ImagePasteHelp);
10742 case PasteDismissCommand:
10747 state|=EscapeState;
10756 switch (event.type)
10760 if (image->debug != MagickFalse)
10761 (void) LogMagickEvent(X11Event,GetMagickModule(),
10762 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10763 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10764 if (event.xbutton.button != Button1)
10766 if (event.xbutton.window != windows->image.id)
10769 Paste rectangle is relative to image configuration.
10771 width=(unsigned int) image->columns;
10772 height=(unsigned int) image->rows;
10775 if (windows->image.crop_geometry != (char *) NULL)
10776 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10778 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10779 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10780 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10781 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10782 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10783 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10784 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10787 case ButtonRelease:
10789 if (image->debug != MagickFalse)
10790 (void) LogMagickEvent(X11Event,GetMagickModule(),
10791 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10792 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10793 if (event.xbutton.button != Button1)
10795 if (event.xbutton.window != windows->image.id)
10797 if ((paste_info.width != 0) && (paste_info.height != 0))
10800 User has selected the location of the paste image.
10802 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10803 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10813 command[MaxTextExtent];
10821 if (event.xkey.window != windows->image.id)
10824 Respond to a user key press.
10826 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10827 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10828 *(command+length)='\0';
10829 if (image->debug != MagickFalse)
10830 (void) LogMagickEvent(X11Event,GetMagickModule(),
10831 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10832 switch ((int) key_symbol)
10840 paste_image=DestroyImage(paste_image);
10841 state|=EscapeState;
10848 (void) XSetFunction(display,windows->image.highlight_context,
10850 XTextViewWidget(display,resource_info,windows,MagickFalse,
10851 "Help Viewer - Image Composite",ImagePasteHelp);
10852 (void) XSetFunction(display,windows->image.highlight_context,
10858 (void) XBell(display,0);
10867 Map and unmap Info widget as text cursor crosses its boundaries.
10871 if (windows->info.mapped != MagickFalse)
10873 if ((x < (int) (windows->info.x+windows->info.width)) &&
10874 (y < (int) (windows->info.y+windows->info.height)))
10875 (void) XWithdrawWindow(display,windows->info.id,
10876 windows->info.screen);
10879 if ((x > (int) (windows->info.x+windows->info.width)) ||
10880 (y > (int) (windows->info.y+windows->info.height)))
10881 (void) XMapWindow(display,windows->info.id);
10882 paste_info.x=(ssize_t) windows->image.x+x;
10883 paste_info.y=(ssize_t) windows->image.y+y;
10888 if (image->debug != MagickFalse)
10889 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10894 } while ((state & ExitState) == 0);
10895 (void) XSelectInput(display,windows->image.id,
10896 windows->image.attributes.event_mask);
10897 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10898 XSetCursorState(display,windows,MagickFalse);
10899 (void) XFreeCursor(display,cursor);
10900 if ((state & EscapeState) != 0)
10901 return(MagickTrue);
10903 Image pasting is relative to image configuration.
10905 XSetCursorState(display,windows,MagickTrue);
10906 XCheckRefreshWindows(display,windows);
10907 width=(unsigned int) image->columns;
10908 height=(unsigned int) image->rows;
10911 if (windows->image.crop_geometry != (char *) NULL)
10912 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10913 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10915 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10916 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10917 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10919 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10920 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10922 Paste image with X Image window.
10924 (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y);
10925 paste_image=DestroyImage(paste_image);
10926 XSetCursorState(display,windows,MagickFalse);
10928 Update image colormap.
10930 XConfigureImageColormap(display,resource_info,windows,image);
10931 (void) XConfigureImage(display,resource_info,windows,image,exception);
10932 return(MagickTrue);
10936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10940 + X P r i n t I m a g e %
10944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10946 % XPrintImage() prints an image to a Postscript printer.
10948 % The format of the XPrintImage method is:
10950 % MagickBooleanType XPrintImage(Display *display,
10951 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10952 % ExceptionInfo *exception)
10954 % A description of each parameter follows:
10956 % o display: Specifies a connection to an X server; returned from
10959 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10961 % o windows: Specifies a pointer to a XWindows structure.
10963 % o image: the image.
10965 % o exception: return any errors or warnings in this structure.
10968 static MagickBooleanType XPrintImage(Display *display,
10969 XResourceInfo *resource_info,XWindows *windows,Image *image,
10970 ExceptionInfo *exception)
10973 filename[MaxTextExtent],
10974 geometry[MaxTextExtent];
10986 Request Postscript page geometry from user.
10988 image_info=CloneImageInfo(resource_info->image_info);
10989 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
10990 if (image_info->page != (char *) NULL)
10991 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
10992 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
10993 "Select Postscript Page Geometry:",geometry);
10994 if (*geometry == '\0')
10995 return(MagickTrue);
10996 image_info->page=GetPageGeometry(geometry);
10998 Apply image transforms.
11000 XSetCursorState(display,windows,MagickTrue);
11001 XCheckRefreshWindows(display,windows);
11002 print_image=CloneImage(image,0,0,MagickTrue,exception);
11003 if (print_image == (Image *) NULL)
11004 return(MagickFalse);
11005 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11006 windows->image.ximage->width,windows->image.ximage->height);
11007 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry);
11011 (void) AcquireUniqueFilename(filename);
11012 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11014 status=WriteImage(image_info,print_image,exception);
11015 (void) RelinquishUniqueFileResource(filename);
11016 print_image=DestroyImage(print_image);
11017 image_info=DestroyImageInfo(image_info);
11018 XSetCursorState(display,windows,MagickFalse);
11019 return(status != 0 ? MagickTrue : MagickFalse);
11023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11027 + X R O I I m a g e %
11031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11033 % XROIImage() applies an image processing technique to a region of interest.
11035 % The format of the XROIImage method is:
11037 % MagickBooleanType XROIImage(Display *display,
11038 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11039 % ExceptionInfo *exception)
11041 % A description of each parameter follows:
11043 % o display: Specifies a connection to an X server; returned from
11046 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11048 % o windows: Specifies a pointer to a XWindows structure.
11050 % o image: the image; returned from ReadImage.
11052 % o exception: return any errors or warnings in this structure.
11055 static MagickBooleanType XROIImage(Display *display,
11056 XResourceInfo *resource_info,XWindows *windows,Image **image,
11057 ExceptionInfo *exception)
11059 #define ApplyMenus 7
11109 "Contrast Stretch...",
11110 "Sigmoidal Contrast...",
11144 "Charcoal Draw...",
11147 *MiscellanyMenu[] =
11158 **Menus[ApplyMenus] =
11169 static const CommandType
11192 TransformCommands[] =
11196 RotateRightCommand,
11199 EnhanceCommands[] =
11207 ContrastStretchCommand,
11208 SigmoidalContrastCommand,
11216 EffectsCommands[] =
11220 ReduceNoiseCommand,
11239 CharcoalDrawCommand
11241 MiscellanyCommands[] =
11245 ShowPreviewCommand,
11246 ShowHistogramCommand,
11255 static const CommandType
11256 *Commands[ApplyMenus] =
11268 command[MaxTextExtent],
11269 text[MaxTextExtent];
11289 MagickProgressMonitor
11308 Map Command widget.
11310 (void) CloneString(&windows->command.name,"ROI");
11311 windows->command.data=0;
11312 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11313 (void) XMapRaised(display,windows->command.id);
11314 XClientMessage(display,windows->image.id,windows->im_protocols,
11315 windows->im_update_widget,CurrentTime);
11317 Track pointer until button 1 is pressed.
11319 XQueryPosition(display,windows->image.id,&x,&y);
11320 (void) XSelectInput(display,windows->image.id,
11321 windows->image.attributes.event_mask | PointerMotionMask);
11322 roi_info.x=(ssize_t) windows->image.x+x;
11323 roi_info.y=(ssize_t) windows->image.y+y;
11326 cursor=XCreateFontCursor(display,XC_fleur);
11327 state=DefaultState;
11330 if (windows->info.mapped != MagickFalse)
11333 Display pointer position.
11335 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11336 (long) roi_info.x,(long) roi_info.y);
11337 XInfoWidget(display,windows,text);
11340 Wait for next event.
11342 XScreenEvent(display,windows,&event);
11343 if (event.xany.window == windows->command.id)
11346 Select a command from the Command widget.
11348 id=XCommandWidget(display,windows,ROIMenu,&event);
11351 switch (ROICommands[id])
11353 case ROIHelpCommand:
11355 XTextViewWidget(display,resource_info,windows,MagickFalse,
11356 "Help Viewer - Region of Interest",ImageROIHelp);
11359 case ROIDismissCommand:
11364 state|=EscapeState;
11373 switch (event.type)
11377 if (event.xbutton.button != Button1)
11379 if (event.xbutton.window != windows->image.id)
11382 Note first corner of region of interest rectangle-- exit loop.
11384 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11385 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11386 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11390 case ButtonRelease:
11399 if (event.xkey.window != windows->image.id)
11402 Respond to a user key press.
11404 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11405 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11406 switch ((int) key_symbol)
11414 state|=EscapeState;
11421 XTextViewWidget(display,resource_info,windows,MagickFalse,
11422 "Help Viewer - Region of Interest",ImageROIHelp);
11427 (void) XBell(display,0);
11436 Map and unmap Info widget as text cursor crosses its boundaries.
11440 if (windows->info.mapped != MagickFalse)
11442 if ((x < (int) (windows->info.x+windows->info.width)) &&
11443 (y < (int) (windows->info.y+windows->info.height)))
11444 (void) XWithdrawWindow(display,windows->info.id,
11445 windows->info.screen);
11448 if ((x > (int) (windows->info.x+windows->info.width)) ||
11449 (y > (int) (windows->info.y+windows->info.height)))
11450 (void) XMapWindow(display,windows->info.id);
11451 roi_info.x=(ssize_t) windows->image.x+x;
11452 roi_info.y=(ssize_t) windows->image.y+y;
11458 } while ((state & ExitState) == 0);
11459 (void) XSelectInput(display,windows->image.id,
11460 windows->image.attributes.event_mask);
11461 if ((state & EscapeState) != 0)
11464 User want to exit without region of interest.
11466 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11467 (void) XFreeCursor(display,cursor);
11468 return(MagickTrue);
11470 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11474 Size rectangle as pointer moves until the mouse button is released.
11476 x=(int) roi_info.x;
11477 y=(int) roi_info.y;
11480 state=DefaultState;
11483 highlight_info=roi_info;
11484 highlight_info.x=roi_info.x-windows->image.x;
11485 highlight_info.y=roi_info.y-windows->image.y;
11486 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11489 Display info and draw region of interest rectangle.
11491 if (windows->info.mapped == MagickFalse)
11492 (void) XMapWindow(display,windows->info.id);
11493 (void) FormatLocaleString(text,MaxTextExtent,
11494 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11495 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11496 XInfoWidget(display,windows,text);
11497 XHighlightRectangle(display,windows->image.id,
11498 windows->image.highlight_context,&highlight_info);
11501 if (windows->info.mapped != MagickFalse)
11502 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11504 Wait for next event.
11506 XScreenEvent(display,windows,&event);
11507 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11508 XHighlightRectangle(display,windows->image.id,
11509 windows->image.highlight_context,&highlight_info);
11510 switch (event.type)
11514 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11515 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11518 case ButtonRelease:
11521 User has committed to region of interest rectangle.
11523 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11524 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11525 XSetCursorState(display,windows,MagickFalse);
11527 if (LocaleCompare(windows->command.name,"Apply") == 0)
11529 (void) CloneString(&windows->command.name,"Apply");
11530 windows->command.data=ApplyMenus;
11531 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11538 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11539 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11544 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11545 ((state & ExitState) != 0))
11548 Check boundary conditions.
11550 if (roi_info.x < 0)
11553 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11554 roi_info.x=(ssize_t) windows->image.ximage->width;
11555 if ((int) roi_info.x < x)
11556 roi_info.width=(unsigned int) (x-roi_info.x);
11559 roi_info.width=(unsigned int) (roi_info.x-x);
11560 roi_info.x=(ssize_t) x;
11562 if (roi_info.y < 0)
11565 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11566 roi_info.y=(ssize_t) windows->image.ximage->height;
11567 if ((int) roi_info.y < y)
11568 roi_info.height=(unsigned int) (y-roi_info.y);
11571 roi_info.height=(unsigned int) (roi_info.y-y);
11572 roi_info.y=(ssize_t) y;
11575 } while ((state & ExitState) == 0);
11577 Wait for user to grab a corner of the rectangle or press return.
11579 state=DefaultState;
11580 command_type=NullCommand;
11581 (void) XMapWindow(display,windows->info.id);
11584 if (windows->info.mapped != MagickFalse)
11587 Display pointer position.
11589 (void) FormatLocaleString(text,MaxTextExtent,
11590 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11591 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11592 XInfoWidget(display,windows,text);
11594 highlight_info=roi_info;
11595 highlight_info.x=roi_info.x-windows->image.x;
11596 highlight_info.y=roi_info.y-windows->image.y;
11597 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11599 state|=EscapeState;
11603 if ((state & UpdateRegionState) != 0)
11605 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11606 switch (command_type)
11611 (void) XMagickCommand(display,resource_info,windows,command_type,
11618 Region of interest is relative to image configuration.
11620 progress_monitor=SetImageProgressMonitor(*image,
11621 (MagickProgressMonitor) NULL,(*image)->client_data);
11622 crop_info=roi_info;
11623 width=(unsigned int) (*image)->columns;
11624 height=(unsigned int) (*image)->rows;
11627 if (windows->image.crop_geometry != (char *) NULL)
11628 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11630 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11632 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11633 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11634 scale_factor=(MagickRealType)
11635 height/windows->image.ximage->height;
11637 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11638 crop_info.height=(unsigned int)
11639 (scale_factor*crop_info.height+0.5);
11640 roi_image=CropImage(*image,&crop_info,exception);
11641 (void) SetImageProgressMonitor(*image,progress_monitor,
11642 (*image)->client_data);
11643 if (roi_image == (Image *) NULL)
11646 Apply image processing technique to the region of interest.
11648 windows->image.orphan=MagickTrue;
11649 (void) XMagickCommand(display,resource_info,windows,command_type,
11650 &roi_image,exception);
11651 progress_monitor=SetImageProgressMonitor(*image,
11652 (MagickProgressMonitor) NULL,(*image)->client_data);
11653 (void) XMagickCommand(display,resource_info,windows,
11654 SaveToUndoBufferCommand,image,exception);
11655 windows->image.orphan=MagickFalse;
11656 (void) CompositeImage(*image,CopyCompositeOp,roi_image,
11657 crop_info.x,crop_info.y);
11658 roi_image=DestroyImage(roi_image);
11659 (void) SetImageProgressMonitor(*image,progress_monitor,
11660 (*image)->client_data);
11664 if (command_type != InfoCommand)
11666 XConfigureImageColormap(display,resource_info,windows,*image);
11667 (void) XConfigureImage(display,resource_info,windows,*image,exception);
11669 XCheckRefreshWindows(display,windows);
11670 XInfoWidget(display,windows,text);
11671 (void) XSetFunction(display,windows->image.highlight_context,
11673 state&=(~UpdateRegionState);
11675 XHighlightRectangle(display,windows->image.id,
11676 windows->image.highlight_context,&highlight_info);
11677 XScreenEvent(display,windows,&event);
11678 if (event.xany.window == windows->command.id)
11681 Select a command from the Command widget.
11683 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11684 command_type=NullCommand;
11685 id=XCommandWidget(display,windows,ApplyMenu,&event);
11688 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11689 command_type=ApplyCommands[id];
11690 if (id < ApplyMenus)
11693 Select a command from a pop-up menu.
11695 entry=XMenuWidget(display,windows,ApplyMenu[id],
11696 (const char **) Menus[id],command);
11699 (void) CopyMagickString(command,Menus[id][entry],
11701 command_type=Commands[id][entry];
11705 (void) XSetFunction(display,windows->image.highlight_context,
11707 XHighlightRectangle(display,windows->image.id,
11708 windows->image.highlight_context,&highlight_info);
11709 if (command_type == HelpCommand)
11711 (void) XSetFunction(display,windows->image.highlight_context,
11713 XTextViewWidget(display,resource_info,windows,MagickFalse,
11714 "Help Viewer - Region of Interest",ImageROIHelp);
11715 (void) XSetFunction(display,windows->image.highlight_context,
11719 if (command_type == QuitCommand)
11724 state|=EscapeState;
11728 if (command_type != NullCommand)
11729 state|=UpdateRegionState;
11732 XHighlightRectangle(display,windows->image.id,
11733 windows->image.highlight_context,&highlight_info);
11734 switch (event.type)
11738 x=windows->image.x;
11739 y=windows->image.y;
11740 if (event.xbutton.button != Button1)
11742 if (event.xbutton.window != windows->image.id)
11744 x=windows->image.x+event.xbutton.x;
11745 y=windows->image.y+event.xbutton.y;
11746 if ((x < (int) (roi_info.x+RoiDelta)) &&
11747 (x > (int) (roi_info.x-RoiDelta)) &&
11748 (y < (int) (roi_info.y+RoiDelta)) &&
11749 (y > (int) (roi_info.y-RoiDelta)))
11751 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11752 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11753 state|=UpdateConfigurationState;
11756 if ((x < (int) (roi_info.x+RoiDelta)) &&
11757 (x > (int) (roi_info.x-RoiDelta)) &&
11758 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11759 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11761 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11762 state|=UpdateConfigurationState;
11765 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11766 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11767 (y < (int) (roi_info.y+RoiDelta)) &&
11768 (y > (int) (roi_info.y-RoiDelta)))
11770 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11771 state|=UpdateConfigurationState;
11774 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11775 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11776 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11777 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11779 state|=UpdateConfigurationState;
11783 case ButtonRelease:
11785 if (event.xbutton.window == windows->pan.id)
11786 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11787 (highlight_info.y != crop_info.y-windows->image.y))
11788 XHighlightRectangle(display,windows->image.id,
11789 windows->image.highlight_context,&highlight_info);
11790 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11791 event.xbutton.time);
11796 if (event.xexpose.window == windows->image.id)
11797 if (event.xexpose.count == 0)
11799 event.xexpose.x=(int) highlight_info.x;
11800 event.xexpose.y=(int) highlight_info.y;
11801 event.xexpose.width=(int) highlight_info.width;
11802 event.xexpose.height=(int) highlight_info.height;
11803 XRefreshWindow(display,&windows->image,&event);
11805 if (event.xexpose.window == windows->info.id)
11806 if (event.xexpose.count == 0)
11807 XInfoWidget(display,windows,text);
11815 if (event.xkey.window != windows->image.id)
11818 Respond to a user key press.
11820 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11821 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11822 switch ((int) key_symbol)
11829 state|=EscapeState;
11838 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11839 roi_info.y=(ssize_t) (windows->image.height/2L-
11840 roi_info.height/2L);
11872 (void) XSetFunction(display,windows->image.highlight_context,
11874 XTextViewWidget(display,resource_info,windows,MagickFalse,
11875 "Help Viewer - Region of Interest",ImageROIHelp);
11876 (void) XSetFunction(display,windows->image.highlight_context,
11882 command_type=XImageWindowCommand(display,resource_info,windows,
11883 event.xkey.state,key_symbol,image,exception);
11884 if (command_type != NullCommand)
11885 state|=UpdateRegionState;
11889 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11897 if (event.xbutton.window != windows->image.id)
11900 Map and unmap Info widget as text cursor crosses its boundaries.
11904 if (windows->info.mapped != MagickFalse)
11906 if ((x < (int) (windows->info.x+windows->info.width)) &&
11907 (y < (int) (windows->info.y+windows->info.height)))
11908 (void) XWithdrawWindow(display,windows->info.id,
11909 windows->info.screen);
11912 if ((x > (int) (windows->info.x+windows->info.width)) ||
11913 (y > (int) (windows->info.y+windows->info.height)))
11914 (void) XMapWindow(display,windows->info.id);
11915 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11916 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11919 case SelectionRequest:
11924 XSelectionRequestEvent
11928 Set primary selection.
11930 (void) FormatLocaleString(text,MaxTextExtent,
11931 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11932 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11933 request=(&(event.xselectionrequest));
11934 (void) XChangeProperty(request->display,request->requestor,
11935 request->property,request->target,8,PropModeReplace,
11936 (unsigned char *) text,(int) strlen(text));
11937 notify.type=SelectionNotify;
11938 notify.display=request->display;
11939 notify.requestor=request->requestor;
11940 notify.selection=request->selection;
11941 notify.target=request->target;
11942 notify.time=request->time;
11943 if (request->property == None)
11944 notify.property=request->target;
11946 notify.property=request->property;
11947 (void) XSendEvent(request->display,request->requestor,False,0,
11948 (XEvent *) ¬ify);
11953 if ((state & UpdateConfigurationState) != 0)
11955 (void) XPutBackEvent(display,&event);
11956 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11959 } while ((state & ExitState) == 0);
11960 } while ((state & ExitState) == 0);
11961 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11962 XSetCursorState(display,windows,MagickFalse);
11963 if ((state & EscapeState) != 0)
11964 return(MagickTrue);
11965 return(MagickTrue);
11969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11973 + X R o t a t e I m a g e %
11977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11979 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11980 % rotation angle is computed from the slope of a line drawn by the user.
11982 % The format of the XRotateImage method is:
11984 % MagickBooleanType XRotateImage(Display *display,
11985 % XResourceInfo *resource_info,XWindows *windows,double degrees,
11986 % Image **image,ExceptionInfo *exception)
11988 % A description of each parameter follows:
11990 % o display: Specifies a connection to an X server; returned from
11993 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11995 % o windows: Specifies a pointer to a XWindows structure.
11997 % o degrees: Specifies the number of degrees to rotate the image.
11999 % o image: the image.
12001 % o exception: return any errors or warnings in this structure.
12004 static MagickBooleanType XRotateImage(Display *display,
12005 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12006 ExceptionInfo *exception)
12019 direction = HorizontalRotateCommand;
12021 static const ModeType
12022 DirectionCommands[] =
12024 HorizontalRotateCommand,
12025 VerticalRotateCommand
12029 RotateColorCommand,
12030 RotateDirectionCommand,
12032 RotateDismissCommand
12035 static unsigned int
12039 command[MaxTextExtent],
12040 text[MaxTextExtent];
12051 normalized_degrees;
12061 if (degrees == 0.0)
12076 Map Command widget.
12078 (void) CloneString(&windows->command.name,"Rotate");
12079 windows->command.data=2;
12080 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12081 (void) XMapRaised(display,windows->command.id);
12082 XClientMessage(display,windows->image.id,windows->im_protocols,
12083 windows->im_update_widget,CurrentTime);
12085 Wait for first button press.
12087 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12088 XQueryPosition(display,windows->image.id,&x,&y);
12093 state=DefaultState;
12096 XHighlightLine(display,windows->image.id,
12097 windows->image.highlight_context,&rotate_info);
12099 Wait for next event.
12101 XScreenEvent(display,windows,&event);
12102 XHighlightLine(display,windows->image.id,
12103 windows->image.highlight_context,&rotate_info);
12104 if (event.xany.window == windows->command.id)
12107 Select a command from the Command widget.
12109 id=XCommandWidget(display,windows,RotateMenu,&event);
12112 (void) XSetFunction(display,windows->image.highlight_context,
12114 switch (RotateCommands[id])
12116 case RotateColorCommand:
12119 *ColorMenu[MaxNumberPens];
12128 Initialize menu selections.
12130 for (i=0; i < (int) (MaxNumberPens-2); i++)
12131 ColorMenu[i]=resource_info->pen_colors[i];
12132 ColorMenu[MaxNumberPens-2]="Browser...";
12133 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12135 Select a pen color from the pop-up menu.
12137 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12138 (const char **) ColorMenu,command);
12139 if (pen_number < 0)
12141 if (pen_number == (MaxNumberPens-2))
12144 color_name[MaxTextExtent] = "gray";
12147 Select a pen color from a dialog.
12149 resource_info->pen_colors[pen_number]=color_name;
12150 XColorBrowserWidget(display,windows,"Select",color_name);
12151 if (*color_name == '\0')
12157 (void) XParseColor(display,windows->map_info->colormap,
12158 resource_info->pen_colors[pen_number],&color);
12159 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12160 (unsigned int) MaxColors,&color);
12161 windows->pixel_info->pen_colors[pen_number]=color;
12162 pen_id=(unsigned int) pen_number;
12165 case RotateDirectionCommand:
12176 Select a command from the pop-up menu.
12178 id=XMenuWidget(display,windows,RotateMenu[id],
12179 Directions,command);
12181 direction=DirectionCommands[id];
12184 case RotateHelpCommand:
12186 XTextViewWidget(display,resource_info,windows,MagickFalse,
12187 "Help Viewer - Image Rotation",ImageRotateHelp);
12190 case RotateDismissCommand:
12195 state|=EscapeState;
12202 (void) XSetFunction(display,windows->image.highlight_context,
12206 switch (event.type)
12210 if (event.xbutton.button != Button1)
12212 if (event.xbutton.window != windows->image.id)
12217 (void) XSetFunction(display,windows->image.highlight_context,
12219 rotate_info.x1=event.xbutton.x;
12220 rotate_info.y1=event.xbutton.y;
12224 case ButtonRelease:
12231 command[MaxTextExtent];
12236 if (event.xkey.window != windows->image.id)
12239 Respond to a user key press.
12241 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12242 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12243 switch ((int) key_symbol)
12251 state|=EscapeState;
12258 (void) XSetFunction(display,windows->image.highlight_context,
12260 XTextViewWidget(display,resource_info,windows,MagickFalse,
12261 "Help Viewer - Image Rotation",ImageRotateHelp);
12262 (void) XSetFunction(display,windows->image.highlight_context,
12268 (void) XBell(display,0);
12276 rotate_info.x1=event.xmotion.x;
12277 rotate_info.y1=event.xmotion.y;
12280 rotate_info.x2=rotate_info.x1;
12281 rotate_info.y2=rotate_info.y1;
12282 if (direction == HorizontalRotateCommand)
12283 rotate_info.x2+=32;
12285 rotate_info.y2-=32;
12286 } while ((state & ExitState) == 0);
12287 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12288 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12289 if ((state & EscapeState) != 0)
12290 return(MagickTrue);
12292 Draw line as pointer moves until the mouse button is released.
12295 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12296 state=DefaultState;
12302 Display info and draw rotation line.
12304 if (windows->info.mapped == MagickFalse)
12305 (void) XMapWindow(display,windows->info.id);
12306 (void) FormatLocaleString(text,MaxTextExtent," %g",
12307 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12308 XInfoWidget(display,windows,text);
12309 XHighlightLine(display,windows->image.id,
12310 windows->image.highlight_context,&rotate_info);
12313 if (windows->info.mapped != MagickFalse)
12314 (void) XWithdrawWindow(display,windows->info.id,
12315 windows->info.screen);
12317 Wait for next event.
12319 XScreenEvent(display,windows,&event);
12321 XHighlightLine(display,windows->image.id,
12322 windows->image.highlight_context,&rotate_info);
12323 switch (event.type)
12327 case ButtonRelease:
12330 User has committed to rotation line.
12332 rotate_info.x2=event.xbutton.x;
12333 rotate_info.y2=event.xbutton.y;
12341 rotate_info.x2=event.xmotion.x;
12342 rotate_info.y2=event.xmotion.y;
12348 Check boundary conditions.
12350 if (rotate_info.x2 < 0)
12353 if (rotate_info.x2 > (int) windows->image.width)
12354 rotate_info.x2=(short) windows->image.width;
12355 if (rotate_info.y2 < 0)
12358 if (rotate_info.y2 > (int) windows->image.height)
12359 rotate_info.y2=(short) windows->image.height;
12361 Compute rotation angle from the slope of the line.
12364 distance=(unsigned int)
12365 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12366 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12368 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12369 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12370 } while ((state & ExitState) == 0);
12371 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12372 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12374 return(MagickTrue);
12376 if (direction == VerticalRotateCommand)
12378 if (degrees == 0.0)
12379 return(MagickTrue);
12383 normalized_degrees=degrees;
12384 while (normalized_degrees < -45.0)
12385 normalized_degrees+=360.0;
12386 for (rotations=0; normalized_degrees > 45.0; rotations++)
12387 normalized_degrees-=90.0;
12388 if (normalized_degrees != 0.0)
12389 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12391 XSetCursorState(display,windows,MagickTrue);
12392 XCheckRefreshWindows(display,windows);
12393 (*image)->background_color.red=ScaleShortToQuantum(
12394 windows->pixel_info->pen_colors[pen_id].red);
12395 (*image)->background_color.green=ScaleShortToQuantum(
12396 windows->pixel_info->pen_colors[pen_id].green);
12397 (*image)->background_color.blue=ScaleShortToQuantum(
12398 windows->pixel_info->pen_colors[pen_id].blue);
12399 rotate_image=RotateImage(*image,degrees,exception);
12400 XSetCursorState(display,windows,MagickFalse);
12401 if (rotate_image == (Image *) NULL)
12402 return(MagickFalse);
12403 *image=DestroyImage(*image);
12404 *image=rotate_image;
12405 if (windows->image.crop_geometry != (char *) NULL)
12408 Rotate crop geometry.
12410 width=(unsigned int) (*image)->columns;
12411 height=(unsigned int) (*image)->rows;
12412 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12413 switch (rotations % 4)
12423 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12424 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12431 Rotate 180 degrees.
12433 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12434 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12440 Rotate 270 degrees.
12442 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12443 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12448 if (windows->image.orphan != MagickFalse)
12449 return(MagickTrue);
12450 if (normalized_degrees != 0.0)
12453 Update image colormap.
12455 windows->image.window_changes.width=(int) (*image)->columns;
12456 windows->image.window_changes.height=(int) (*image)->rows;
12457 if (windows->image.crop_geometry != (char *) NULL)
12460 Obtain dimensions of image from crop geometry.
12462 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12464 windows->image.window_changes.width=(int) width;
12465 windows->image.window_changes.height=(int) height;
12467 XConfigureImageColormap(display,resource_info,windows,*image);
12470 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12472 windows->image.window_changes.width=windows->image.ximage->height;
12473 windows->image.window_changes.height=windows->image.ximage->width;
12476 Update image configuration.
12478 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12479 return(MagickTrue);
12483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12487 + X S a v e I m a g e %
12491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12493 % XSaveImage() saves an image to a file.
12495 % The format of the XSaveImage method is:
12497 % MagickBooleanType XSaveImage(Display *display,
12498 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12499 % ExceptionInfo *exception)
12501 % A description of each parameter follows:
12503 % o display: Specifies a connection to an X server; returned from
12506 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12508 % o windows: Specifies a pointer to a XWindows structure.
12510 % o image: the image.
12512 % o exception: return any errors or warnings in this structure.
12515 static MagickBooleanType XSaveImage(Display *display,
12516 XResourceInfo *resource_info,XWindows *windows,Image *image,
12517 ExceptionInfo *exception)
12520 filename[MaxTextExtent],
12521 geometry[MaxTextExtent];
12533 Request file name from user.
12535 if (resource_info->write_filename != (char *) NULL)
12536 (void) CopyMagickString(filename,resource_info->write_filename,
12541 path[MaxTextExtent];
12546 GetPathComponent(image->filename,HeadPath,path);
12547 GetPathComponent(image->filename,TailPath,filename);
12550 status=chdir(path);
12552 (void) ThrowMagickException(exception,GetMagickModule(),
12553 FileOpenError,"UnableToOpenFile","%s",path);
12556 XFileBrowserWidget(display,windows,"Save",filename);
12557 if (*filename == '\0')
12558 return(MagickTrue);
12559 if (IsPathAccessible(filename) != MagickFalse)
12565 File exists-- seek user's permission before overwriting.
12567 status=XConfirmWidget(display,windows,"Overwrite",filename);
12569 return(MagickTrue);
12571 image_info=CloneImageInfo(resource_info->image_info);
12572 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12573 (void) SetImageInfo(image_info,1,exception);
12574 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12575 (LocaleCompare(image_info->magick,"JPG") == 0))
12578 quality[MaxTextExtent];
12584 Request JPEG quality from user.
12586 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12588 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12590 if (*quality == '\0')
12591 return(MagickTrue);
12592 image->quality=StringToUnsignedLong(quality);
12593 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12595 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12596 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12597 (LocaleCompare(image_info->magick,"PS") == 0) ||
12598 (LocaleCompare(image_info->magick,"PS2") == 0))
12601 geometry[MaxTextExtent];
12604 Request page geometry from user.
12606 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12607 if (LocaleCompare(image_info->magick,"PDF") == 0)
12608 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12609 if (image_info->page != (char *) NULL)
12610 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12611 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12612 "Select page geometry:",geometry);
12613 if (*geometry != '\0')
12614 image_info->page=GetPageGeometry(geometry);
12617 Apply image transforms.
12619 XSetCursorState(display,windows,MagickTrue);
12620 XCheckRefreshWindows(display,windows);
12621 save_image=CloneImage(image,0,0,MagickTrue,exception);
12622 if (save_image == (Image *) NULL)
12623 return(MagickFalse);
12624 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12625 windows->image.ximage->width,windows->image.ximage->height);
12626 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry);
12630 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12631 status=WriteImage(image_info,save_image,exception);
12632 if (status != MagickFalse)
12633 image->taint=MagickFalse;
12634 save_image=DestroyImage(save_image);
12635 image_info=DestroyImageInfo(image_info);
12636 XSetCursorState(display,windows,MagickFalse);
12637 return(status != 0 ? MagickTrue : MagickFalse);
12641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12645 + X S c r e e n E v e n t %
12649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12651 % XScreenEvent() handles global events associated with the Pan and Magnify
12654 % The format of the XScreenEvent function is:
12656 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12658 % A description of each parameter follows:
12660 % o display: Specifies a pointer to the Display structure; returned from
12663 % o windows: Specifies a pointer to a XWindows structure.
12665 % o event: Specifies a pointer to a X11 XEvent structure.
12670 #if defined(__cplusplus) || defined(c_plusplus)
12674 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12679 windows=(XWindows *) data;
12680 if ((event->type == ClientMessage) &&
12681 (event->xclient.window == windows->image.id))
12682 return(MagickFalse);
12683 return(MagickTrue);
12686 #if defined(__cplusplus) || defined(c_plusplus)
12690 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12696 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12697 if (event->xany.window == windows->command.id)
12699 switch (event->type)
12702 case ButtonRelease:
12704 if ((event->xbutton.button == Button3) &&
12705 (event->xbutton.state & Mod1Mask))
12708 Convert Alt-Button3 to Button2.
12710 event->xbutton.button=Button2;
12711 event->xbutton.state&=(~Mod1Mask);
12713 if (event->xbutton.window == windows->backdrop.id)
12715 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12716 event->xbutton.time);
12719 if (event->xbutton.window == windows->pan.id)
12721 XPanImage(display,windows,event);
12724 if (event->xbutton.window == windows->image.id)
12725 if (event->xbutton.button == Button2)
12728 Update magnified image.
12730 x=event->xbutton.x;
12731 y=event->xbutton.y;
12735 if (x >= (int) windows->image.width)
12736 x=(int) (windows->image.width-1);
12737 windows->magnify.x=(int) windows->image.x+x;
12741 if (y >= (int) windows->image.height)
12742 y=(int) (windows->image.height-1);
12743 windows->magnify.y=windows->image.y+y;
12744 if (windows->magnify.mapped == MagickFalse)
12745 (void) XMapRaised(display,windows->magnify.id);
12746 XMakeMagnifyImage(display,windows);
12747 if (event->type == ButtonRelease)
12748 (void) XWithdrawWindow(display,windows->info.id,
12749 windows->info.screen);
12754 case ClientMessage:
12757 If client window delete message, exit.
12759 if (event->xclient.message_type != windows->wm_protocols)
12761 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12763 if (event->xclient.window == windows->magnify.id)
12765 (void) XWithdrawWindow(display,windows->magnify.id,
12766 windows->magnify.screen);
12771 case ConfigureNotify:
12773 if (event->xconfigure.window == windows->magnify.id)
12779 Magnify window has a new configuration.
12781 windows->magnify.width=(unsigned int) event->xconfigure.width;
12782 windows->magnify.height=(unsigned int) event->xconfigure.height;
12783 if (windows->magnify.mapped == MagickFalse)
12786 while ((int) magnify <= event->xconfigure.width)
12788 while ((int) magnify <= event->xconfigure.height)
12791 if (((int) magnify != event->xconfigure.width) ||
12792 ((int) magnify != event->xconfigure.height))
12797 window_changes.width=(int) magnify;
12798 window_changes.height=(int) magnify;
12799 (void) XReconfigureWMWindow(display,windows->magnify.id,
12800 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12804 XMakeMagnifyImage(display,windows);
12811 if (event->xexpose.window == windows->image.id)
12813 XRefreshWindow(display,&windows->image,event);
12816 if (event->xexpose.window == windows->pan.id)
12817 if (event->xexpose.count == 0)
12819 XDrawPanRectangle(display,windows);
12822 if (event->xexpose.window == windows->magnify.id)
12823 if (event->xexpose.count == 0)
12825 XMakeMagnifyImage(display,windows);
12833 command[MaxTextExtent];
12838 if (event->xkey.window != windows->magnify.id)
12841 Respond to a user key press.
12843 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12844 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12845 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol);
12850 if (event->xmap.window == windows->magnify.id)
12852 windows->magnify.mapped=MagickTrue;
12853 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12856 if (event->xmap.window == windows->info.id)
12858 windows->info.mapped=MagickTrue;
12865 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12866 if (event->xmotion.window == windows->image.id)
12867 if (windows->magnify.mapped != MagickFalse)
12870 Update magnified image.
12872 x=event->xmotion.x;
12873 y=event->xmotion.y;
12877 if (x >= (int) windows->image.width)
12878 x=(int) (windows->image.width-1);
12879 windows->magnify.x=(int) windows->image.x+x;
12883 if (y >= (int) windows->image.height)
12884 y=(int) (windows->image.height-1);
12885 windows->magnify.y=windows->image.y+y;
12886 XMakeMagnifyImage(display,windows);
12892 if (event->xunmap.window == windows->magnify.id)
12894 windows->magnify.mapped=MagickFalse;
12897 if (event->xunmap.window == windows->info.id)
12899 windows->info.mapped=MagickFalse;
12910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12914 + X S e t C r o p G e o m e t r y %
12918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12920 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12921 % and translates it to a cropping geometry relative to the image.
12923 % The format of the XSetCropGeometry method is:
12925 % void XSetCropGeometry(Display *display,XWindows *windows,
12926 % RectangleInfo *crop_info,Image *image)
12928 % A description of each parameter follows:
12930 % o display: Specifies a connection to an X server; returned from
12933 % o windows: Specifies a pointer to a XWindows structure.
12935 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12936 % Image window to crop.
12938 % o image: the image.
12941 static void XSetCropGeometry(Display *display,XWindows *windows,
12942 RectangleInfo *crop_info,Image *image)
12945 text[MaxTextExtent];
12958 if (windows->info.mapped != MagickFalse)
12961 Display info on cropping rectangle.
12963 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12964 (double) crop_info->width,(double) crop_info->height,(double)
12965 crop_info->x,(double) crop_info->y);
12966 XInfoWidget(display,windows,text);
12969 Cropping geometry is relative to any previous crop geometry.
12973 width=(unsigned int) image->columns;
12974 height=(unsigned int) image->rows;
12975 if (windows->image.crop_geometry != (char *) NULL)
12976 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12978 windows->image.crop_geometry=AcquireString((char *) NULL);
12980 Define the crop geometry string from the cropping rectangle.
12982 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12983 if (crop_info->x > 0)
12984 x+=(int) (scale_factor*crop_info->x+0.5);
12985 width=(unsigned int) (scale_factor*crop_info->width+0.5);
12988 scale_factor=(MagickRealType) height/windows->image.ximage->height;
12989 if (crop_info->y > 0)
12990 y+=(int) (scale_factor*crop_info->y+0.5);
12991 height=(unsigned int) (scale_factor*crop_info->height+0.5);
12994 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12995 "%ux%u%+d%+d",width,height,x,y);
12999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13003 + X T i l e I m a g e %
13007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13009 % XTileImage() loads or deletes a selected tile from a visual image directory.
13010 % The load or delete command is chosen from a menu.
13012 % The format of the XTileImage method is:
13014 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13015 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13017 % A description of each parameter follows:
13019 % o tile_image: XTileImage reads or deletes the tile image
13020 % and returns it. A null image is returned if an error occurs.
13022 % o display: Specifies a connection to an X server; returned from
13025 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13027 % o windows: Specifies a pointer to a XWindows structure.
13029 % o image: the image; returned from ReadImage.
13031 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13032 % the entire image is refreshed.
13034 % o exception: return any errors or warnings in this structure.
13037 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13038 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13051 static const ModeType
13062 command[MaxTextExtent],
13063 filename[MaxTextExtent];
13090 Tile image is relative to montage image configuration.
13094 width=(unsigned int) image->columns;
13095 height=(unsigned int) image->rows;
13096 if (windows->image.crop_geometry != (char *) NULL)
13097 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13098 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13099 event->xbutton.x+=windows->image.x;
13100 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13101 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13102 event->xbutton.y+=windows->image.y;
13103 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13105 Determine size and location of each tile in the visual image directory.
13107 width=(unsigned int) image->columns;
13108 height=(unsigned int) image->rows;
13111 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13112 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13113 (event->xbutton.x-x)/width;
13117 Button press is outside any tile.
13119 (void) XBell(display,0);
13120 return((Image *) NULL);
13123 Determine file name from the tile directory.
13125 p=image->directory;
13126 for (i=tile; (i != 0) && (*p != '\0'); )
13135 Button press is outside any tile.
13137 (void) XBell(display,0);
13138 return((Image *) NULL);
13141 Select a command from the pop-up menu.
13143 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13145 return((Image *) NULL);
13147 while ((*q != '\n') && (*q != '\0'))
13149 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13151 Perform command for the selected tile.
13153 XSetCursorState(display,windows,MagickTrue);
13154 XCheckRefreshWindows(display,windows);
13155 tile_image=NewImageList();
13156 switch (TileCommands[id])
13158 case TileLoadCommand:
13163 XCheckRefreshWindows(display,windows);
13164 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13166 (void) CopyMagickString(resource_info->image_info->filename,filename,
13168 tile_image=ReadImage(resource_info->image_info,exception);
13169 CatchException(exception);
13170 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13173 case TileNextCommand:
13176 Display next image.
13178 XClientMessage(display,windows->image.id,windows->im_protocols,
13179 windows->im_next_image,CurrentTime);
13182 case TileFormerCommand:
13185 Display former image.
13187 XClientMessage(display,windows->image.id,windows->im_protocols,
13188 windows->im_former_image,CurrentTime);
13191 case TileDeleteCommand:
13196 if (IsPathAccessible(filename) == MagickFalse)
13198 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13201 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13204 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
13205 if (status != MagickFalse)
13207 XNoticeWidget(display,windows,"Unable to delete image file:",
13212 case TileUpdateCommand:
13222 virtual_pixel[MaxPixelChannels];
13231 Ensure all the images exist.
13234 for (p=image->directory; *p != '\0'; p++)
13240 while ((*q != '\n') && (*q != '\0'))
13242 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13244 if (IsPathAccessible(filename) != MagickFalse)
13250 Overwrite tile with background color.
13252 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13253 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13254 image_view=AcquireCacheView(image);
13255 (void) GetOneCacheViewVirtualPixel(image_view,0,0,virtual_pixel,
13257 pixel.red=virtual_pixel[RedPixelChannel];
13258 pixel.green=virtual_pixel[GreenPixelChannel];
13259 pixel.blue=virtual_pixel[BluePixelChannel];
13260 pixel.alpha=virtual_pixel[AlphaPixelChannel];
13261 for (i=0; i < (int) height; i++)
13263 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13264 y_offset+i,width,1,exception);
13265 if (s == (Quantum *) NULL)
13267 for (j=0; j < (int) width; j++)
13269 SetPixelPacket(image,&pixel,s);
13270 s+=GetPixelChannels(image);
13272 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13275 image_view=DestroyCacheView(image_view);
13278 windows->image.window_changes.width=(int) image->columns;
13279 windows->image.window_changes.height=(int) image->rows;
13280 XConfigureImageColormap(display,resource_info,windows,image);
13281 (void) XConfigureImage(display,resource_info,windows,image,exception);
13287 XSetCursorState(display,windows,MagickFalse);
13288 return(tile_image);
13292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13296 + X T r a n s l a t e I m a g e %
13300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13302 % XTranslateImage() translates the image within an Image window by one pixel
13303 % as specified by the key symbol. If the image has a `montage string the
13304 % translation is respect to the width and height contained within the string.
13306 % The format of the XTranslateImage method is:
13308 % void XTranslateImage(Display *display,XWindows *windows,
13309 % Image *image,const KeySym key_symbol)
13311 % A description of each parameter follows:
13313 % o display: Specifies a connection to an X server; returned from
13316 % o windows: Specifies a pointer to a XWindows structure.
13318 % o image: the image.
13320 % o key_symbol: Specifies a KeySym which indicates which side of the image
13324 static void XTranslateImage(Display *display,XWindows *windows,
13325 Image *image,const KeySym key_symbol)
13328 text[MaxTextExtent];
13339 User specified a pan position offset.
13341 x_offset=windows->image.width;
13342 y_offset=windows->image.height;
13343 if (image->montage != (char *) NULL)
13344 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13345 switch ((int) key_symbol)
13350 windows->image.x=(int) windows->image.width/2;
13351 windows->image.y=(int) windows->image.height/2;
13357 windows->image.x-=x_offset;
13364 windows->image.y-=y_offset;
13370 windows->image.x+=x_offset;
13377 windows->image.y+=y_offset;
13384 Check boundary conditions.
13386 if (windows->image.x < 0)
13387 windows->image.x=0;
13389 if ((int) (windows->image.x+windows->image.width) >
13390 windows->image.ximage->width)
13391 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13392 if (windows->image.y < 0)
13393 windows->image.y=0;
13395 if ((int) (windows->image.y+windows->image.height) >
13396 windows->image.ximage->height)
13397 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13399 Refresh Image window.
13401 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13402 windows->image.width,windows->image.height,windows->image.x,
13404 XInfoWidget(display,windows,text);
13405 XCheckRefreshWindows(display,windows);
13406 XDrawPanRectangle(display,windows);
13407 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13408 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13416 + X T r i m I m a g e %
13420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13422 % XTrimImage() trims the edges from the Image window.
13424 % The format of the XTrimImage method is:
13426 % MagickBooleanType XTrimImage(Display *display,
13427 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13428 % ExceptionInfo *exception)
13430 % A description of each parameter follows:
13432 % o display: Specifies a connection to an X server; returned from
13435 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13437 % o windows: Specifies a pointer to a XWindows structure.
13439 % o image: the image.
13441 % o exception: return any errors or warnings in this structure.
13444 static MagickBooleanType XTrimImage(Display *display,
13445 XResourceInfo *resource_info,XWindows *windows,Image *image,
13446 ExceptionInfo *exception)
13460 Trim edges from image.
13462 XSetCursorState(display,windows,MagickTrue);
13463 XCheckRefreshWindows(display,windows);
13465 Crop the left edge.
13467 background=XGetPixel(windows->image.ximage,0,0);
13468 trim_info.width=(size_t) windows->image.ximage->width;
13469 for (x=0; x < windows->image.ximage->width; x++)
13471 for (y=0; y < windows->image.ximage->height; y++)
13473 pixel=XGetPixel(windows->image.ximage,x,y);
13474 if (pixel != background)
13477 if (y < windows->image.ximage->height)
13480 trim_info.x=(ssize_t) x;
13481 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13483 XSetCursorState(display,windows,MagickFalse);
13484 return(MagickFalse);
13487 Crop the right edge.
13489 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13490 for (x=windows->image.ximage->width-1; x != 0; x--)
13492 for (y=0; y < windows->image.ximage->height; y++)
13494 pixel=XGetPixel(windows->image.ximage,x,y);
13495 if (pixel != background)
13498 if (y < windows->image.ximage->height)
13501 trim_info.width=(size_t) (x-trim_info.x+1);
13505 background=XGetPixel(windows->image.ximage,0,0);
13506 trim_info.height=(size_t) windows->image.ximage->height;
13507 for (y=0; y < windows->image.ximage->height; y++)
13509 for (x=0; x < windows->image.ximage->width; x++)
13511 pixel=XGetPixel(windows->image.ximage,x,y);
13512 if (pixel != background)
13515 if (x < windows->image.ximage->width)
13518 trim_info.y=(ssize_t) y;
13520 Crop the bottom edge.
13522 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13523 for (y=windows->image.ximage->height-1; y != 0; y--)
13525 for (x=0; x < windows->image.ximage->width; x++)
13527 pixel=XGetPixel(windows->image.ximage,x,y);
13528 if (pixel != background)
13531 if (x < windows->image.ximage->width)
13534 trim_info.height=(size_t) y-trim_info.y+1;
13535 if (((unsigned int) trim_info.width != windows->image.width) ||
13536 ((unsigned int) trim_info.height != windows->image.height))
13539 Reconfigure Image window as defined by the trimming rectangle.
13541 XSetCropGeometry(display,windows,&trim_info,image);
13542 windows->image.window_changes.width=(int) trim_info.width;
13543 windows->image.window_changes.height=(int) trim_info.height;
13544 (void) XConfigureImage(display,resource_info,windows,image,exception);
13546 XSetCursorState(display,windows,MagickFalse);
13547 return(MagickTrue);
13551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13555 + X V i s u a l D i r e c t o r y I m a g e %
13559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13561 % XVisualDirectoryImage() creates a Visual Image Directory.
13563 % The format of the XVisualDirectoryImage method is:
13565 % Image *XVisualDirectoryImage(Display *display,
13566 % XResourceInfo *resource_info,XWindows *windows,
13567 % ExceptionInfo *exception)
13569 % A description of each parameter follows:
13571 % o display: Specifies a connection to an X server; returned from
13574 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13576 % o windows: Specifies a pointer to a XWindows structure.
13578 % o exception: return any errors or warnings in this structure.
13581 static Image *XVisualDirectoryImage(Display *display,
13582 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13584 #define TileImageTag "Scale/Image"
13585 #define XClientName "montage"
13618 filename[MaxTextExtent] = "\0",
13619 filenames[MaxTextExtent] = "*";
13622 background_resources;
13625 Request file name from user.
13627 XFileBrowserWidget(display,windows,"Directory",filenames);
13628 if (*filenames == '\0')
13629 return((Image *) NULL);
13631 Expand the filenames.
13633 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13634 if (filelist == (char **) NULL)
13636 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13638 return((Image *) NULL);
13641 filelist[0]=filenames;
13642 status=ExpandFilenames(&number_files,&filelist);
13643 if ((status == MagickFalse) || (number_files == 0))
13645 if (number_files == 0)
13646 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13648 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13650 return((Image *) NULL);
13653 Set image background resources.
13655 background_resources=(*resource_info);
13656 background_resources.window_id=AcquireString("");
13657 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13658 "0x%lx",windows->image.id);
13659 background_resources.backdrop=MagickTrue;
13661 Read each image and convert them to a tile.
13663 backdrop=(windows->visual_info->klass == TrueColor) ||
13664 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13665 read_info=CloneImageInfo(resource_info->image_info);
13666 (void) SetImageOption(read_info,"jpeg:size","120x120");
13667 (void) CloneString(&read_info->size,DefaultTileGeometry);
13668 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13670 images=NewImageList();
13671 XSetCursorState(display,windows,MagickTrue);
13672 XCheckRefreshWindows(display,windows);
13673 for (i=0; i < (int) number_files; i++)
13675 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13676 filelist[i]=DestroyString(filelist[i]);
13677 *read_info->magick='\0';
13678 next_image=ReadImage(read_info,exception);
13679 CatchException(exception);
13680 if (next_image != (Image *) NULL)
13682 (void) DeleteImageProperty(next_image,"label");
13683 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13684 read_info,next_image,DefaultTileLabel,exception));
13685 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13687 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13688 geometry.height,exception);
13689 if (thumbnail_image != (Image *) NULL)
13691 next_image=DestroyImage(next_image);
13692 next_image=thumbnail_image;
13696 (void) XDisplayBackgroundImage(display,&background_resources,
13697 next_image,exception);
13698 XSetCursorState(display,windows,MagickTrue);
13700 AppendImageToList(&images,next_image);
13701 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13706 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13707 (MagickSizeType) number_files);
13708 if (proceed == MagickFalse)
13713 filelist=(char **) RelinquishMagickMemory(filelist);
13714 if (images == (Image *) NULL)
13716 read_info=DestroyImageInfo(read_info);
13717 XSetCursorState(display,windows,MagickFalse);
13718 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13719 return((Image *) NULL);
13722 Create the Visual Image Directory.
13724 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13725 montage_info->pointsize=10;
13726 if (resource_info->font != (char *) NULL)
13727 (void) CloneString(&montage_info->font,resource_info->font);
13728 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13729 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13730 images),exception);
13731 images=DestroyImageList(images);
13732 montage_info=DestroyMontageInfo(montage_info);
13733 read_info=DestroyImageInfo(read_info);
13734 XSetCursorState(display,windows,MagickFalse);
13735 if (montage_image == (Image *) NULL)
13736 return(montage_image);
13737 XClientMessage(display,windows->image.id,windows->im_protocols,
13738 windows->im_next_image,CurrentTime);
13739 return(montage_image);
13743 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13747 % X D i s p l a y B a c k g r o u n d I m a g e %
13751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13753 % XDisplayBackgroundImage() displays an image in the background of a window.
13755 % The format of the XDisplayBackgroundImage method is:
13757 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13758 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13760 % A description of each parameter follows:
13762 % o display: Specifies a connection to an X server; returned from
13765 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13767 % o image: the image.
13769 % o exception: return any errors or warnings in this structure.
13772 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13773 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13776 geometry[MaxTextExtent],
13777 visual_type[MaxTextExtent];
13790 static XStandardColormap
13794 *visual_info = (XVisualInfo *) NULL;
13815 Determine target window.
13817 assert(image != (Image *) NULL);
13818 assert(image->signature == MagickSignature);
13819 if (image->debug != MagickFalse)
13820 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13821 resources=(*resource_info);
13822 window_info.id=(Window) NULL;
13823 root_window=XRootWindow(display,XDefaultScreen(display));
13824 if (LocaleCompare(resources.window_id,"root") == 0)
13825 window_info.id=root_window;
13828 if (isdigit((unsigned char) *resources.window_id) != 0)
13829 window_info.id=XWindowByID(display,root_window,
13830 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13831 if (window_info.id == (Window) NULL)
13832 window_info.id=XWindowByName(display,root_window,resources.window_id);
13834 if (window_info.id == (Window) NULL)
13836 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13837 resources.window_id);
13838 return(MagickFalse);
13841 Determine window visual id.
13843 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13844 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13845 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13846 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13848 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13849 XVisualIDFromVisual(window_attributes.visual));
13850 if (visual_info == (XVisualInfo *) NULL)
13853 Allocate standard colormap.
13855 map_info=XAllocStandardColormap();
13856 if (map_info == (XStandardColormap *) NULL)
13857 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13859 map_info->colormap=(Colormap) NULL;
13860 pixel.pixels=(unsigned long *) NULL;
13862 Initialize visual info.
13864 resources.map_type=(char *) NULL;
13865 resources.visual_type=visual_type;
13866 visual_info=XBestVisualInfo(display,map_info,&resources);
13867 if (visual_info == (XVisualInfo *) NULL)
13868 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13869 resources.visual_type);
13871 Initialize window info.
13873 window_info.ximage=(XImage *) NULL;
13874 window_info.matte_image=(XImage *) NULL;
13875 window_info.pixmap=(Pixmap) NULL;
13876 window_info.matte_pixmap=(Pixmap) NULL;
13879 Free previous root colors.
13881 if (window_info.id == root_window)
13882 (void) XDestroyWindowColors(display,root_window);
13884 Initialize Standard Colormap.
13886 resources.colormap=SharedColormap;
13887 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel);
13889 Graphic context superclass.
13891 context_values.background=pixel.background_color.pixel;
13892 context_values.foreground=pixel.foreground_color.pixel;
13893 pixel.annotate_context=XCreateGC(display,window_info.id,
13894 (size_t) (GCBackground | GCForeground),&context_values);
13895 if (pixel.annotate_context == (GC) NULL)
13896 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13899 Initialize Image window attributes.
13901 window_info.name=AcquireString("\0");
13902 window_info.icon_name=AcquireString("\0");
13903 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13904 &resources,&window_info);
13906 Create the X image.
13908 window_info.width=(unsigned int) image->columns;
13909 window_info.height=(unsigned int) image->rows;
13910 if ((image->columns != window_info.width) ||
13911 (image->rows != window_info.height))
13912 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13914 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13915 window_attributes.width,window_attributes.height);
13916 geometry_info.width=window_info.width;
13917 geometry_info.height=window_info.height;
13918 geometry_info.x=(ssize_t) window_info.x;
13919 geometry_info.y=(ssize_t) window_info.y;
13920 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13921 &geometry_info.width,&geometry_info.height);
13922 window_info.width=(unsigned int) geometry_info.width;
13923 window_info.height=(unsigned int) geometry_info.height;
13924 window_info.x=(int) geometry_info.x;
13925 window_info.y=(int) geometry_info.y;
13926 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13927 window_info.height,exception);
13928 if (status == MagickFalse)
13929 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13933 if (image->debug != MagickFalse)
13935 (void) LogMagickEvent(X11Event,GetMagickModule(),
13936 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13937 (double) image->columns,(double) image->rows);
13938 if (image->colors != 0)
13939 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13941 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13944 Adjust image dimensions as specified by backdrop or geometry options.
13946 width=(int) window_info.width;
13947 height=(int) window_info.height;
13948 if (resources.backdrop != MagickFalse)
13951 Center image on window.
13953 window_info.x=(window_attributes.width/2)-
13954 (window_info.ximage->width/2);
13955 window_info.y=(window_attributes.height/2)-
13956 (window_info.ximage->height/2);
13957 width=window_attributes.width;
13958 height=window_attributes.height;
13960 if ((resources.image_geometry != (char *) NULL) &&
13961 (*resources.image_geometry != '\0'))
13964 default_geometry[MaxTextExtent];
13974 User specified geometry.
13976 size_hints=XAllocSizeHints();
13977 if (size_hints == (XSizeHints *) NULL)
13978 ThrowXWindowFatalException(ResourceLimitFatalError,
13979 "MemoryAllocationFailed",image->filename);
13980 size_hints->flags=0L;
13981 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
13983 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13984 default_geometry,window_info.border_width,size_hints,&window_info.x,
13985 &window_info.y,&width,&height,&gravity);
13986 if (flags & (XValue | YValue))
13988 width=window_attributes.width;
13989 height=window_attributes.height;
13991 (void) XFree((void *) size_hints);
13994 Create the X pixmap.
13996 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
13997 (unsigned int) height,window_info.depth);
13998 if (window_info.pixmap == (Pixmap) NULL)
13999 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14002 Display pixmap on the window.
14004 if (((unsigned int) width > window_info.width) ||
14005 ((unsigned int) height > window_info.height))
14006 (void) XFillRectangle(display,window_info.pixmap,
14007 window_info.annotate_context,0,0,(unsigned int) width,
14008 (unsigned int) height);
14009 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14010 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14011 window_info.width,(unsigned int) window_info.height);
14012 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14013 (void) XClearWindow(display,window_info.id);
14014 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14015 XDelay(display,delay == 0UL ? 10UL : delay);
14016 (void) XSync(display,MagickFalse);
14017 return(window_info.id == root_window ? MagickTrue : MagickFalse);
14021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14025 + X D i s p l a y I m a g e %
14029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14031 % XDisplayImage() displays an image via X11. A new image is created and
14032 % returned if the user interactively transforms the displayed image.
14034 % The format of the XDisplayImage method is:
14036 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14037 % char **argv,int argc,Image **image,size_t *state,
14038 % ExceptionInfo *exception)
14040 % A description of each parameter follows:
14042 % o nexus: Method XDisplayImage returns an image when the
14043 % user chooses 'Open Image' from the command menu or picks a tile
14044 % from the image directory. Otherwise a null image is returned.
14046 % o display: Specifies a connection to an X server; returned from
14049 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14051 % o argv: Specifies the application's argument list.
14053 % o argc: Specifies the number of arguments.
14055 % o image: Specifies an address to an address of an Image structure;
14057 % o exception: return any errors or warnings in this structure.
14060 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14061 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14063 #define MagnifySize 256 /* must be a power of 2 */
14064 #define MagickMenus 10
14065 #define MagickTitle "Commands"
14092 "Visual Directory...",
14138 "Contrast Stretch...",
14139 "Sigmoidal Contrast...",
14173 "Charcoal Draw...",
14187 "Region of Interest...",
14190 *MiscellanyMenu[] =
14205 "Browse Documentation",
14232 **Menus[MagickMenus] =
14270 VisualDirectoryCommand,
14284 OriginalSizeCommand,
14291 TransformCommands[] =
14297 RotateRightCommand,
14304 EnhanceCommands[] =
14312 ContrastStretchCommand,
14313 SigmoidalContrastCommand,
14321 EffectsCommands[] =
14325 ReduceNoiseCommand,
14345 CharcoalDrawCommand
14347 ImageEditCommands[] =
14358 RegionofInterestCommand
14360 MiscellanyCommands[] =
14364 ShowPreviewCommand,
14365 ShowHistogramCommand,
14374 BrowseDocumentationCommand,
14377 ShortCutsCommands[] =
14389 VirtualCommands[] =
14398 *Commands[MagickMenus] =
14408 MiscellanyCommands,
14413 command[MaxTextExtent],
14415 geometry[MaxTextExtent],
14416 resource_name[MaxTextExtent];
14443 working_directory[MaxTextExtent];
14449 *magick_windows[MaxXWindows];
14451 static unsigned int
14511 assert(image != (Image **) NULL);
14512 assert((*image)->signature == MagickSignature);
14513 if ((*image)->debug != MagickFalse)
14514 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14515 display_image=(*image);
14516 warning_handler=(WarningHandler) NULL;
14517 windows=XSetWindows((XWindows *) ~0);
14518 if (windows != (XWindows *) NULL)
14523 status=chdir(working_directory);
14525 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14526 "UnableToOpenFile","%s",working_directory);
14527 warning_handler=resource_info->display_warnings ?
14528 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14529 warning_handler=resource_info->display_warnings ?
14530 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14535 Allocate windows structure.
14537 resource_info->colors=display_image->colors;
14538 windows=XSetWindows(XInitializeWindows(display,resource_info));
14539 if (windows == (XWindows *) NULL)
14540 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14541 (*image)->filename);
14543 Initialize window id's.
14546 magick_windows[number_windows++]=(&windows->icon);
14547 magick_windows[number_windows++]=(&windows->backdrop);
14548 magick_windows[number_windows++]=(&windows->image);
14549 magick_windows[number_windows++]=(&windows->info);
14550 magick_windows[number_windows++]=(&windows->command);
14551 magick_windows[number_windows++]=(&windows->widget);
14552 magick_windows[number_windows++]=(&windows->popup);
14553 magick_windows[number_windows++]=(&windows->magnify);
14554 magick_windows[number_windows++]=(&windows->pan);
14555 for (i=0; i < (int) number_windows; i++)
14556 magick_windows[i]->id=(Window) NULL;
14561 Initialize font info.
14563 if (windows->font_info != (XFontStruct *) NULL)
14564 (void) XFreeFont(display,windows->font_info);
14565 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14566 if (windows->font_info == (XFontStruct *) NULL)
14567 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14568 resource_info->font);
14570 Initialize Standard Colormap.
14572 map_info=windows->map_info;
14573 icon_map=windows->icon_map;
14574 visual_info=windows->visual_info;
14575 icon_visual=windows->icon_visual;
14576 pixel=windows->pixel_info;
14577 icon_pixel=windows->icon_pixel;
14578 font_info=windows->font_info;
14579 icon_resources=windows->icon_resources;
14580 class_hints=windows->class_hints;
14581 manager_hints=windows->manager_hints;
14582 root_window=XRootWindow(display,visual_info->screen);
14583 nexus=NewImageList();
14584 if (display_image->debug != MagickFalse)
14586 (void) LogMagickEvent(X11Event,GetMagickModule(),
14587 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14588 (double) display_image->scene,(double) display_image->columns,
14589 (double) display_image->rows);
14590 if (display_image->colors != 0)
14591 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14592 display_image->colors);
14593 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14594 display_image->magick);
14596 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14598 display_image->taint=MagickFalse;
14600 Initialize graphic context.
14602 windows->context.id=(Window) NULL;
14603 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14604 resource_info,&windows->context);
14605 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14606 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14607 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14608 manager_hints->flags=InputHint | StateHint;
14609 manager_hints->input=MagickFalse;
14610 manager_hints->initial_state=WithdrawnState;
14611 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14612 &windows->context);
14613 if (display_image->debug != MagickFalse)
14614 (void) LogMagickEvent(X11Event,GetMagickModule(),
14615 "Window id: 0x%lx (context)",windows->context.id);
14616 context_values.background=pixel->background_color.pixel;
14617 context_values.font=font_info->fid;
14618 context_values.foreground=pixel->foreground_color.pixel;
14619 context_values.graphics_exposures=MagickFalse;
14620 context_mask=(MagickStatusType)
14621 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14622 if (pixel->annotate_context != (GC) NULL)
14623 (void) XFreeGC(display,pixel->annotate_context);
14624 pixel->annotate_context=XCreateGC(display,windows->context.id,
14625 context_mask,&context_values);
14626 if (pixel->annotate_context == (GC) NULL)
14627 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14628 display_image->filename);
14629 context_values.background=pixel->depth_color.pixel;
14630 if (pixel->widget_context != (GC) NULL)
14631 (void) XFreeGC(display,pixel->widget_context);
14632 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14634 if (pixel->widget_context == (GC) NULL)
14635 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14636 display_image->filename);
14637 context_values.background=pixel->foreground_color.pixel;
14638 context_values.foreground=pixel->background_color.pixel;
14639 context_values.plane_mask=context_values.background ^
14640 context_values.foreground;
14641 if (pixel->highlight_context != (GC) NULL)
14642 (void) XFreeGC(display,pixel->highlight_context);
14643 pixel->highlight_context=XCreateGC(display,windows->context.id,
14644 (size_t) (context_mask | GCPlaneMask),&context_values);
14645 if (pixel->highlight_context == (GC) NULL)
14646 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14647 display_image->filename);
14648 (void) XDestroyWindow(display,windows->context.id);
14650 Initialize icon window.
14652 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14653 icon_resources,&windows->icon);
14654 windows->icon.geometry=resource_info->icon_geometry;
14655 XBestIconSize(display,&windows->icon,display_image);
14656 windows->icon.attributes.colormap=XDefaultColormap(display,
14657 icon_visual->screen);
14658 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14659 manager_hints->flags=InputHint | StateHint;
14660 manager_hints->input=MagickFalse;
14661 manager_hints->initial_state=IconicState;
14662 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14664 if (display_image->debug != MagickFalse)
14665 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14668 Initialize graphic context for icon window.
14670 if (icon_pixel->annotate_context != (GC) NULL)
14671 (void) XFreeGC(display,icon_pixel->annotate_context);
14672 context_values.background=icon_pixel->background_color.pixel;
14673 context_values.foreground=icon_pixel->foreground_color.pixel;
14674 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14675 (size_t) (GCBackground | GCForeground),&context_values);
14676 if (icon_pixel->annotate_context == (GC) NULL)
14677 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14678 display_image->filename);
14679 windows->icon.annotate_context=icon_pixel->annotate_context;
14681 Initialize Image window.
14683 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14685 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14686 if (resource_info->use_shared_memory == MagickFalse)
14687 windows->image.shared_memory=MagickFalse;
14688 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14693 title=InterpretImageProperties(resource_info->image_info,display_image,
14694 resource_info->title,exception);
14695 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14696 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14697 title=DestroyString(title);
14702 filename[MaxTextExtent];
14705 Window name is the base of the filename.
14707 GetPathComponent(display_image->magick_filename,TailPath,filename);
14708 if (display_image->scene == 0)
14709 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14710 "%s: %s",MagickPackageName,filename);
14712 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14713 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14714 (double) display_image->scene,(double) GetImageListLength(
14716 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14718 if (resource_info->immutable)
14719 windows->image.immutable=MagickTrue;
14720 windows->image.use_pixmap=resource_info->use_pixmap;
14721 windows->image.geometry=resource_info->image_geometry;
14722 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14723 XDisplayWidth(display,visual_info->screen),
14724 XDisplayHeight(display,visual_info->screen));
14725 geometry_info.width=display_image->columns;
14726 geometry_info.height=display_image->rows;
14729 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14730 &geometry_info.width,&geometry_info.height);
14731 windows->image.width=(unsigned int) geometry_info.width;
14732 windows->image.height=(unsigned int) geometry_info.height;
14733 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14734 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14735 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14736 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14737 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14738 resource_info,&windows->backdrop);
14739 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14742 Initialize backdrop window.
14744 windows->backdrop.x=0;
14745 windows->backdrop.y=0;
14746 (void) CloneString(&windows->backdrop.name,"Backdrop");
14747 windows->backdrop.flags=(size_t) (USSize | USPosition);
14748 windows->backdrop.width=(unsigned int)
14749 XDisplayWidth(display,visual_info->screen);
14750 windows->backdrop.height=(unsigned int)
14751 XDisplayHeight(display,visual_info->screen);
14752 windows->backdrop.border_width=0;
14753 windows->backdrop.immutable=MagickTrue;
14754 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14756 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14757 StructureNotifyMask;
14758 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14759 manager_hints->icon_window=windows->icon.id;
14760 manager_hints->input=MagickTrue;
14761 manager_hints->initial_state=resource_info->iconic ? IconicState :
14763 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14764 &windows->backdrop);
14765 if (display_image->debug != MagickFalse)
14766 (void) LogMagickEvent(X11Event,GetMagickModule(),
14767 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14768 (void) XMapWindow(display,windows->backdrop.id);
14769 (void) XClearWindow(display,windows->backdrop.id);
14770 if (windows->image.id != (Window) NULL)
14772 (void) XDestroyWindow(display,windows->image.id);
14773 windows->image.id=(Window) NULL;
14776 Position image in the center the backdrop.
14778 windows->image.flags|=USPosition;
14779 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14780 (windows->image.width/2);
14781 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14782 (windows->image.height/2);
14784 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14785 manager_hints->icon_window=windows->icon.id;
14786 manager_hints->input=MagickTrue;
14787 manager_hints->initial_state=resource_info->iconic ? IconicState :
14789 if (windows->group_leader.id != (Window) NULL)
14794 manager_hints->flags|=WindowGroupHint;
14795 manager_hints->window_group=windows->group_leader.id;
14796 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14797 if (display_image->debug != MagickFalse)
14798 (void) LogMagickEvent(X11Event,GetMagickModule(),
14799 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14801 XMakeWindow(display,
14802 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14803 argv,argc,class_hints,manager_hints,&windows->image);
14804 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14805 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14806 if (windows->group_leader.id != (Window) NULL)
14807 (void) XSetTransientForHint(display,windows->image.id,
14808 windows->group_leader.id);
14809 if (display_image->debug != MagickFalse)
14810 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14811 windows->image.id);
14813 Initialize Info widget.
14815 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14817 (void) CloneString(&windows->info.name,"Info");
14818 (void) CloneString(&windows->info.icon_name,"Info");
14819 windows->info.border_width=1;
14822 windows->info.flags|=PPosition;
14823 windows->info.attributes.win_gravity=UnmapGravity;
14824 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14825 StructureNotifyMask;
14826 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14827 manager_hints->input=MagickFalse;
14828 manager_hints->initial_state=NormalState;
14829 manager_hints->window_group=windows->image.id;
14830 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14832 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14833 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14834 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14835 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14836 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14837 if (windows->image.mapped != MagickFalse)
14838 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14839 if (display_image->debug != MagickFalse)
14840 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14843 Initialize Command widget.
14845 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14846 resource_info,&windows->command);
14847 windows->command.data=MagickMenus;
14848 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14849 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14850 resource_info->client_name);
14851 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14852 resource_name,"geometry",(char *) NULL);
14853 (void) CloneString(&windows->command.name,MagickTitle);
14854 windows->command.border_width=0;
14855 windows->command.flags|=PPosition;
14856 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14857 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14858 OwnerGrabButtonMask | StructureNotifyMask;
14859 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14860 manager_hints->input=MagickTrue;
14861 manager_hints->initial_state=NormalState;
14862 manager_hints->window_group=windows->image.id;
14863 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14864 &windows->command);
14865 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14866 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14868 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14869 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14870 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14871 if (windows->command.mapped != MagickFalse)
14872 (void) XMapRaised(display,windows->command.id);
14873 if (display_image->debug != MagickFalse)
14874 (void) LogMagickEvent(X11Event,GetMagickModule(),
14875 "Window id: 0x%lx (command)",windows->command.id);
14877 Initialize Widget window.
14879 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14880 resource_info,&windows->widget);
14881 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14882 resource_info->client_name);
14883 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14884 resource_name,"geometry",(char *) NULL);
14885 windows->widget.border_width=0;
14886 windows->widget.flags|=PPosition;
14887 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14888 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14889 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14890 StructureNotifyMask;
14891 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14892 manager_hints->input=MagickTrue;
14893 manager_hints->initial_state=NormalState;
14894 manager_hints->window_group=windows->image.id;
14895 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14897 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14898 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14899 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14900 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14901 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14902 if (display_image->debug != MagickFalse)
14903 (void) LogMagickEvent(X11Event,GetMagickModule(),
14904 "Window id: 0x%lx (widget)",windows->widget.id);
14906 Initialize popup window.
14908 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14909 resource_info,&windows->popup);
14910 windows->popup.border_width=0;
14911 windows->popup.flags|=PPosition;
14912 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14913 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14914 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14915 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14916 manager_hints->input=MagickTrue;
14917 manager_hints->initial_state=NormalState;
14918 manager_hints->window_group=windows->image.id;
14919 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14921 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14922 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14923 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14924 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14925 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14926 if (display_image->debug != MagickFalse)
14927 (void) LogMagickEvent(X11Event,GetMagickModule(),
14928 "Window id: 0x%lx (pop up)",windows->popup.id);
14930 Initialize Magnify window and cursor.
14932 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14933 resource_info,&windows->magnify);
14934 if (resource_info->use_shared_memory == MagickFalse)
14935 windows->magnify.shared_memory=MagickFalse;
14936 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14937 resource_info->client_name);
14938 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14939 resource_name,"geometry",(char *) NULL);
14940 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14941 resource_info->magnify);
14942 if (windows->magnify.cursor != (Cursor) NULL)
14943 (void) XFreeCursor(display,windows->magnify.cursor);
14944 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14945 map_info->colormap,resource_info->background_color,
14946 resource_info->foreground_color);
14947 if (windows->magnify.cursor == (Cursor) NULL)
14948 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14949 display_image->filename);
14950 windows->magnify.width=MagnifySize;
14951 windows->magnify.height=MagnifySize;
14952 windows->magnify.flags|=PPosition;
14953 windows->magnify.min_width=MagnifySize;
14954 windows->magnify.min_height=MagnifySize;
14955 windows->magnify.width_inc=MagnifySize;
14956 windows->magnify.height_inc=MagnifySize;
14957 windows->magnify.data=resource_info->magnify;
14958 windows->magnify.attributes.cursor=windows->magnify.cursor;
14959 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14960 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14961 StructureNotifyMask;
14962 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14963 manager_hints->input=MagickTrue;
14964 manager_hints->initial_state=NormalState;
14965 manager_hints->window_group=windows->image.id;
14966 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14967 &windows->magnify);
14968 if (display_image->debug != MagickFalse)
14969 (void) LogMagickEvent(X11Event,GetMagickModule(),
14970 "Window id: 0x%lx (magnify)",windows->magnify.id);
14971 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14973 Initialize panning window.
14975 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14976 resource_info,&windows->pan);
14977 (void) CloneString(&windows->pan.name,"Pan Icon");
14978 windows->pan.width=windows->icon.width;
14979 windows->pan.height=windows->icon.height;
14980 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
14981 resource_info->client_name);
14982 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14983 resource_name,"geometry",(char *) NULL);
14984 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14985 &windows->pan.width,&windows->pan.height);
14986 windows->pan.flags|=PPosition;
14987 windows->pan.immutable=MagickTrue;
14988 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14989 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
14990 StructureNotifyMask;
14991 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14992 manager_hints->input=MagickFalse;
14993 manager_hints->initial_state=NormalState;
14994 manager_hints->window_group=windows->image.id;
14995 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14997 if (display_image->debug != MagickFalse)
14998 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15000 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15001 if (windows->info.mapped != MagickFalse)
15002 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15003 if ((windows->image.mapped == MagickFalse) ||
15004 (windows->backdrop.id != (Window) NULL))
15005 (void) XMapWindow(display,windows->image.id);
15007 Set our progress monitor and warning handlers.
15009 if (warning_handler == (WarningHandler) NULL)
15011 warning_handler=resource_info->display_warnings ?
15012 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15013 warning_handler=resource_info->display_warnings ?
15014 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15017 Initialize Image and Magnify X images.
15019 windows->image.x=0;
15020 windows->image.y=0;
15021 windows->magnify.shape=MagickFalse;
15022 width=(unsigned int) display_image->columns;
15023 height=(unsigned int) display_image->rows;
15024 if ((display_image->columns != width) || (display_image->rows != height))
15025 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15026 display_image->filename);
15027 status=XMakeImage(display,resource_info,&windows->image,display_image,
15028 width,height,exception);
15029 if (status == MagickFalse)
15030 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15031 display_image->filename);
15032 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15033 windows->magnify.width,windows->magnify.height,exception);
15034 if (status == MagickFalse)
15035 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15036 display_image->filename);
15037 if (windows->magnify.mapped != MagickFalse)
15038 (void) XMapRaised(display,windows->magnify.id);
15039 if (windows->pan.mapped != MagickFalse)
15040 (void) XMapRaised(display,windows->pan.id);
15041 windows->image.window_changes.width=(int) display_image->columns;
15042 windows->image.window_changes.height=(int) display_image->rows;
15043 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15044 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15045 (void) XSync(display,MagickFalse);
15049 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15050 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15052 if (resource_info->update != MagickFalse)
15058 Determine when file data was last modified.
15060 status=GetPathAttributes(display_image->filename,&attributes);
15061 if (status != MagickFalse)
15062 update_time=attributes.st_mtime;
15064 *state&=(~FormerImageState);
15065 *state&=(~MontageImageState);
15066 *state&=(~NextImageState);
15070 Handle a window event.
15072 if (windows->image.mapped != MagickFalse)
15073 if ((display_image->delay != 0) || (resource_info->update != 0))
15075 if (timer < time((time_t *) NULL))
15077 if (resource_info->update == MagickFalse)
15078 *state|=NextImageState | ExitState;
15085 Determine if image file was modified.
15087 status=GetPathAttributes(display_image->filename,&attributes);
15088 if (status != MagickFalse)
15089 if (update_time != attributes.st_mtime)
15094 (void) FormatLocaleString(
15095 resource_info->image_info->filename,MaxTextExtent,
15096 "%s:%s",display_image->magick,
15097 display_image->filename);
15098 nexus=ReadImage(resource_info->image_info,
15099 &display_image->exception);
15100 if (nexus != (Image *) NULL)
15102 nexus=DestroyImage(nexus);
15103 *state|=NextImageState | ExitState;
15106 delay=display_image->delay/MagickMax(
15107 display_image->ticks_per_second,1L);
15108 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15111 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15114 Do not block if delay > 0.
15116 XDelay(display,SuspendTime << 2);
15120 timestamp=time((time_t *) NULL);
15121 (void) XNextEvent(display,&event);
15122 if (windows->image.stasis == MagickFalse)
15123 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15124 MagickTrue : MagickFalse;
15125 if (windows->magnify.stasis == MagickFalse)
15126 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15127 MagickTrue : MagickFalse;
15128 if (event.xany.window == windows->command.id)
15131 Select a command from the Command widget.
15133 id=XCommandWidget(display,windows,CommandMenu,&event);
15136 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15137 command_type=CommandMenus[id];
15138 if (id < MagickMenus)
15141 Select a command from a pop-up menu.
15143 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15147 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15148 command_type=Commands[id][entry];
15150 if (command_type != NullCommand)
15151 nexus=XMagickCommand(display,resource_info,windows,command_type,
15152 &display_image,exception);
15155 switch (event.type)
15159 if (display_image->debug != MagickFalse)
15160 (void) LogMagickEvent(X11Event,GetMagickModule(),
15161 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15162 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15163 if ((event.xbutton.button == Button3) &&
15164 (event.xbutton.state & Mod1Mask))
15167 Convert Alt-Button3 to Button2.
15169 event.xbutton.button=Button2;
15170 event.xbutton.state&=(~Mod1Mask);
15172 if (event.xbutton.window == windows->backdrop.id)
15174 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15175 event.xbutton.time);
15178 if (event.xbutton.window == windows->image.id)
15180 switch (event.xbutton.button)
15184 if (resource_info->immutable)
15187 Select a command from the Virtual menu.
15189 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15192 nexus=XMagickCommand(display,resource_info,windows,
15193 VirtualCommands[entry],&display_image,exception);
15197 Map/unmap Command widget.
15199 if (windows->command.mapped != MagickFalse)
15200 (void) XWithdrawWindow(display,windows->command.id,
15201 windows->command.screen);
15204 (void) XCommandWidget(display,windows,CommandMenu,
15206 (void) XMapRaised(display,windows->command.id);
15213 User pressed the image magnify button.
15215 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15216 &display_image,exception);
15217 XMagnifyImage(display,windows,&event);
15222 if (resource_info->immutable)
15225 Select a command from the Virtual menu.
15227 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15230 nexus=XMagickCommand(display,resource_info,windows,
15231 VirtualCommands[entry],&display_image,exception);
15234 if (display_image->montage != (char *) NULL)
15237 Open or delete a tile from a visual image directory.
15239 nexus=XTileImage(display,resource_info,windows,
15240 display_image,&event,exception);
15241 if (nexus != (Image *) NULL)
15242 *state|=MontageImageState | NextImageState | ExitState;
15243 vid_info.x=(short int) windows->image.x;
15244 vid_info.y=(short int) windows->image.y;
15248 Select a command from the Short Cuts menu.
15250 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15253 nexus=XMagickCommand(display,resource_info,windows,
15254 ShortCutsCommands[entry],&display_image,exception);
15262 XTranslateImage(display,windows,*image,XK_Up);
15270 XTranslateImage(display,windows,*image,XK_Down);
15278 if (event.xbutton.window == windows->magnify.id)
15298 MagnifyCommands[] =
15311 Select a magnify factor from the pop-up menu.
15313 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15315 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor]);
15318 if (event.xbutton.window == windows->pan.id)
15320 switch (event.xbutton.button)
15327 XTranslateImage(display,windows,*image,XK_Up);
15335 XTranslateImage(display,windows,*image,XK_Down);
15340 XPanImage(display,windows,&event);
15346 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15348 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15351 case ButtonRelease:
15353 if (display_image->debug != MagickFalse)
15354 (void) LogMagickEvent(X11Event,GetMagickModule(),
15355 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15356 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15359 case ClientMessage:
15361 if (display_image->debug != MagickFalse)
15362 (void) LogMagickEvent(X11Event,GetMagickModule(),
15363 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15364 event.xclient.message_type,event.xclient.format,(unsigned long)
15365 event.xclient.data.l[0]);
15366 if (event.xclient.message_type == windows->im_protocols)
15368 if (*event.xclient.data.l == (long) windows->im_update_widget)
15370 (void) CloneString(&windows->command.name,MagickTitle);
15371 windows->command.data=MagickMenus;
15372 (void) XCommandWidget(display,windows,CommandMenu,
15376 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15379 Update graphic context and window colormap.
15381 for (i=0; i < (int) number_windows; i++)
15383 if (magick_windows[i]->id == windows->icon.id)
15385 context_values.background=pixel->background_color.pixel;
15386 context_values.foreground=pixel->foreground_color.pixel;
15387 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15388 context_mask,&context_values);
15389 (void) XChangeGC(display,magick_windows[i]->widget_context,
15390 context_mask,&context_values);
15391 context_values.background=pixel->foreground_color.pixel;
15392 context_values.foreground=pixel->background_color.pixel;
15393 context_values.plane_mask=context_values.background ^
15394 context_values.foreground;
15395 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15396 (size_t) (context_mask | GCPlaneMask),
15398 magick_windows[i]->attributes.background_pixel=
15399 pixel->background_color.pixel;
15400 magick_windows[i]->attributes.border_pixel=
15401 pixel->border_color.pixel;
15402 magick_windows[i]->attributes.colormap=map_info->colormap;
15403 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15404 (unsigned long) magick_windows[i]->mask,
15405 &magick_windows[i]->attributes);
15407 if (windows->pan.mapped != MagickFalse)
15409 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15410 windows->pan.pixmap);
15411 (void) XClearWindow(display,windows->pan.id);
15412 XDrawPanRectangle(display,windows);
15414 if (windows->backdrop.id != (Window) NULL)
15415 (void) XInstallColormap(display,map_info->colormap);
15418 if (*event.xclient.data.l == (long) windows->im_former_image)
15420 *state|=FormerImageState | ExitState;
15423 if (*event.xclient.data.l == (long) windows->im_next_image)
15425 *state|=NextImageState | ExitState;
15428 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15430 *state|=RetainColorsState;
15433 if (*event.xclient.data.l == (long) windows->im_exit)
15440 if (event.xclient.message_type == windows->dnd_protocols)
15458 Display image named by the Drag-and-Drop selection.
15460 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15462 selection=XInternAtom(display,"DndSelection",MagickFalse);
15463 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15464 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15465 &length,&after,&data);
15466 if ((status != Success) || (length == 0))
15468 if (*event.xclient.data.l == 2)
15473 (void) CopyMagickString(resource_info->image_info->filename,
15474 (char *) data,MaxTextExtent);
15481 if (strncmp((char *) data, "file:", 5) != 0)
15483 (void) XFree((void *) data);
15486 (void) CopyMagickString(resource_info->image_info->filename,
15487 ((char *) data)+5,MaxTextExtent);
15489 nexus=ReadImage(resource_info->image_info,
15490 &display_image->exception);
15491 CatchException(&display_image->exception);
15492 if (nexus != (Image *) NULL)
15493 *state|=NextImageState | ExitState;
15494 (void) XFree((void *) data);
15498 If client window delete message, exit.
15500 if (event.xclient.message_type != windows->wm_protocols)
15502 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15504 (void) XWithdrawWindow(display,event.xclient.window,
15505 visual_info->screen);
15506 if (event.xclient.window == windows->image.id)
15511 if (event.xclient.window == windows->pan.id)
15514 Restore original image size when pan window is deleted.
15516 windows->image.window_changes.width=windows->image.ximage->width;
15517 windows->image.window_changes.height=windows->image.ximage->height;
15518 (void) XConfigureImage(display,resource_info,windows,
15519 display_image,exception);
15523 case ConfigureNotify:
15525 if (display_image->debug != MagickFalse)
15526 (void) LogMagickEvent(X11Event,GetMagickModule(),
15527 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15528 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15529 event.xconfigure.y,event.xconfigure.send_event);
15530 if (event.xconfigure.window == windows->image.id)
15533 Image window has a new configuration.
15535 if (event.xconfigure.send_event != 0)
15541 Position the transient windows relative of the Image window.
15543 if (windows->command.geometry == (char *) NULL)
15544 if (windows->command.mapped == MagickFalse)
15546 windows->command.x=event.xconfigure.x-
15547 windows->command.width-25;
15548 windows->command.y=event.xconfigure.y;
15549 XConstrainWindowPosition(display,&windows->command);
15550 window_changes.x=windows->command.x;
15551 window_changes.y=windows->command.y;
15552 (void) XReconfigureWMWindow(display,windows->command.id,
15553 windows->command.screen,(unsigned int) (CWX | CWY),
15556 if (windows->widget.geometry == (char *) NULL)
15557 if (windows->widget.mapped == MagickFalse)
15559 windows->widget.x=event.xconfigure.x+
15560 event.xconfigure.width/10;
15561 windows->widget.y=event.xconfigure.y+
15562 event.xconfigure.height/10;
15563 XConstrainWindowPosition(display,&windows->widget);
15564 window_changes.x=windows->widget.x;
15565 window_changes.y=windows->widget.y;
15566 (void) XReconfigureWMWindow(display,windows->widget.id,
15567 windows->widget.screen,(unsigned int) (CWX | CWY),
15570 if (windows->magnify.geometry == (char *) NULL)
15571 if (windows->magnify.mapped == MagickFalse)
15573 windows->magnify.x=event.xconfigure.x+
15574 event.xconfigure.width+25;
15575 windows->magnify.y=event.xconfigure.y;
15576 XConstrainWindowPosition(display,&windows->magnify);
15577 window_changes.x=windows->magnify.x;
15578 window_changes.y=windows->magnify.y;
15579 (void) XReconfigureWMWindow(display,windows->magnify.id,
15580 windows->magnify.screen,(unsigned int) (CWX | CWY),
15583 if (windows->pan.geometry == (char *) NULL)
15584 if (windows->pan.mapped == MagickFalse)
15586 windows->pan.x=event.xconfigure.x+
15587 event.xconfigure.width+25;
15588 windows->pan.y=event.xconfigure.y+
15589 windows->magnify.height+50;
15590 XConstrainWindowPosition(display,&windows->pan);
15591 window_changes.x=windows->pan.x;
15592 window_changes.y=windows->pan.y;
15593 (void) XReconfigureWMWindow(display,windows->pan.id,
15594 windows->pan.screen,(unsigned int) (CWX | CWY),
15598 if ((event.xconfigure.width == (int) windows->image.width) &&
15599 (event.xconfigure.height == (int) windows->image.height))
15601 windows->image.width=(unsigned int) event.xconfigure.width;
15602 windows->image.height=(unsigned int) event.xconfigure.height;
15603 windows->image.x=0;
15604 windows->image.y=0;
15605 if (display_image->montage != (char *) NULL)
15607 windows->image.x=vid_info.x;
15608 windows->image.y=vid_info.y;
15610 if ((windows->image.mapped != MagickFalse) &&
15611 (windows->image.stasis != MagickFalse))
15614 Update image window configuration.
15616 windows->image.window_changes.width=event.xconfigure.width;
15617 windows->image.window_changes.height=event.xconfigure.height;
15618 (void) XConfigureImage(display,resource_info,windows,
15619 display_image,exception);
15622 Update pan window configuration.
15624 if ((event.xconfigure.width < windows->image.ximage->width) ||
15625 (event.xconfigure.height < windows->image.ximage->height))
15627 (void) XMapRaised(display,windows->pan.id);
15628 XDrawPanRectangle(display,windows);
15631 if (windows->pan.mapped != MagickFalse)
15632 (void) XWithdrawWindow(display,windows->pan.id,
15633 windows->pan.screen);
15636 if (event.xconfigure.window == windows->magnify.id)
15642 Magnify window has a new configuration.
15644 windows->magnify.width=(unsigned int) event.xconfigure.width;
15645 windows->magnify.height=(unsigned int) event.xconfigure.height;
15646 if (windows->magnify.mapped == MagickFalse)
15649 while ((int) magnify <= event.xconfigure.width)
15651 while ((int) magnify <= event.xconfigure.height)
15654 if (((int) magnify != event.xconfigure.width) ||
15655 ((int) magnify != event.xconfigure.height))
15657 window_changes.width=(int) magnify;
15658 window_changes.height=(int) magnify;
15659 (void) XReconfigureWMWindow(display,windows->magnify.id,
15660 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15664 if ((windows->magnify.mapped != MagickFalse) &&
15665 (windows->magnify.stasis != MagickFalse))
15667 status=XMakeImage(display,resource_info,&windows->magnify,
15668 display_image,windows->magnify.width,windows->magnify.height,
15670 XMakeMagnifyImage(display,windows);
15674 if ((windows->magnify.mapped != MagickFalse) &&
15675 (event.xconfigure.window == windows->pan.id))
15678 Pan icon window has a new configuration.
15680 if (event.xconfigure.send_event != 0)
15682 windows->pan.x=event.xconfigure.x;
15683 windows->pan.y=event.xconfigure.y;
15685 windows->pan.width=(unsigned int) event.xconfigure.width;
15686 windows->pan.height=(unsigned int) event.xconfigure.height;
15689 if (event.xconfigure.window == windows->icon.id)
15692 Icon window has a new configuration.
15694 windows->icon.width=(unsigned int) event.xconfigure.width;
15695 windows->icon.height=(unsigned int) event.xconfigure.height;
15700 case DestroyNotify:
15703 Group leader has exited.
15705 if (display_image->debug != MagickFalse)
15706 (void) LogMagickEvent(X11Event,GetMagickModule(),
15707 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15708 if (event.xdestroywindow.window == windows->group_leader.id)
15718 Selectively install colormap.
15720 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15721 if (event.xcrossing.mode != NotifyUngrab)
15722 XInstallColormap(display,map_info->colormap);
15727 if (display_image->debug != MagickFalse)
15728 (void) LogMagickEvent(X11Event,GetMagickModule(),
15729 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15730 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15733 Refresh windows that are now exposed.
15735 if ((event.xexpose.window == windows->image.id) &&
15736 (windows->image.mapped != MagickFalse))
15738 XRefreshWindow(display,&windows->image,&event);
15739 delay=display_image->delay/MagickMax(
15740 display_image->ticks_per_second,1L);
15741 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15744 if ((event.xexpose.window == windows->magnify.id) &&
15745 (windows->magnify.mapped != MagickFalse))
15747 XMakeMagnifyImage(display,windows);
15750 if (event.xexpose.window == windows->pan.id)
15752 XDrawPanRectangle(display,windows);
15755 if (event.xexpose.window == windows->icon.id)
15757 XRefreshWindow(display,&windows->icon,&event);
15768 Respond to a user key press.
15770 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15771 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15772 *(command+length)='\0';
15773 if (display_image->debug != MagickFalse)
15774 (void) LogMagickEvent(X11Event,GetMagickModule(),
15775 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15776 key_symbol,command);
15777 if (event.xkey.window == windows->image.id)
15779 command_type=XImageWindowCommand(display,resource_info,windows,
15780 event.xkey.state,key_symbol,&display_image,exception);
15781 if (command_type != NullCommand)
15782 nexus=XMagickCommand(display,resource_info,windows,command_type,
15783 &display_image,exception);
15785 if (event.xkey.window == windows->magnify.id)
15786 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol);
15787 if (event.xkey.window == windows->pan.id)
15789 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15790 (void) XWithdrawWindow(display,windows->pan.id,
15791 windows->pan.screen);
15793 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15794 XTextViewWidget(display,resource_info,windows,MagickFalse,
15795 "Help Viewer - Image Pan",ImagePanHelp);
15797 XTranslateImage(display,windows,*image,key_symbol);
15799 delay=display_image->delay/MagickMax(
15800 display_image->ticks_per_second,1L);
15801 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15807 Respond to a user key release.
15809 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15810 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15811 if (display_image->debug != MagickFalse)
15812 (void) LogMagickEvent(X11Event,GetMagickModule(),
15813 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15819 Selectively uninstall colormap.
15821 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15822 if (event.xcrossing.mode != NotifyUngrab)
15823 XUninstallColormap(display,map_info->colormap);
15828 if (display_image->debug != MagickFalse)
15829 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15830 event.xmap.window);
15831 if (event.xmap.window == windows->backdrop.id)
15833 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15835 windows->backdrop.mapped=MagickTrue;
15838 if (event.xmap.window == windows->image.id)
15840 if (windows->backdrop.id != (Window) NULL)
15841 (void) XInstallColormap(display,map_info->colormap);
15842 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15844 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15845 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15847 if (((int) windows->image.width < windows->image.ximage->width) ||
15848 ((int) windows->image.height < windows->image.ximage->height))
15849 (void) XMapRaised(display,windows->pan.id);
15850 windows->image.mapped=MagickTrue;
15853 if (event.xmap.window == windows->magnify.id)
15855 XMakeMagnifyImage(display,windows);
15856 windows->magnify.mapped=MagickTrue;
15857 (void) XWithdrawWindow(display,windows->info.id,
15858 windows->info.screen);
15861 if (event.xmap.window == windows->pan.id)
15863 XMakePanImage(display,resource_info,windows,display_image,
15865 windows->pan.mapped=MagickTrue;
15868 if (event.xmap.window == windows->info.id)
15870 windows->info.mapped=MagickTrue;
15873 if (event.xmap.window == windows->icon.id)
15879 Create an icon image.
15881 taint=display_image->taint;
15882 XMakeStandardColormap(display,icon_visual,icon_resources,
15883 display_image,icon_map,icon_pixel);
15884 (void) XMakeImage(display,icon_resources,&windows->icon,
15885 display_image,windows->icon.width,windows->icon.height,
15887 display_image->taint=taint;
15888 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15889 windows->icon.pixmap);
15890 (void) XClearWindow(display,windows->icon.id);
15891 (void) XWithdrawWindow(display,windows->info.id,
15892 windows->info.screen);
15893 windows->icon.mapped=MagickTrue;
15896 if (event.xmap.window == windows->command.id)
15898 windows->command.mapped=MagickTrue;
15901 if (event.xmap.window == windows->popup.id)
15903 windows->popup.mapped=MagickTrue;
15906 if (event.xmap.window == windows->widget.id)
15908 windows->widget.mapped=MagickTrue;
15913 case MappingNotify:
15915 (void) XRefreshKeyboardMapping(&event.xmapping);
15920 case PropertyNotify:
15936 if (display_image->debug != MagickFalse)
15937 (void) LogMagickEvent(X11Event,GetMagickModule(),
15938 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15939 event.xproperty.atom,event.xproperty.state);
15940 if (event.xproperty.atom != windows->im_remote_command)
15943 Display image named by the remote command protocol.
15945 status=XGetWindowProperty(display,event.xproperty.window,
15946 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15947 AnyPropertyType,&type,&format,&length,&after,&data);
15948 if ((status != Success) || (length == 0))
15950 if (LocaleCompare((char *) data,"-quit") == 0)
15952 XClientMessage(display,windows->image.id,windows->im_protocols,
15953 windows->im_exit,CurrentTime);
15954 (void) XFree((void *) data);
15957 (void) CopyMagickString(resource_info->image_info->filename,
15958 (char *) data,MaxTextExtent);
15959 (void) XFree((void *) data);
15960 nexus=ReadImage(resource_info->image_info,&display_image->exception);
15961 CatchException(&display_image->exception);
15962 if (nexus != (Image *) NULL)
15963 *state|=NextImageState | ExitState;
15966 case ReparentNotify:
15968 if (display_image->debug != MagickFalse)
15969 (void) LogMagickEvent(X11Event,GetMagickModule(),
15970 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15971 event.xreparent.window);
15976 if (display_image->debug != MagickFalse)
15977 (void) LogMagickEvent(X11Event,GetMagickModule(),
15978 "Unmap Notify: 0x%lx",event.xunmap.window);
15979 if (event.xunmap.window == windows->backdrop.id)
15981 windows->backdrop.mapped=MagickFalse;
15984 if (event.xunmap.window == windows->image.id)
15986 windows->image.mapped=MagickFalse;
15989 if (event.xunmap.window == windows->magnify.id)
15991 windows->magnify.mapped=MagickFalse;
15994 if (event.xunmap.window == windows->pan.id)
15996 windows->pan.mapped=MagickFalse;
15999 if (event.xunmap.window == windows->info.id)
16001 windows->info.mapped=MagickFalse;
16004 if (event.xunmap.window == windows->icon.id)
16006 if (map_info->colormap == icon_map->colormap)
16007 XConfigureImageColormap(display,resource_info,windows,
16009 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16011 windows->icon.mapped=MagickFalse;
16014 if (event.xunmap.window == windows->command.id)
16016 windows->command.mapped=MagickFalse;
16019 if (event.xunmap.window == windows->popup.id)
16021 if (windows->backdrop.id != (Window) NULL)
16022 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16024 windows->popup.mapped=MagickFalse;
16027 if (event.xunmap.window == windows->widget.id)
16029 if (windows->backdrop.id != (Window) NULL)
16030 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16032 windows->widget.mapped=MagickFalse;
16039 if (display_image->debug != MagickFalse)
16040 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16045 } while (!(*state & ExitState));
16046 if ((*state & ExitState) == 0)
16047 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16048 &display_image,exception);
16050 if (resource_info->confirm_edit != MagickFalse)
16053 Query user if image has changed.
16055 if ((resource_info->immutable == MagickFalse) &&
16056 (display_image->taint != MagickFalse))
16061 status=XConfirmWidget(display,windows,"Your image changed.",
16062 "Do you want to save it");
16064 *state&=(~ExitState);
16067 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16068 &display_image,exception);
16071 if ((windows->visual_info->klass == GrayScale) ||
16072 (windows->visual_info->klass == PseudoColor) ||
16073 (windows->visual_info->klass == DirectColor))
16076 Withdraw pan and Magnify window.
16078 if (windows->info.mapped != MagickFalse)
16079 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16080 if (windows->magnify.mapped != MagickFalse)
16081 (void) XWithdrawWindow(display,windows->magnify.id,
16082 windows->magnify.screen);
16083 if (windows->command.mapped != MagickFalse)
16084 (void) XWithdrawWindow(display,windows->command.id,
16085 windows->command.screen);
16087 if (windows->pan.mapped != MagickFalse)
16088 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16089 if (resource_info->backdrop == MagickFalse)
16090 if (windows->backdrop.mapped)
16092 (void) XWithdrawWindow(display,windows->backdrop.id,
16093 windows->backdrop.screen);
16094 (void) XDestroyWindow(display,windows->backdrop.id);
16095 windows->backdrop.id=(Window) NULL;
16096 (void) XWithdrawWindow(display,windows->image.id,
16097 windows->image.screen);
16098 (void) XDestroyWindow(display,windows->image.id);
16099 windows->image.id=(Window) NULL;
16101 XSetCursorState(display,windows,MagickTrue);
16102 XCheckRefreshWindows(display,windows);
16103 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16104 *state&=(~ExitState);
16105 if (*state & ExitState)
16108 Free Standard Colormap.
16110 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16111 if (resource_info->map_type == (char *) NULL)
16112 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16116 if (resource_info->copy_image != (Image *) NULL)
16118 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16119 resource_info->copy_image=NewImageList();
16121 DestroyXResources();
16123 (void) XSync(display,MagickFalse);
16125 Restore our progress monitor and warning handlers.
16127 (void) SetErrorHandler(warning_handler);
16128 (void) SetWarningHandler(warning_handler);
16130 Change to home directory.
16132 directory=getcwd(working_directory,MaxTextExtent);
16138 status=chdir(resource_info->home_directory);
16140 (void) ThrowMagickException(&display_image->exception,GetMagickModule(),
16141 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
16143 *image=display_image;
16149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16153 + D i s p l a y I m a g e s %
16157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16159 % DisplayImages() displays an image sequence to any X window screen. It
16160 % returns a value other than 0 if successful. Check the exception member
16161 % of image to determine the reason for any failure.
16163 % The format of the DisplayImages method is:
16165 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16166 % Image *images,ExceptionInfo *exception)
16168 % A description of each parameter follows:
16170 % o image_info: the image info.
16172 % o image: the image.
16174 % o exception: return any errors or warnings in this structure.
16177 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16178 Image *image,ExceptionInfo *exception)
16180 assert(image_info != (const ImageInfo *) NULL);
16181 assert(image_info->signature == MagickSignature);
16182 assert(image != (Image *) NULL);
16183 assert(image->signature == MagickSignature);
16184 if (image->debug != MagickFalse)
16185 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16186 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16187 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
16188 return(MagickFalse);
16192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16196 + R e m o t e D i s p l a y C o m m a n d %
16200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16202 % RemoteDisplayCommand() encourages a remote display program to display the
16203 % specified image filename.
16205 % The format of the RemoteDisplayCommand method is:
16207 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16208 % const char *window,const char *filename,ExceptionInfo *exception)
16210 % A description of each parameter follows:
16212 % o image_info: the image info.
16214 % o window: Specifies the name or id of an X window.
16216 % o filename: the name of the image filename to display.
16218 % o exception: return any errors or warnings in this structure.
16221 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16222 const char *window,const char *filename,ExceptionInfo *exception)
16224 assert(image_info != (const ImageInfo *) NULL);
16225 assert(image_info->signature == MagickSignature);
16226 assert(filename != (char *) NULL);
16228 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16229 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16230 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename);
16231 return(MagickFalse);