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-2012 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/artifact.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/cache-private.h"
47 #include "MagickCore/client.h"
48 #include "MagickCore/color.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/composite.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/decorate.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/display.h"
55 #include "MagickCore/display-private.h"
56 #include "MagickCore/distort.h"
57 #include "MagickCore/draw.h"
58 #include "MagickCore/effect.h"
59 #include "MagickCore/enhance.h"
60 #include "MagickCore/exception.h"
61 #include "MagickCore/exception-private.h"
62 #include "MagickCore/fx.h"
63 #include "MagickCore/geometry.h"
64 #include "MagickCore/image.h"
65 #include "MagickCore/image-private.h"
66 #include "MagickCore/list.h"
67 #include "MagickCore/log.h"
68 #include "MagickCore/magick.h"
69 #include "MagickCore/memory_.h"
70 #include "MagickCore/monitor.h"
71 #include "MagickCore/monitor-private.h"
72 #include "MagickCore/montage.h"
73 #include "MagickCore/option.h"
74 #include "MagickCore/paint.h"
75 #include "MagickCore/pixel.h"
76 #include "MagickCore/pixel-accessor.h"
77 #include "MagickCore/PreRvIcccm.h"
78 #include "MagickCore/property.h"
79 #include "MagickCore/quantum.h"
80 #include "MagickCore/quantum-private.h"
81 #include "MagickCore/resize.h"
82 #include "MagickCore/resource_.h"
83 #include "MagickCore/shear.h"
84 #include "MagickCore/segment.h"
85 #include "MagickCore/statistic.h"
86 #include "MagickCore/string_.h"
87 #include "MagickCore/string-private.h"
88 #include "MagickCore/transform.h"
89 #include "MagickCore/threshold.h"
90 #include "MagickCore/utility.h"
91 #include "MagickCore/utility-private.h"
92 #include "MagickCore/version.h"
93 #include "MagickCore/widget.h"
94 #include "MagickCore/widget-private.h"
95 #include "MagickCore/xwindow.h"
96 #include "MagickCore/xwindow-private.h"
98 #if defined(MAGICKCORE_X11_DELEGATE)
102 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
105 Constant declarations.
107 static const unsigned char
110 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
114 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
142 Help widget declarations.
145 *ImageAnnotateHelp[] =
147 "In annotate mode, the Command widget has these options:",
197 "Choose a font name from the Font Name sub-menu. Additional",
198 "font names can be specified with the font browser. You can",
199 "change the menu names by setting the X resources font1",
202 "Choose a font color from the Font Color sub-menu.",
203 "Additional font colors can be specified with the color",
204 "browser. You can change the menu colors by setting the X",
205 "resources pen1 through pen9.",
207 "If you select the color browser and press Grab, you can",
208 "choose the font color by moving the pointer to the desired",
209 "color on the screen and press any button.",
211 "If you choose to rotate the text, choose Rotate Text from the",
212 "menu and select an angle. Typically you will only want to",
213 "rotate one line of text at a time. Depending on the angle you",
214 "choose, subsequent lines may end up overwriting each other.",
216 "Choosing a font and its color is optional. The default font",
217 "is fixed and the default color is black. However, you must",
218 "choose a location to begin entering text and press button 1.",
219 "An underscore character will appear at the location of the",
220 "pointer. The cursor changes to a pencil to indicate you are",
221 "in text mode. To exit immediately, press Dismiss.",
223 "In text mode, any key presses will display the character at",
224 "the location of the underscore and advance the underscore",
225 "cursor. Enter your text and once completed press Apply to",
226 "finish your image annotation. To correct errors press BACK",
227 "SPACE. To delete an entire line of text, press DELETE. Any",
228 "text that exceeds the boundaries of the image window is",
229 "automagically continued onto the next line.",
231 "The actual color you request for the font is saved in the",
232 "image. However, the color that appears in your image window",
233 "may be different. For example, on a monochrome screen the",
234 "text will appear black or white even if you choose the color",
235 "red as the font color. However, the image saved to a file",
236 "with -write is written with red lettering. To assure the",
237 "correct color text in the final image, any PseudoClass image",
238 "is promoted to DirectClass (see miff(5)). To force a",
239 "PseudoClass image to remain PseudoClass, use -colors.",
244 "In chop mode, the Command widget has these options:",
252 "If the you choose the horizontal direction (this the",
253 "default), the area of the image between the two horizontal",
254 "endpoints of the chop line is removed. Otherwise, the area",
255 "of the image between the two vertical endpoints of the chop",
258 "Select a location within the image window to begin your chop,",
259 "press and hold any button. Next, move the pointer to",
260 "another location in the image. As you move a line will",
261 "connect the initial location and the pointer. When you",
262 "release the button, the area within the image to chop is",
263 "determined by which direction you choose from the Command",
266 "To cancel the image chopping, move the pointer back to the",
267 "starting point of the line and release the button.",
270 *ImageColorEditHelp[] =
272 "In color edit mode, the Command widget has these options:",
313 "Choose a color editing method from the Method sub-menu",
314 "of the Command widget. The point method recolors any pixel",
315 "selected with the pointer until the button is released. The",
316 "replace method recolors any pixel that matches the color of",
317 "the pixel you select with a button press. Floodfill recolors",
318 "any pixel that matches the color of the pixel you select with",
319 "a button press and is a neighbor. Whereas filltoborder recolors",
320 "any neighbor pixel that is not the border color. Finally reset",
321 "changes the entire image to the designated color.",
323 "Next, choose a pixel color from the Pixel Color sub-menu.",
324 "Additional pixel colors can be specified with the color",
325 "browser. You can change the menu colors by setting the X",
326 "resources pen1 through pen9.",
328 "Now press button 1 to select a pixel within the image window",
329 "to change its color. Additional pixels may be recolored as",
330 "prescribed by the method you choose.",
332 "If the Magnify widget is mapped, it can be helpful in positioning",
333 "your pointer within the image (refer to button 2).",
335 "The actual color you request for the pixels is saved in the",
336 "image. However, the color that appears in your image window",
337 "may be different. For example, on a monochrome screen the",
338 "pixel will appear black or white even if you choose the",
339 "color red as the pixel color. However, the image saved to a",
340 "file with -write is written with red pixels. To assure the",
341 "correct color text in the final image, any PseudoClass image",
342 "is promoted to DirectClass (see miff(5)). To force a",
343 "PseudoClass image to remain PseudoClass, use -colors.",
346 *ImageCompositeHelp[] =
348 "First a widget window is displayed requesting you to enter an",
349 "image name. Press Composite, Grab or type a file name.",
350 "Press Cancel if you choose not to create a composite image.",
351 "When you choose Grab, move the pointer to the desired window",
352 "and press any button.",
354 "If the Composite image does not have any matte information,",
355 "you are informed and the file browser is displayed again.",
356 "Enter the name of a mask image. The image is typically",
357 "grayscale and the same size as the composite image. If the",
358 "image is not grayscale, it is converted to grayscale and the",
359 "resulting intensities are used as matte information.",
361 "A small window appears showing the location of the cursor in",
362 "the image window. You are now in composite mode. To exit",
363 "immediately, press Dismiss. In composite mode, the Command",
364 "widget has these options:",
390 "Choose a composite operation from the Operators sub-menu of",
391 "the Command widget. How each operator behaves is described",
392 "below. Image window is the image currently displayed on",
393 "your X server and image is the image obtained with the File",
396 "Over The result is the union of the two image shapes,",
397 " with image obscuring image window in the region of",
400 "In The result is simply image cut by the shape of",
401 " image window. None of the image data of image",
402 " window is in the result.",
404 "Out The resulting image is image with the shape of",
405 " image window cut out.",
407 "Atop The result is the same shape as image image window,",
408 " with image obscuring image window where the image",
409 " shapes overlap. Note this differs from over",
410 " because the portion of image outside image window's",
411 " shape does not appear in the result.",
413 "Xor The result is the image data from both image and",
414 " image window that is outside the overlap region.",
415 " The overlap region is blank.",
417 "Plus The result is just the sum of the image data.",
418 " Output values are cropped to QuantumRange (no overflow).",
420 "Minus The result of image - image window, with underflow",
423 "Add The result of image + image window, with overflow",
424 " wrapping around (mod 256).",
426 "Subtract The result of image - image window, with underflow",
427 " wrapping around (mod 256). The add and subtract",
428 " operators can be used to perform reversible",
432 " The result of abs(image - image window). This",
433 " useful for comparing two very similar images.",
436 " The result of image * image window. This",
437 " useful for the creation of drop-shadows.",
439 "Bumpmap The result of surface normals from image * image",
442 "Copy The resulting image is image window replaced with",
443 " image. Here the matte information is ignored.",
445 "CopyRed The red layer of the image window is replace with",
446 " the red layer of the image. The other layers are",
450 " The green layer of the image window is replace with",
451 " the green layer of the image. The other layers are",
454 "CopyBlue The blue layer of the image window is replace with",
455 " the blue layer of the image. The other layers are",
459 " The matte layer of the image window is replace with",
460 " the matte layer of the image. The other layers are",
463 "The image compositor requires a matte, or alpha channel in",
464 "the image for some operations. This extra channel usually",
465 "defines a mask which represents a sort of a cookie-cutter",
466 "for the image. This the case when matte is opaque (full",
467 "coverage) for pixels inside the shape, zero outside, and",
468 "between 0 and QuantumRange on the boundary. If image does not",
469 "have a matte channel, it is initialized with 0 for any pixel",
470 "matching in color to pixel location (0,0), otherwise QuantumRange.",
472 "If you choose Dissolve, the composite operator becomes Over. The",
473 "image matte channel percent transparency is initialized to factor.",
474 "The image window is initialized to (100-factor). Where factor is the",
475 "value you specify in the Dialog widget.",
477 "Displace shifts the image pixels as defined by a displacement",
478 "map. With this option, image is used as a displacement map.",
479 "Black, within the displacement map, is a maximum positive",
480 "displacement. White is a maximum negative displacement and",
481 "middle gray is neutral. The displacement is scaled to determine",
482 "the pixel shift. By default, the displacement applies in both the",
483 "horizontal and vertical directions. However, if you specify a mask,",
484 "image is the horizontal X displacement and mask the vertical Y",
487 "Note that matte information for image window is not retained",
488 "for colormapped X server visuals (e.g. StaticColor,",
489 "StaticColor, GrayScale, PseudoColor). Correct compositing",
490 "behavior may require a TrueColor or DirectColor visual or a",
491 "Standard Colormap.",
493 "Choosing a composite operator is optional. The default",
494 "operator is replace. However, you must choose a location to",
495 "composite your image and press button 1. Press and hold the",
496 "button before releasing and an outline of the image will",
497 "appear to help you identify your location.",
499 "The actual colors of the composite image is saved. However,",
500 "the color that appears in image window may be different.",
501 "For example, on a monochrome screen image window will appear",
502 "black or white even though your composited image may have",
503 "many colors. If the image is saved to a file it is written",
504 "with the correct colors. To assure the correct colors are",
505 "saved in the final image, any PseudoClass image is promoted",
506 "to DirectClass (see miff(5)). To force a PseudoClass image",
507 "to remain PseudoClass, use -colors.",
512 "In cut mode, the Command widget has these options:",
517 "To define a cut region, press button 1 and drag. The",
518 "cut region is defined by a highlighted rectangle that",
519 "expands or contracts as it follows the pointer. Once you",
520 "are satisfied with the cut region, release the button.",
521 "You are now in rectify mode. In rectify mode, the Command",
522 "widget has these options:",
528 "You can make adjustments by moving the pointer to one of the",
529 "cut rectangle corners, pressing a button, and dragging.",
530 "Finally, press Cut to commit your copy region. To",
531 "exit without cutting the image, press Dismiss.",
536 "In copy mode, the Command widget has these options:",
541 "To define a copy region, press button 1 and drag. The",
542 "copy region is defined by a highlighted rectangle that",
543 "expands or contracts as it follows the pointer. Once you",
544 "are satisfied with the copy region, release the button.",
545 "You are now in rectify mode. In rectify mode, the Command",
546 "widget has these options:",
552 "You can make adjustments by moving the pointer to one of the",
553 "copy rectangle corners, pressing a button, and dragging.",
554 "Finally, press Copy to commit your copy region. To",
555 "exit without copying the image, press Dismiss.",
560 "In crop mode, the Command widget has these options:",
565 "To define a cropping region, press button 1 and drag. The",
566 "cropping region is defined by a highlighted rectangle that",
567 "expands or contracts as it follows the pointer. Once you",
568 "are satisfied with the cropping region, release the button.",
569 "You are now in rectify mode. In rectify mode, the Command",
570 "widget has these options:",
576 "You can make adjustments by moving the pointer to one of the",
577 "cropping rectangle corners, pressing a button, and dragging.",
578 "Finally, press Crop to commit your cropping region. To",
579 "exit without cropping the image, press Dismiss.",
584 "The cursor changes to a crosshair to indicate you are in",
585 "draw mode. To exit immediately, press Dismiss. In draw mode,",
586 "the Command widget has these options:",
631 "Choose a drawing primitive from the Element sub-menu.",
633 "Choose a color from the Color sub-menu. Additional",
634 "colors can be specified with the color browser.",
636 "If you choose the color browser and press Grab, you can",
637 "select the color by moving the pointer to the desired",
638 "color on the screen and press any button. The transparent",
639 "color updates the image matte channel and is useful for",
640 "image compositing.",
642 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
643 "Additional stipples can be specified with the file browser.",
644 "Stipples obtained from the file browser must be on disk in the",
645 "X11 bitmap format.",
647 "Choose a width, if appropriate, from the Width sub-menu. To",
648 "choose a specific width select the Dialog widget.",
650 "Choose a point in the Image window and press button 1 and",
651 "hold. Next, move the pointer to another location in the",
652 "image. As you move, a line connects the initial location and",
653 "the pointer. When you release the button, the image is",
654 "updated with the primitive you just drew. For polygons, the",
655 "image is updated when you press and release the button without",
656 "moving the pointer.",
658 "To cancel image drawing, move the pointer back to the",
659 "starting point of the line and release the button.",
665 " The effects of each button press is described below. Three",
666 " buttons are required. If you have a two button mouse,",
667 " button 1 and 3 are returned. Press ALT and button 3 to",
668 " simulate button 2.",
670 " 1 Press this button to map or unmap the Command widget.",
672 " 2 Press and drag to define a region of the image to",
675 " 3 Press and drag to choose from a select set of commands.",
676 " This button behaves differently if the image being",
677 " displayed is a visual image directory. Here, choose a",
678 " particular tile of the directory and press this button and",
679 " drag to select a command from a pop-up menu. Choose from",
680 " these menu items:",
688 " If you choose Open, the image represented by the tile is",
689 " displayed. To return to the visual image directory, choose",
690 " Next from the Command widget. Next and Former moves to the",
691 " next or former image respectively. Choose Delete to delete",
692 " a particular image tile. Finally, choose Update to",
693 " synchronize all the image tiles with their respective",
697 " The Command widget lists a number of sub-menus and commands.",
709 " Visual Directory...",
743 " Contrast Stretch...",
744 " Sigmoidal Contrast...",
772 " Charcoal Drawing...",
783 " Region of Interest...",
795 " Browse Documentation",
798 " Menu items with a indented triangle have a sub-menu. They",
799 " are represented above as the indented items. To access a",
800 " sub-menu item, move the pointer to the appropriate menu and",
801 " press a button and drag. When you find the desired sub-menu",
802 " item, release the button and the command is executed. Move",
803 " the pointer away from the sub-menu if you decide not to",
804 " execute a particular command.",
806 "KEYBOARD ACCELERATORS",
807 " Accelerators are one or two key presses that effect a",
808 " particular command. The keyboard accelerators that",
809 " display(1) understands is:",
811 " Ctl+O Press to open an image from a file.",
813 " space Press to display the next image.",
815 " If the image is a multi-paged document such as a Postscript",
816 " document, you can skip ahead several pages by preceding",
817 " this command with a number. For example to display the",
818 " third page beyond the current page, press 3<space>.",
820 " backspace Press to display the former image.",
822 " If the image is a multi-paged document such as a Postscript",
823 " document, you can skip behind several pages by preceding",
824 " this command with a number. For example to display the",
825 " third page preceding the current page, press 3<backspace>.",
827 " Ctl+S Press to write the image to a file.",
829 " Ctl+P Press to print the image to a Postscript printer.",
831 " Ctl+D Press to delete an image file.",
833 " Ctl+N Press to create a blank canvas.",
835 " Ctl+Q Press to discard all images and exit program.",
837 " Ctl+Z Press to undo last image transformation.",
839 " Ctl+R Press to redo last image transformation.",
841 " Ctl+X Press to cut a region of the image.",
843 " Ctl+C Press to copy a region of the image.",
845 " Ctl+V Press to paste a region to the image.",
847 " < Press to half the image size.",
849 " - Press to return to the original image size.",
851 " > Press to double the image size.",
853 " % Press to resize the image to a width and height you",
856 "Cmd-A Press to make any image transformations permanent."
858 " By default, any image size transformations are applied",
859 " to the original image to create the image displayed on",
860 " the X server. However, the transformations are not",
861 " permanent (i.e. the original image does not change",
862 " size only the X image does). For example, if you",
863 " press > the X image will appear to double in size,",
864 " but the original image will in fact remain the same size.",
865 " To force the original image to double in size, press >",
866 " followed by Cmd-A.",
868 " @ Press to refresh the image window.",
870 " C Press to cut out a rectangular region of the image.",
872 " [ Press to chop the image.",
874 " H Press to flop image in the horizontal direction.",
876 " V Press to flip image in the vertical direction.",
878 " / Press to rotate the image 90 degrees clockwise.",
880 " \\ Press to rotate the image 90 degrees counter-clockwise.",
882 " * Press to rotate the image the number of degrees you",
885 " S Press to shear the image the number of degrees you",
888 " R Press to roll the image.",
890 " T Press to trim the image edges.",
892 " Shft-H Press to vary the image hue.",
894 " Shft-S Press to vary the color saturation.",
896 " Shft-L Press to vary the color brightness.",
898 " Shft-G Press to gamma correct the image.",
900 " Shft-C Press to sharpen the image contrast.",
902 " Shft-Z Press to dull the image contrast.",
904 " = Press to perform histogram equalization on the image.",
906 " Shft-N Press to perform histogram normalization on the image.",
908 " Shft-~ Press to negate the colors of the image.",
910 " . Press to convert the image colors to gray.",
912 " Shft-# Press to set the maximum number of unique colors in the",
915 " F2 Press to reduce the speckles in an image.",
917 " F3 Press to eliminate peak noise from an image.",
919 " F4 Press to add noise to an image.",
921 " F5 Press to sharpen an image.",
923 " F6 Press to delete an image file.",
925 " F7 Press to threshold the image.",
927 " F8 Press to detect edges within an image.",
929 " F9 Press to emboss an image.",
931 " F10 Press to displace pixels by a random amount.",
933 " F11 Press to negate all pixels above the threshold level.",
935 " F12 Press to shade the image using a distant light source.",
937 " F13 Press to lighten or darken image edges to create a 3-D effect.",
939 " F14 Press to segment the image by color.",
941 " Meta-S Press to swirl image pixels about the center.",
943 " Meta-I Press to implode image pixels about the center.",
945 " Meta-W Press to alter an image along a sine wave.",
947 " Meta-P Press to simulate an oil painting.",
949 " Meta-C Press to simulate a charcoal drawing.",
951 " Alt-A Press to annotate the image with text.",
953 " Alt-D Press to draw on an image.",
955 " Alt-P Press to edit an image pixel color.",
957 " Alt-M Press to edit the image matte information.",
959 " Alt-V Press to composite the image with another.",
961 " Alt-B Press to add a border to the image.",
963 " Alt-F Press to add an ornamental border to the image.",
966 " Press to add an image comment.",
968 " Ctl-A Press to apply image processing techniques to a region",
971 " Shft-? Press to display information about the image.",
973 " Shft-+ Press to map the zoom image window.",
975 " Shft-P Press to preview an image enhancement, effect, or f/x.",
977 " F1 Press to display helpful information about display(1).",
979 " Find Press to browse documentation about ImageMagick.",
981 " 1-9 Press to change the level of magnification.",
983 " Use the arrow keys to move the image one pixel up, down,",
984 " left, or right within the magnify window. Be sure to first",
985 " map the magnify window by pressing button 2.",
987 " Press ALT and one of the arrow keys to trim off one pixel",
988 " from any side of the image.",
991 *ImageMatteEditHelp[] =
993 "Matte information within an image is useful for some",
994 "operations such as image compositing (See IMAGE",
995 "COMPOSITING). This extra channel usually defines a mask",
996 "which represents a sort of a cookie-cutter for the image.",
997 "This the case when matte is opaque (full coverage) for",
998 "pixels inside the shape, zero outside, and between 0 and",
999 "QuantumRange on the boundary.",
1001 "A small window appears showing the location of the cursor in",
1002 "the image window. You are now in matte edit mode. To exit",
1003 "immediately, press Dismiss. In matte edit mode, the Command",
1004 "widget has these options:",
1038 "Choose a matte editing method from the Method sub-menu of",
1039 "the Command widget. The point method changes the matte value",
1040 "of any pixel selected with the pointer until the button is",
1041 "is released. The replace method changes the matte value of",
1042 "any pixel that matches the color of the pixel you select with",
1043 "a button press. Floodfill changes the matte value of any pixel",
1044 "that matches the color of the pixel you select with a button",
1045 "press and is a neighbor. Whereas filltoborder changes the matte",
1046 "value any neighbor pixel that is not the border color. Finally",
1047 "reset changes the entire image to the designated matte value.",
1049 "Choose Matte Value and pick Opaque or Transarent. For other values",
1050 "select the Dialog entry. Here a dialog appears requesting a matte",
1051 "value. The value you select is assigned as the opacity value of the",
1052 "selected pixel or pixels.",
1054 "Now, press any button to select a pixel within the image",
1055 "window to change its matte value.",
1057 "If the Magnify widget is mapped, it can be helpful in positioning",
1058 "your pointer within the image (refer to button 2).",
1060 "Matte information is only valid in a DirectClass image.",
1061 "Therefore, any PseudoClass image is promoted to DirectClass",
1062 "(see miff(5)). Note that matte information for PseudoClass",
1063 "is not retained for colormapped X server visuals (e.g.",
1064 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1065 "immediately save your image to a file (refer to Write).",
1066 "Correct matte editing behavior may require a TrueColor or",
1067 "DirectColor visual or a Standard Colormap.",
1072 "When an image exceeds the width or height of the X server",
1073 "screen, display maps a small panning icon. The rectangle",
1074 "within the panning icon shows the area that is currently",
1075 "displayed in the image window. To pan about the image,",
1076 "press any button and drag the pointer within the panning",
1077 "icon. The pan rectangle moves with the pointer and the",
1078 "image window is updated to reflect the location of the",
1079 "rectangle within the panning icon. When you have selected",
1080 "the area of the image you wish to view, release the button.",
1082 "Use the arrow keys to pan the image one pixel up, down,",
1083 "left, or right within the image window.",
1085 "The panning icon is withdrawn if the image becomes smaller",
1086 "than the dimensions of the X server screen.",
1091 "A small window appears showing the location of the cursor in",
1092 "the image window. You are now in paste mode. To exit",
1093 "immediately, press Dismiss. In paste mode, the Command",
1094 "widget has these options:",
1111 "Choose a composite operation from the Operators sub-menu of",
1112 "the Command widget. How each operator behaves is described",
1113 "below. Image window is the image currently displayed on",
1114 "your X server and image is the image obtained with the File",
1117 "Over The result is the union of the two image shapes,",
1118 " with image obscuring image window in the region of",
1121 "In The result is simply image cut by the shape of",
1122 " image window. None of the image data of image",
1123 " window is in the result.",
1125 "Out The resulting image is image with the shape of",
1126 " image window cut out.",
1128 "Atop The result is the same shape as image image window,",
1129 " with image obscuring image window where the image",
1130 " shapes overlap. Note this differs from over",
1131 " because the portion of image outside image window's",
1132 " shape does not appear in the result.",
1134 "Xor The result is the image data from both image and",
1135 " image window that is outside the overlap region.",
1136 " The overlap region is blank.",
1138 "Plus The result is just the sum of the image data.",
1139 " Output values are cropped to QuantumRange (no overflow).",
1140 " This operation is independent of the matte",
1143 "Minus The result of image - image window, with underflow",
1144 " cropped to zero.",
1146 "Add The result of image + image window, with overflow",
1147 " wrapping around (mod 256).",
1149 "Subtract The result of image - image window, with underflow",
1150 " wrapping around (mod 256). The add and subtract",
1151 " operators can be used to perform reversible",
1152 " transformations.",
1155 " The result of abs(image - image window). This",
1156 " useful for comparing two very similar images.",
1158 "Copy The resulting image is image window replaced with",
1159 " image. Here the matte information is ignored.",
1161 "CopyRed The red layer of the image window is replace with",
1162 " the red layer of the image. The other layers are",
1166 " The green layer of the image window is replace with",
1167 " the green layer of the image. The other layers are",
1170 "CopyBlue The blue layer of the image window is replace with",
1171 " the blue layer of the image. The other layers are",
1175 " The matte layer of the image window is replace with",
1176 " the matte layer of the image. The other layers are",
1179 "The image compositor requires a matte, or alpha channel in",
1180 "the image for some operations. This extra channel usually",
1181 "defines a mask which represents a sort of a cookie-cutter",
1182 "for the image. This the case when matte is opaque (full",
1183 "coverage) for pixels inside the shape, zero outside, and",
1184 "between 0 and QuantumRange on the boundary. If image does not",
1185 "have a matte channel, it is initialized with 0 for any pixel",
1186 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1188 "Note that matte information for image window is not retained",
1189 "for colormapped X server visuals (e.g. StaticColor,",
1190 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1191 "behavior may require a TrueColor or DirectColor visual or a",
1192 "Standard Colormap.",
1194 "Choosing a composite operator is optional. The default",
1195 "operator is replace. However, you must choose a location to",
1196 "paste your image and press button 1. Press and hold the",
1197 "button before releasing and an outline of the image will",
1198 "appear to help you identify your location.",
1200 "The actual colors of the pasted image is saved. However,",
1201 "the color that appears in image window may be different.",
1202 "For example, on a monochrome screen image window will appear",
1203 "black or white even though your pasted image may have",
1204 "many colors. If the image is saved to a file it is written",
1205 "with the correct colors. To assure the correct colors are",
1206 "saved in the final image, any PseudoClass image is promoted",
1207 "to DirectClass (see miff(5)). To force a PseudoClass image",
1208 "to remain PseudoClass, use -colors.",
1213 "In region of interest mode, the Command widget has these",
1219 "To define a region of interest, press button 1 and drag.",
1220 "The region of interest is defined by a highlighted rectangle",
1221 "that expands or contracts as it follows the pointer. Once",
1222 "you are satisfied with the region of interest, release the",
1223 "button. You are now in apply mode. In apply mode the",
1224 "Command widget has these options:",
1244 " Contrast Stretch",
1245 " Sigmoidal Contrast...",
1272 " Charcoal Drawing...",
1282 "You can make adjustments to the region of interest by moving",
1283 "the pointer to one of the rectangle corners, pressing a",
1284 "button, and dragging. Finally, choose an image processing",
1285 "technique from the Command widget. You can choose more than",
1286 "one image processing technique to apply to an area.",
1287 "Alternatively, you can move the region of interest before",
1288 "applying another image processing technique. To exit, press",
1292 *ImageRotateHelp[] =
1294 "In rotate mode, the Command widget has these options:",
1313 "Choose a background color from the Pixel Color sub-menu.",
1314 "Additional background colors can be specified with the color",
1315 "browser. You can change the menu colors by setting the X",
1316 "resources pen1 through pen9.",
1318 "If you choose the color browser and press Grab, you can",
1319 "select the background color by moving the pointer to the",
1320 "desired color on the screen and press any button.",
1322 "Choose a point in the image window and press this button and",
1323 "hold. Next, move the pointer to another location in the",
1324 "image. As you move a line connects the initial location and",
1325 "the pointer. When you release the button, the degree of",
1326 "image rotation is determined by the slope of the line you",
1327 "just drew. The slope is relative to the direction you",
1328 "choose from the Direction sub-menu of the Command widget.",
1330 "To cancel the image rotation, move the pointer back to the",
1331 "starting point of the line and release the button.",
1336 Enumeration declarations.
1355 VisualDirectoryCommand,
1363 OriginalSizeCommand,
1385 ContrastStretchCommand,
1386 SigmoidalContrastCommand,
1412 CharcoalDrawCommand,
1422 RegionofInterestCommand,
1428 ShowHistogramCommand,
1434 BrowseDocumentationCommand,
1436 SaveToUndoBufferCommand,
1443 AnnotateNameCommand,
1444 AnnotateFontColorCommand,
1445 AnnotateBackgroundColorCommand,
1446 AnnotateRotateCommand,
1447 AnnotateHelpCommand,
1448 AnnotateDismissCommand,
1451 ChopDirectionCommand,
1454 HorizontalChopCommand,
1455 VerticalChopCommand,
1456 ColorEditMethodCommand,
1457 ColorEditColorCommand,
1458 ColorEditBorderCommand,
1459 ColorEditFuzzCommand,
1460 ColorEditUndoCommand,
1461 ColorEditHelpCommand,
1462 ColorEditDismissCommand,
1463 CompositeOperatorsCommand,
1464 CompositeDissolveCommand,
1465 CompositeDisplaceCommand,
1466 CompositeHelpCommand,
1467 CompositeDismissCommand,
1472 RectifyDismissCommand,
1481 MatteEditBorderCommand,
1482 MatteEditFuzzCommand,
1483 MatteEditValueCommand,
1484 MatteEditUndoCommand,
1485 MatteEditHelpCommand,
1486 MatteEditDismissCommand,
1487 PasteOperatorsCommand,
1489 PasteDismissCommand,
1491 RotateDirectionCommand,
1493 RotateSharpenCommand,
1495 RotateDismissCommand,
1496 HorizontalRotateCommand,
1497 VerticalRotateCommand,
1508 #define BricksWidth 20
1509 #define BricksHeight 20
1510 #define DiagonalWidth 16
1511 #define DiagonalHeight 16
1512 #define HighlightWidth 8
1513 #define HighlightHeight 8
1514 #define OpaqueWidth 8
1515 #define OpaqueHeight 8
1516 #define ScalesWidth 16
1517 #define ScalesHeight 16
1518 #define ShadowWidth 8
1519 #define ShadowHeight 8
1520 #define VerticalWidth 16
1521 #define VerticalHeight 16
1522 #define WavyWidth 16
1523 #define WavyHeight 16
1526 Constant declaration.
1531 static const unsigned char
1534 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1535 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1536 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1537 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1538 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1542 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1543 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1544 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1548 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1549 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1550 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1554 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1555 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1556 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1560 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1561 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1562 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1566 Function prototypes.
1569 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1570 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1573 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1574 Image **,ExceptionInfo *),
1575 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1576 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1578 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1581 static MagickBooleanType
1582 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1584 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1586 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1588 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1590 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1592 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1594 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1595 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1597 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1599 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1600 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1601 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1603 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1604 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1605 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1608 XDrawPanRectangle(Display *,XWindows *),
1609 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1611 XMagnifyImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1612 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1613 XPanImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1614 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1615 const KeySym,ExceptionInfo *),
1616 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1617 XScreenEvent(Display *,XWindows *,XEvent *,ExceptionInfo *),
1618 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1625 % D i s p l a y I m a g e s %
1629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1631 % DisplayImages() displays an image sequence to any X window screen. It
1632 % returns a value other than 0 if successful. Check the exception member
1633 % of image to determine the reason for any failure.
1635 % The format of the DisplayImages method is:
1637 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1638 % Image *images,ExceptionInfo *exception)
1640 % A description of each parameter follows:
1642 % o image_info: the image info.
1644 % o image: the image.
1646 % o exception: return any errors or warnings in this structure.
1649 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1650 Image *images,ExceptionInfo *exception)
1673 assert(image_info != (const ImageInfo *) NULL);
1674 assert(image_info->signature == MagickSignature);
1675 assert(images != (Image *) NULL);
1676 assert(images->signature == MagickSignature);
1677 if (images->debug != MagickFalse)
1678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1679 display=XOpenDisplay(image_info->server_name);
1680 if (display == (Display *) NULL)
1682 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1683 "UnableToOpenXServer","'%s'",XDisplayName(image_info->server_name));
1684 return(MagickFalse);
1686 if (exception->severity != UndefinedException)
1687 CatchException(exception);
1688 (void) XSetErrorHandler(XError);
1689 resource_database=XGetResourceDatabase(display,GetClientName());
1690 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1691 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1692 if (image_info->page != (char *) NULL)
1693 resource_info.image_geometry=AcquireString(image_info->page);
1694 resource_info.immutable=MagickTrue;
1695 argv[0]=AcquireString(GetClientName());
1697 for (i=0; (state & ExitState) == 0; i++)
1699 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1701 image=GetImageFromList(images,i % GetImageListLength(images));
1702 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1704 (void) SetErrorHandler((ErrorHandler) NULL);
1705 (void) SetWarningHandler((WarningHandler) NULL);
1706 argv[0]=DestroyString(argv[0]);
1707 (void) XCloseDisplay(display);
1708 XDestroyResourceInfo(&resource_info);
1709 if (exception->severity != UndefinedException)
1710 return(MagickFalse);
1715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1719 % R e m o t e D i s p l a y C o m m a n d %
1723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 % RemoteDisplayCommand() encourages a remote display program to display the
1726 % specified image filename.
1728 % The format of the RemoteDisplayCommand method is:
1730 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1731 % const char *window,const char *filename,ExceptionInfo *exception)
1733 % A description of each parameter follows:
1735 % o image_info: the image info.
1737 % o window: Specifies the name or id of an X window.
1739 % o filename: the name of the image filename to display.
1741 % o exception: return any errors or warnings in this structure.
1744 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1745 const char *window,const char *filename,ExceptionInfo *exception)
1753 assert(image_info != (const ImageInfo *) NULL);
1754 assert(image_info->signature == MagickSignature);
1755 assert(filename != (char *) NULL);
1756 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1757 display=XOpenDisplay(image_info->server_name);
1758 if (display == (Display *) NULL)
1760 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1761 "UnableToOpenXServer","'%s'",XDisplayName(image_info->server_name));
1762 return(MagickFalse);
1764 (void) XSetErrorHandler(XError);
1765 status=XRemoteCommand(display,window,filename);
1766 (void) XCloseDisplay(display);
1767 return(status != 0 ? MagickTrue : MagickFalse);
1771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775 + X A n n o t a t e E d i t I m a g e %
1779 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781 % XAnnotateEditImage() annotates the image with text.
1783 % The format of the XAnnotateEditImage method is:
1785 % MagickBooleanType XAnnotateEditImage(Display *display,
1786 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1787 % ExceptionInfo *exception)
1789 % A description of each parameter follows:
1791 % o display: Specifies a connection to an X server; returned from
1794 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1796 % o windows: Specifies a pointer to a XWindows structure.
1798 % o image: the image; returned from ReadImage.
1802 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
1809 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
1816 static MagickBooleanType XAnnotateEditImage(Display *display,
1817 XResourceInfo *resource_info,XWindows *windows,Image *image,
1818 ExceptionInfo *exception)
1838 static const ModeType
1839 AnnotateCommands[] =
1841 AnnotateNameCommand,
1842 AnnotateFontColorCommand,
1843 AnnotateBackgroundColorCommand,
1844 AnnotateRotateCommand,
1845 AnnotateHelpCommand,
1846 AnnotateDismissCommand
1854 static MagickBooleanType
1855 transparent_box = MagickTrue,
1856 transparent_pen = MagickFalse;
1858 static MagickRealType
1862 box_id = MaxNumberPens-2,
1867 command[MaxTextExtent],
1868 text[MaxTextExtent];
1871 *ColorMenu[MaxNumberPens+1];
1919 (void) CloneString(&windows->command.name,"Annotate");
1920 windows->command.data=4;
1921 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1922 (void) XMapRaised(display,windows->command.id);
1923 XClientMessage(display,windows->image.id,windows->im_protocols,
1924 windows->im_update_widget,CurrentTime);
1926 Track pointer until button 1 is pressed.
1928 XQueryPosition(display,windows->image.id,&x,&y);
1929 (void) XSelectInput(display,windows->image.id,
1930 windows->image.attributes.event_mask | PointerMotionMask);
1931 cursor=XCreateFontCursor(display,XC_left_side);
1932 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1936 if (windows->info.mapped != MagickFalse)
1939 Display pointer position.
1941 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
1942 x+windows->image.x,y+windows->image.y);
1943 XInfoWidget(display,windows,text);
1946 Wait for next event.
1948 XScreenEvent(display,windows,&event,exception);
1949 if (event.xany.window == windows->command.id)
1952 Select a command from the Command widget.
1954 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1955 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1958 switch (AnnotateCommands[id])
1960 case AnnotateNameCommand:
1963 *FontMenu[MaxNumberFonts];
1969 Initialize menu selections.
1971 for (i=0; i < MaxNumberFonts; i++)
1972 FontMenu[i]=resource_info->font_name[i];
1973 FontMenu[MaxNumberFonts-2]="Browser...";
1974 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1976 Select a font name from the pop-up menu.
1978 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1979 (const char **) FontMenu,command);
1980 if (font_number < 0)
1982 if (font_number == (MaxNumberFonts-2))
1985 font_name[MaxTextExtent] = "fixed";
1988 Select a font name from a browser.
1990 resource_info->font_name[font_number]=font_name;
1991 XFontBrowserWidget(display,windows,"Select",font_name);
1992 if (*font_name == '\0')
1996 Initialize font info.
1998 font_info=XLoadQueryFont(display,resource_info->font_name[
2000 if (font_info == (XFontStruct *) NULL)
2002 XNoticeWidget(display,windows,"Unable to load font:",
2003 resource_info->font_name[font_number]);
2006 font_id=(unsigned int) font_number;
2007 (void) XFreeFont(display,font_info);
2010 case AnnotateFontColorCommand:
2013 Initialize menu selections.
2015 for (i=0; i < (int) (MaxNumberPens-2); i++)
2016 ColorMenu[i]=resource_info->pen_colors[i];
2017 ColorMenu[MaxNumberPens-2]="transparent";
2018 ColorMenu[MaxNumberPens-1]="Browser...";
2019 ColorMenu[MaxNumberPens]=(const char *) NULL;
2021 Select a pen color from the pop-up menu.
2023 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2024 (const char **) ColorMenu,command);
2027 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2029 if (transparent_pen != MagickFalse)
2031 if (pen_number == (MaxNumberPens-1))
2034 color_name[MaxTextExtent] = "gray";
2037 Select a pen color from a dialog.
2039 resource_info->pen_colors[pen_number]=color_name;
2040 XColorBrowserWidget(display,windows,"Select",color_name);
2041 if (*color_name == '\0')
2047 (void) XParseColor(display,windows->map_info->colormap,
2048 resource_info->pen_colors[pen_number],&color);
2049 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2050 (unsigned int) MaxColors,&color);
2051 windows->pixel_info->pen_colors[pen_number]=color;
2052 pen_id=(unsigned int) pen_number;
2055 case AnnotateBackgroundColorCommand:
2058 Initialize menu selections.
2060 for (i=0; i < (int) (MaxNumberPens-2); i++)
2061 ColorMenu[i]=resource_info->pen_colors[i];
2062 ColorMenu[MaxNumberPens-2]="transparent";
2063 ColorMenu[MaxNumberPens-1]="Browser...";
2064 ColorMenu[MaxNumberPens]=(const char *) NULL;
2066 Select a pen color from the pop-up menu.
2068 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2069 (const char **) ColorMenu,command);
2072 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2074 if (transparent_box != MagickFalse)
2076 if (pen_number == (MaxNumberPens-1))
2079 color_name[MaxTextExtent] = "gray";
2082 Select a pen color from a dialog.
2084 resource_info->pen_colors[pen_number]=color_name;
2085 XColorBrowserWidget(display,windows,"Select",color_name);
2086 if (*color_name == '\0')
2092 (void) XParseColor(display,windows->map_info->colormap,
2093 resource_info->pen_colors[pen_number],&color);
2094 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2095 (unsigned int) MaxColors,&color);
2096 windows->pixel_info->pen_colors[pen_number]=color;
2097 box_id=(unsigned int) pen_number;
2100 case AnnotateRotateCommand:
2106 angle[MaxTextExtent] = "30.0";
2124 Select a command from the pop-up menu.
2126 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2132 degrees=StringToDouble(RotateMenu[entry],(char **) NULL);
2135 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2139 degrees=StringToDouble(angle,(char **) NULL);
2142 case AnnotateHelpCommand:
2144 XTextViewWidget(display,resource_info,windows,MagickFalse,
2145 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2148 case AnnotateDismissCommand:
2166 if (event.xbutton.button != Button1)
2168 if (event.xbutton.window != windows->image.id)
2171 Change to text entering mode.
2184 if (event.xkey.window != windows->image.id)
2187 Respond to a user key press.
2189 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2190 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2191 switch ((int) key_symbol)
2206 XTextViewWidget(display,resource_info,windows,MagickFalse,
2207 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2212 (void) XBell(display,0);
2221 Map and unmap Info widget as cursor crosses its boundaries.
2225 if (windows->info.mapped != MagickFalse)
2227 if ((x < (int) (windows->info.x+windows->info.width)) &&
2228 (y < (int) (windows->info.y+windows->info.height)))
2229 (void) XWithdrawWindow(display,windows->info.id,
2230 windows->info.screen);
2233 if ((x > (int) (windows->info.x+windows->info.width)) ||
2234 (y > (int) (windows->info.y+windows->info.height)))
2235 (void) XMapWindow(display,windows->info.id);
2241 } while ((state & ExitState) == 0);
2242 (void) XSelectInput(display,windows->image.id,
2243 windows->image.attributes.event_mask);
2244 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2245 if ((state & EscapeState) != 0)
2248 Set font info and check boundary conditions.
2250 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2251 if (font_info == (XFontStruct *) NULL)
2253 XNoticeWidget(display,windows,"Unable to load font:",
2254 resource_info->font_name[font_id]);
2255 font_info=windows->font_info;
2257 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2258 x=(int) windows->image.width-font_info->max_bounds.width;
2259 if (y < (int) (font_info->ascent+font_info->descent))
2260 y=(int) font_info->ascent+font_info->descent;
2261 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2262 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2263 return(MagickFalse);
2265 Initialize annotate structure.
2267 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2268 if (annotate_info == (XAnnotateInfo *) NULL)
2269 return(MagickFalse);
2270 XGetAnnotateInfo(annotate_info);
2273 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
2274 annotate_info->stencil=OpaqueStencil;
2276 if (transparent_box == MagickFalse)
2277 annotate_info->stencil=BackgroundStencil;
2279 annotate_info->stencil=ForegroundStencil;
2280 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2281 annotate_info->degrees=degrees;
2282 annotate_info->font_info=font_info;
2283 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2284 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2285 sizeof(*annotate_info->text));
2286 if (annotate_info->text == (char *) NULL)
2287 return(MagickFalse);
2289 Create cursor and set graphic context.
2291 cursor=XCreateFontCursor(display,XC_pencil);
2292 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2293 annotate_context=windows->image.annotate_context;
2294 (void) XSetFont(display,annotate_context,font_info->fid);
2295 (void) XSetBackground(display,annotate_context,
2296 windows->pixel_info->pen_colors[box_id].pixel);
2297 (void) XSetForeground(display,annotate_context,
2298 windows->pixel_info->pen_colors[pen_id].pixel);
2300 Begin annotating the image with text.
2302 (void) CloneString(&windows->command.name,"Text");
2303 windows->command.data=0;
2304 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2306 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2307 text_event.xexpose.width=(int) font_info->max_bounds.width;
2308 text_event.xexpose.height=font_info->max_bounds.ascent+
2309 font_info->max_bounds.descent;
2310 p=annotate_info->text;
2314 Display text cursor.
2317 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2319 Wait for next event.
2321 XScreenEvent(display,windows,&event,exception);
2322 if (event.xany.window == windows->command.id)
2325 Select a command from the Command widget.
2327 (void) XSetBackground(display,annotate_context,
2328 windows->pixel_info->background_color.pixel);
2329 (void) XSetForeground(display,annotate_context,
2330 windows->pixel_info->foreground_color.pixel);
2331 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2332 (void) XSetBackground(display,annotate_context,
2333 windows->pixel_info->pen_colors[box_id].pixel);
2334 (void) XSetForeground(display,annotate_context,
2335 windows->pixel_info->pen_colors[pen_id].pixel);
2338 switch (TextCommands[id])
2340 case TextHelpCommand:
2342 XTextViewWidget(display,resource_info,windows,MagickFalse,
2343 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2344 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2347 case TextApplyCommand:
2350 Finished annotating.
2352 annotate_info->width=(unsigned int) XTextWidth(font_info,
2353 annotate_info->text,(int) strlen(annotate_info->text));
2354 XRefreshWindow(display,&windows->image,&text_event);
2366 text_event.xexpose.x=x;
2367 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2368 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2369 (unsigned int) text_event.xexpose.width,(unsigned int)
2370 text_event.xexpose.height,MagickFalse);
2371 XRefreshWindow(display,&windows->image,&text_event);
2376 if (event.xbutton.window != windows->image.id)
2378 if (event.xbutton.button == Button2)
2381 Request primary selection.
2383 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2384 windows->image.id,CurrentTime);
2391 if (event.xexpose.count == 0)
2397 Refresh Image window.
2399 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2400 text_info=annotate_info;
2401 while (text_info != (XAnnotateInfo *) NULL)
2403 if (annotate_info->stencil == ForegroundStencil)
2404 (void) XDrawString(display,windows->image.id,annotate_context,
2405 text_info->x,text_info->y,text_info->text,
2406 (int) strlen(text_info->text));
2408 (void) XDrawImageString(display,windows->image.id,
2409 annotate_context,text_info->x,text_info->y,text_info->text,
2410 (int) strlen(text_info->text));
2411 text_info=text_info->previous;
2413 (void) XDrawString(display,windows->image.id,annotate_context,
2423 if (event.xkey.window != windows->image.id)
2426 Respond to a user key press.
2428 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2429 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2430 *(command+length)='\0';
2431 if (((event.xkey.state & ControlMask) != 0) ||
2432 ((event.xkey.state & Mod1Mask) != 0))
2433 state|=ModifierState;
2434 if ((state & ModifierState) != 0)
2435 switch ((int) key_symbol)
2440 key_symbol=DeleteCommand;
2446 switch ((int) key_symbol)
2451 Erase one character.
2453 if (p == annotate_info->text)
2455 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2460 Go to end of the previous line of text.
2462 annotate_info=annotate_info->previous;
2463 p=annotate_info->text;
2464 x=annotate_info->x+annotate_info->width;
2466 if (annotate_info->width != 0)
2467 p+=strlen(annotate_info->text);
2472 x-=XTextWidth(font_info,p,1);
2473 text_event.xexpose.x=x;
2474 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2475 XRefreshWindow(display,&windows->image,&text_event);
2478 case XK_bracketleft:
2480 key_symbol=XK_Escape;
2486 Erase the entire line of text.
2488 while (p != annotate_info->text)
2491 x-=XTextWidth(font_info,p,1);
2492 text_event.xexpose.x=x;
2493 XRefreshWindow(display,&windows->image,&text_event);
2501 Finished annotating.
2503 annotate_info->width=(unsigned int) XTextWidth(font_info,
2504 annotate_info->text,(int) strlen(annotate_info->text));
2505 XRefreshWindow(display,&windows->image,&text_event);
2512 Draw a single character on the Image window.
2514 if ((state & ModifierState) != 0)
2516 if (*command == '\0')
2519 if (annotate_info->stencil == ForegroundStencil)
2520 (void) XDrawString(display,windows->image.id,annotate_context,
2523 (void) XDrawImageString(display,windows->image.id,
2524 annotate_context,x,y,p,1);
2525 x+=XTextWidth(font_info,p,1);
2527 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2534 Advance to the next line of text.
2537 annotate_info->width=(unsigned int) XTextWidth(font_info,
2538 annotate_info->text,(int) strlen(annotate_info->text));
2539 if (annotate_info->next != (XAnnotateInfo *) NULL)
2542 Line of text already exists.
2544 annotate_info=annotate_info->next;
2547 p=annotate_info->text;
2550 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2551 sizeof(*annotate_info->next));
2552 if (annotate_info->next == (XAnnotateInfo *) NULL)
2553 return(MagickFalse);
2554 *annotate_info->next=(*annotate_info);
2555 annotate_info->next->previous=annotate_info;
2556 annotate_info=annotate_info->next;
2557 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2558 windows->image.width/MagickMax((ssize_t)
2559 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2560 if (annotate_info->text == (char *) NULL)
2561 return(MagickFalse);
2562 annotate_info->y+=annotate_info->height;
2563 if (annotate_info->y > (int) windows->image.height)
2564 annotate_info->y=(int) annotate_info->height;
2565 annotate_info->next=(XAnnotateInfo *) NULL;
2568 p=annotate_info->text;
2577 Respond to a user key release.
2579 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2580 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2581 state&=(~ModifierState);
2584 case SelectionNotify:
2600 Obtain response from primary selection.
2602 if (event.xselection.property == (Atom) None)
2604 status=XGetWindowProperty(display,event.xselection.requestor,
2605 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2606 &type,&format,&length,&after,&data);
2607 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2611 Annotate Image window with primary selection.
2613 for (i=0; i < (ssize_t) length; i++)
2615 if ((char) data[i] != '\n')
2618 Draw a single character on the Image window.
2621 (void) XDrawString(display,windows->image.id,annotate_context,
2623 x+=XTextWidth(font_info,p,1);
2625 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2629 Advance to the next line of text.
2632 annotate_info->width=(unsigned int) XTextWidth(font_info,
2633 annotate_info->text,(int) strlen(annotate_info->text));
2634 if (annotate_info->next != (XAnnotateInfo *) NULL)
2637 Line of text already exists.
2639 annotate_info=annotate_info->next;
2642 p=annotate_info->text;
2645 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2646 sizeof(*annotate_info->next));
2647 if (annotate_info->next == (XAnnotateInfo *) NULL)
2648 return(MagickFalse);
2649 *annotate_info->next=(*annotate_info);
2650 annotate_info->next->previous=annotate_info;
2651 annotate_info=annotate_info->next;
2652 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2653 windows->image.width/MagickMax((ssize_t)
2654 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2655 if (annotate_info->text == (char *) NULL)
2656 return(MagickFalse);
2657 annotate_info->y+=annotate_info->height;
2658 if (annotate_info->y > (int) windows->image.height)
2659 annotate_info->y=(int) annotate_info->height;
2660 annotate_info->next=(XAnnotateInfo *) NULL;
2663 p=annotate_info->text;
2665 (void) XFree((void *) data);
2671 } while ((state & ExitState) == 0);
2672 (void) XFreeCursor(display,cursor);
2674 Annotation is relative to image configuration.
2676 width=(unsigned int) image->columns;
2677 height=(unsigned int) image->rows;
2680 if (windows->image.crop_geometry != (char *) NULL)
2681 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2683 Initialize annotated image.
2685 XSetCursorState(display,windows,MagickTrue);
2686 XCheckRefreshWindows(display,windows);
2687 while (annotate_info != (XAnnotateInfo *) NULL)
2689 if (annotate_info->width == 0)
2692 No text on this line-- go to the next line of text.
2694 previous_info=annotate_info->previous;
2695 annotate_info->text=(char *)
2696 RelinquishMagickMemory(annotate_info->text);
2697 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2698 annotate_info=previous_info;
2702 Determine pixel index for box and pen color.
2704 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2705 if (windows->pixel_info->colors != 0)
2706 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2707 if (windows->pixel_info->pixels[i] ==
2708 windows->pixel_info->pen_colors[box_id].pixel)
2710 windows->pixel_info->box_index=(unsigned short) i;
2713 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2714 if (windows->pixel_info->colors != 0)
2715 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2716 if (windows->pixel_info->pixels[i] ==
2717 windows->pixel_info->pen_colors[pen_id].pixel)
2719 windows->pixel_info->pen_index=(unsigned short) i;
2723 Define the annotate geometry string.
2725 annotate_info->x=(int)
2726 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2727 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2728 windows->image.y)/windows->image.ximage->height;
2729 (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent,
2730 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2731 height*annotate_info->height/windows->image.ximage->height,
2732 annotate_info->x+x,annotate_info->y+y);
2734 Annotate image with text.
2736 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image,
2739 return(MagickFalse);
2743 previous_info=annotate_info->previous;
2744 annotate_info->text=DestroyString(annotate_info->text);
2745 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2746 annotate_info=previous_info;
2748 (void) XSetForeground(display,annotate_context,
2749 windows->pixel_info->foreground_color.pixel);
2750 (void) XSetBackground(display,annotate_context,
2751 windows->pixel_info->background_color.pixel);
2752 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2753 XSetCursorState(display,windows,MagickFalse);
2754 (void) XFreeFont(display,font_info);
2756 Update image configuration.
2758 XConfigureImageColormap(display,resource_info,windows,image,exception);
2759 (void) XConfigureImage(display,resource_info,windows,image,exception);
2764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2768 + X B a c k g r o u n d I m a g e %
2772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2774 % XBackgroundImage() displays the image in the background of a window.
2776 % The format of the XBackgroundImage method is:
2778 % MagickBooleanType XBackgroundImage(Display *display,
2779 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2780 % ExceptionInfo *exception)
2782 % A description of each parameter follows:
2784 % o display: Specifies a connection to an X server; returned from
2787 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2789 % o windows: Specifies a pointer to a XWindows structure.
2791 % o image: the image.
2793 % o exception: return any errors or warnings in this structure.
2796 static MagickBooleanType XBackgroundImage(Display *display,
2797 XResourceInfo *resource_info,XWindows *windows,Image **image,
2798 ExceptionInfo *exception)
2800 #define BackgroundImageTag "Background/Image"
2806 window_id[MaxTextExtent] = "root";
2809 background_resources;
2812 Put image in background.
2814 status=XDialogWidget(display,windows,"Background",
2815 "Enter window id (id 0x00 selects window with pointer):",window_id);
2816 if (*window_id == '\0')
2817 return(MagickFalse);
2818 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2820 XInfoWidget(display,windows,BackgroundImageTag);
2821 XSetCursorState(display,windows,MagickTrue);
2822 XCheckRefreshWindows(display,windows);
2823 background_resources=(*resource_info);
2824 background_resources.window_id=window_id;
2825 background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse;
2826 status=XDisplayBackgroundImage(display,&background_resources,*image,
2828 if (status != MagickFalse)
2829 XClientMessage(display,windows->image.id,windows->im_protocols,
2830 windows->im_retain_colors,CurrentTime);
2831 XSetCursorState(display,windows,MagickFalse);
2832 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2842 + X C h o p I m a g e %
2846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2848 % XChopImage() chops the X image.
2850 % The format of the XChopImage method is:
2852 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2853 % XWindows *windows,Image **image,ExceptionInfo *exception)
2855 % A description of each parameter follows:
2857 % o display: Specifies a connection to an X server; returned from
2860 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2862 % o windows: Specifies a pointer to a XWindows structure.
2864 % o image: the image.
2866 % o exception: return any errors or warnings in this structure.
2869 static MagickBooleanType XChopImage(Display *display,
2870 XResourceInfo *resource_info,XWindows *windows,Image **image,
2871 ExceptionInfo *exception)
2883 direction = HorizontalChopCommand;
2885 static const ModeType
2888 ChopDirectionCommand,
2892 DirectionCommands[] =
2894 HorizontalChopCommand,
2899 text[MaxTextExtent];
2932 (void) CloneString(&windows->command.name,"Chop");
2933 windows->command.data=1;
2934 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2935 (void) XMapRaised(display,windows->command.id);
2936 XClientMessage(display,windows->image.id,windows->im_protocols,
2937 windows->im_update_widget,CurrentTime);
2939 Track pointer until button 1 is pressed.
2941 XQueryPosition(display,windows->image.id,&x,&y);
2942 (void) XSelectInput(display,windows->image.id,
2943 windows->image.attributes.event_mask | PointerMotionMask);
2947 if (windows->info.mapped != MagickFalse)
2950 Display pointer position.
2952 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
2953 x+windows->image.x,y+windows->image.y);
2954 XInfoWidget(display,windows,text);
2957 Wait for next event.
2959 XScreenEvent(display,windows,&event,exception);
2960 if (event.xany.window == windows->command.id)
2963 Select a command from the Command widget.
2965 id=XCommandWidget(display,windows,ChopMenu,&event);
2968 switch (ChopCommands[id])
2970 case ChopDirectionCommand:
2973 command[MaxTextExtent];
2984 Select a command from the pop-up menu.
2986 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2988 direction=DirectionCommands[id];
2991 case ChopHelpCommand:
2993 XTextViewWidget(display,resource_info,windows,MagickFalse,
2994 "Help Viewer - Image Chop",ImageChopHelp);
2997 case ChopDismissCommand:
3015 if (event.xbutton.button != Button1)
3017 if (event.xbutton.window != windows->image.id)
3020 User has committed to start point of chopping line.
3022 segment_info.x1=(short int) event.xbutton.x;
3023 segment_info.x2=(short int) event.xbutton.x;
3024 segment_info.y1=(short int) event.xbutton.y;
3025 segment_info.y2=(short int) event.xbutton.y;
3036 command[MaxTextExtent];
3041 if (event.xkey.window != windows->image.id)
3044 Respond to a user key press.
3046 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3047 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3048 switch ((int) key_symbol)
3063 (void) XSetFunction(display,windows->image.highlight_context,
3065 XTextViewWidget(display,resource_info,windows,MagickFalse,
3066 "Help Viewer - Image Chop",ImageChopHelp);
3067 (void) XSetFunction(display,windows->image.highlight_context,
3073 (void) XBell(display,0);
3082 Map and unmap Info widget as text cursor crosses its boundaries.
3086 if (windows->info.mapped != MagickFalse)
3088 if ((x < (int) (windows->info.x+windows->info.width)) &&
3089 (y < (int) (windows->info.y+windows->info.height)))
3090 (void) XWithdrawWindow(display,windows->info.id,
3091 windows->info.screen);
3094 if ((x > (int) (windows->info.x+windows->info.width)) ||
3095 (y > (int) (windows->info.y+windows->info.height)))
3096 (void) XMapWindow(display,windows->info.id);
3099 } while ((state & ExitState) == 0);
3100 (void) XSelectInput(display,windows->image.id,
3101 windows->image.attributes.event_mask);
3102 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3103 if ((state & EscapeState) != 0)
3106 Draw line as pointer moves until the mouse button is released.
3113 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3120 Display info and draw chopping line.
3122 if (windows->info.mapped == MagickFalse)
3123 (void) XMapWindow(display,windows->info.id);
3124 (void) FormatLocaleString(text,MaxTextExtent,
3125 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3126 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3127 XInfoWidget(display,windows,text);
3128 XHighlightLine(display,windows->image.id,
3129 windows->image.highlight_context,&segment_info);
3132 if (windows->info.mapped != MagickFalse)
3133 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3135 Wait for next event.
3137 XScreenEvent(display,windows,&event,exception);
3139 XHighlightLine(display,windows->image.id,
3140 windows->image.highlight_context,&segment_info);
3145 segment_info.x2=(short int) event.xmotion.x;
3146 segment_info.y2=(short int) event.xmotion.y;
3152 User has committed to chopping line.
3154 segment_info.x2=(short int) event.xbutton.x;
3155 segment_info.y2=(short int) event.xbutton.y;
3163 segment_info.x2=(short int) event.xmotion.x;
3164 segment_info.y2=(short int) event.xmotion.y;
3170 Check boundary conditions.
3172 if (segment_info.x2 < 0)
3175 if (segment_info.x2 > windows->image.ximage->width)
3176 segment_info.x2=windows->image.ximage->width;
3177 if (segment_info.y2 < 0)
3180 if (segment_info.y2 > windows->image.ximage->height)
3181 segment_info.y2=windows->image.ximage->height;
3182 distance=(unsigned int)
3183 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3184 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3186 Compute chopping geometry.
3188 if (direction == HorizontalChopCommand)
3190 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3191 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3194 if (segment_info.x1 > (int) segment_info.x2)
3196 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3197 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3203 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3205 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3206 if (segment_info.y1 > segment_info.y2)
3208 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3209 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3212 } while ((state & ExitState) == 0);
3213 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3214 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3218 Image chopping is relative to image configuration.
3220 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3222 XSetCursorState(display,windows,MagickTrue);
3223 XCheckRefreshWindows(display,windows);
3224 windows->image.window_changes.width=windows->image.ximage->width-
3225 (unsigned int) chop_info.width;
3226 windows->image.window_changes.height=windows->image.ximage->height-
3227 (unsigned int) chop_info.height;
3228 width=(unsigned int) (*image)->columns;
3229 height=(unsigned int) (*image)->rows;
3232 if (windows->image.crop_geometry != (char *) NULL)
3233 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3234 scale_factor=(MagickRealType) width/windows->image.ximage->width;
3236 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3237 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3238 scale_factor=(MagickRealType) height/windows->image.ximage->height;
3240 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3241 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3245 chop_image=ChopImage(*image,&chop_info,exception);
3246 XSetCursorState(display,windows,MagickFalse);
3247 if (chop_image == (Image *) NULL)
3248 return(MagickFalse);
3249 *image=DestroyImage(*image);
3252 Update image configuration.
3254 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3255 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3264 + X C o l o r E d i t I m a g e %
3268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3270 % XColorEditImage() allows the user to interactively change the color of one
3271 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3273 % The format of the XColorEditImage method is:
3275 % MagickBooleanType XColorEditImage(Display *display,
3276 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3277 % ExceptionInfo *exception)
3279 % A description of each parameter follows:
3281 % o display: Specifies a connection to an X server; returned from
3284 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3286 % o windows: Specifies a pointer to a XWindows structure.
3288 % o image: the image; returned from ReadImage.
3290 % o exception: return any errors or warnings in this structure.
3293 static MagickBooleanType XColorEditImage(Display *display,
3294 XResourceInfo *resource_info,XWindows *windows,Image **image,
3295 ExceptionInfo *exception)
3310 static const ModeType
3311 ColorEditCommands[] =
3313 ColorEditMethodCommand,
3314 ColorEditColorCommand,
3315 ColorEditBorderCommand,
3316 ColorEditFuzzCommand,
3317 ColorEditUndoCommand,
3318 ColorEditHelpCommand,
3319 ColorEditDismissCommand
3323 method = PointMethod;
3329 border_color = { 0, 0, 0, 0, 0, 0 };
3332 command[MaxTextExtent],
3333 text[MaxTextExtent];
3368 (void) CloneString(&windows->command.name,"Color Edit");
3369 windows->command.data=4;
3370 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3371 (void) XMapRaised(display,windows->command.id);
3372 XClientMessage(display,windows->image.id,windows->im_protocols,
3373 windows->im_update_widget,CurrentTime);
3377 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3378 resource_info->background_color,resource_info->foreground_color);
3379 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3381 Track pointer until button 1 is pressed.
3383 XQueryPosition(display,windows->image.id,&x,&y);
3384 (void) XSelectInput(display,windows->image.id,
3385 windows->image.attributes.event_mask | PointerMotionMask);
3389 if (windows->info.mapped != MagickFalse)
3392 Display pointer position.
3394 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
3395 x+windows->image.x,y+windows->image.y);
3396 XInfoWidget(display,windows,text);
3399 Wait for next event.
3401 XScreenEvent(display,windows,&event,exception);
3402 if (event.xany.window == windows->command.id)
3405 Select a command from the Command widget.
3407 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3410 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3413 switch (ColorEditCommands[id])
3415 case ColorEditMethodCommand:
3421 Select a method from the pop-up menu.
3423 methods=(char **) GetCommandOptions(MagickMethodOptions);
3424 if (methods == (char **) NULL)
3426 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3427 (const char **) methods,command);
3429 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3430 MagickFalse,methods[entry]);
3431 methods=DestroyStringList(methods);
3434 case ColorEditColorCommand:
3437 *ColorMenu[MaxNumberPens];
3443 Initialize menu selections.
3445 for (i=0; i < (int) (MaxNumberPens-2); i++)
3446 ColorMenu[i]=resource_info->pen_colors[i];
3447 ColorMenu[MaxNumberPens-2]="Browser...";
3448 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3450 Select a pen color from the pop-up menu.
3452 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3453 (const char **) ColorMenu,command);
3456 if (pen_number == (MaxNumberPens-2))
3459 color_name[MaxTextExtent] = "gray";
3462 Select a pen color from a dialog.
3464 resource_info->pen_colors[pen_number]=color_name;
3465 XColorBrowserWidget(display,windows,"Select",color_name);
3466 if (*color_name == '\0')
3472 (void) XParseColor(display,windows->map_info->colormap,
3473 resource_info->pen_colors[pen_number],&color);
3474 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3475 (unsigned int) MaxColors,&color);
3476 windows->pixel_info->pen_colors[pen_number]=color;
3477 pen_id=(unsigned int) pen_number;
3480 case ColorEditBorderCommand:
3483 *ColorMenu[MaxNumberPens];
3489 Initialize menu selections.
3491 for (i=0; i < (int) (MaxNumberPens-2); i++)
3492 ColorMenu[i]=resource_info->pen_colors[i];
3493 ColorMenu[MaxNumberPens-2]="Browser...";
3494 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3496 Select a pen color from the pop-up menu.
3498 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3499 (const char **) ColorMenu,command);
3502 if (pen_number == (MaxNumberPens-2))
3505 color_name[MaxTextExtent] = "gray";
3508 Select a pen color from a dialog.
3510 resource_info->pen_colors[pen_number]=color_name;
3511 XColorBrowserWidget(display,windows,"Select",color_name);
3512 if (*color_name == '\0')
3518 (void) XParseColor(display,windows->map_info->colormap,
3519 resource_info->pen_colors[pen_number],&border_color);
3522 case ColorEditFuzzCommand:
3525 fuzz[MaxTextExtent];
3540 Select a command from the pop-up menu.
3542 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3548 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
3552 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3553 (void) XDialogWidget(display,windows,"Ok",
3554 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3557 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3558 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
3562 case ColorEditUndoCommand:
3564 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3568 case ColorEditHelpCommand:
3571 XTextViewWidget(display,resource_info,windows,MagickFalse,
3572 "Help Viewer - Image Annotation",ImageColorEditHelp);
3575 case ColorEditDismissCommand:
3585 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3592 if (event.xbutton.button != Button1)
3594 if ((event.xbutton.window != windows->image.id) &&
3595 (event.xbutton.window != windows->magnify.id))
3602 (void) XMagickCommand(display,resource_info,windows,
3603 SaveToUndoBufferCommand,image,exception);
3604 state|=UpdateConfigurationState;
3609 if (event.xbutton.button != Button1)
3611 if ((event.xbutton.window != windows->image.id) &&
3612 (event.xbutton.window != windows->magnify.id))
3615 Update colormap information.
3619 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3620 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3621 XInfoWidget(display,windows,text);
3622 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3623 state&=(~UpdateConfigurationState);
3633 if (event.xkey.window == windows->magnify.id)
3638 window=windows->magnify.id;
3639 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3641 if (event.xkey.window != windows->image.id)
3644 Respond to a user key press.
3646 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3647 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3648 switch ((int) key_symbol)
3662 XTextViewWidget(display,resource_info,windows,MagickFalse,
3663 "Help Viewer - Image Annotation",ImageColorEditHelp);
3668 (void) XBell(display,0);
3677 Map and unmap Info widget as cursor crosses its boundaries.
3681 if (windows->info.mapped != MagickFalse)
3683 if ((x < (int) (windows->info.x+windows->info.width)) &&
3684 (y < (int) (windows->info.y+windows->info.height)))
3685 (void) XWithdrawWindow(display,windows->info.id,
3686 windows->info.screen);
3689 if ((x > (int) (windows->info.x+windows->info.width)) ||
3690 (y > (int) (windows->info.y+windows->info.height)))
3691 (void) XMapWindow(display,windows->info.id);
3697 if (event.xany.window == windows->magnify.id)
3699 x=windows->magnify.x-windows->image.x;
3700 y=windows->magnify.y-windows->image.y;
3704 if ((state & UpdateConfigurationState) != 0)
3714 Pixel edit is relative to image configuration.
3716 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3718 color=windows->pixel_info->pen_colors[pen_id];
3719 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3720 width=(unsigned int) (*image)->columns;
3721 height=(unsigned int) (*image)->rows;
3724 if (windows->image.crop_geometry != (char *) NULL)
3725 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3728 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3730 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3731 if ((x_offset < 0) || (y_offset < 0))
3733 if ((x_offset >= (int) (*image)->columns) ||
3734 (y_offset >= (int) (*image)->rows))
3736 image_view=AcquireAuthenticCacheView(*image,exception);
3743 Update color information using point algorithm.
3745 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3746 return(MagickFalse);
3747 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3748 (ssize_t) y_offset,1,1,exception);
3749 if (q == (Quantum *) NULL)
3751 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3752 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3753 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3754 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3764 Update color information using replace algorithm.
3766 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
3767 x_offset,(ssize_t) y_offset,&target,exception);
3768 if ((*image)->storage_class == DirectClass)
3770 for (y=0; y < (int) (*image)->rows; y++)
3772 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3773 (*image)->columns,1,exception);
3774 if (q == (Quantum *) NULL)
3776 for (x=0; x < (int) (*image)->columns; x++)
3778 GetPixelInfoPixel(*image,q,&pixel);
3779 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3781 SetPixelRed(*image,ScaleShortToQuantum(
3783 SetPixelGreen(*image,ScaleShortToQuantum(
3785 SetPixelBlue(*image,ScaleShortToQuantum(
3788 q+=GetPixelChannels(*image);
3790 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3796 for (i=0; i < (ssize_t) (*image)->colors; i++)
3797 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3799 (*image)->colormap[i].red=(double) ScaleShortToQuantum(
3801 (*image)->colormap[i].green=(double) ScaleShortToQuantum(
3803 (*image)->colormap[i].blue=(double) ScaleShortToQuantum(
3806 (void) SyncImage(*image,exception);
3810 case FloodfillMethod:
3811 case FillToBorderMethod:
3820 Update color information using floodfill algorithm.
3822 (void) GetOneVirtualPixelInfo(*image,
3823 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3824 y_offset,&target,exception);
3825 if (method == FillToBorderMethod)
3827 target.red=(MagickRealType)
3828 ScaleShortToQuantum(border_color.red);
3829 target.green=(MagickRealType)
3830 ScaleShortToQuantum(border_color.green);
3831 target.blue=(MagickRealType)
3832 ScaleShortToQuantum(border_color.blue);
3834 draw_info=CloneDrawInfo(resource_info->image_info,
3836 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3837 AllCompliance,&draw_info->fill,exception);
3838 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
3839 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
3840 MagickFalse : MagickTrue,exception);
3841 draw_info=DestroyDrawInfo(draw_info);
3847 Update color information using reset algorithm.
3849 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3850 return(MagickFalse);
3851 for (y=0; y < (int) (*image)->rows; y++)
3853 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3854 (*image)->columns,1,exception);
3855 if (q == (Quantum *) NULL)
3857 for (x=0; x < (int) (*image)->columns; x++)
3859 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3860 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3861 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3862 q+=GetPixelChannels(*image);
3864 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3870 image_view=DestroyCacheView(image_view);
3871 state&=(~UpdateConfigurationState);
3873 } while ((state & ExitState) == 0);
3874 (void) XSelectInput(display,windows->image.id,
3875 windows->image.attributes.event_mask);
3876 XSetCursorState(display,windows,MagickFalse);
3877 (void) XFreeCursor(display,cursor);
3882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3886 + X C o m p o s i t e I m a g e %
3890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3892 % XCompositeImage() requests an image name from the user, reads the image and
3893 % composites it with the X window image at a location the user chooses with
3896 % The format of the XCompositeImage method is:
3898 % MagickBooleanType XCompositeImage(Display *display,
3899 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3900 % ExceptionInfo *exception)
3902 % A description of each parameter follows:
3904 % o display: Specifies a connection to an X server; returned from
3907 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3909 % o windows: Specifies a pointer to a XWindows structure.
3911 % o image: the image; returned from ReadImage.
3913 % o exception: return any errors or warnings in this structure.
3916 static MagickBooleanType XCompositeImage(Display *display,
3917 XResourceInfo *resource_info,XWindows *windows,Image *image,
3918 ExceptionInfo *exception)
3921 displacement_geometry[MaxTextExtent] = "30x30",
3922 filename[MaxTextExtent] = "\0";
3935 static CompositeOperator
3936 compose = CopyCompositeOp;
3938 static const ModeType
3939 CompositeCommands[] =
3941 CompositeOperatorsCommand,
3942 CompositeDissolveCommand,
3943 CompositeDisplaceCommand,
3944 CompositeHelpCommand,
3945 CompositeDismissCommand
3949 text[MaxTextExtent];
3982 Request image file name from user.
3984 XFileBrowserWidget(display,windows,"Composite",filename);
3985 if (*filename == '\0')
3990 XSetCursorState(display,windows,MagickTrue);
3991 XCheckRefreshWindows(display,windows);
3992 (void) CopyMagickString(resource_info->image_info->filename,filename,
3994 composite_image=ReadImage(resource_info->image_info,exception);
3995 CatchException(exception);
3996 XSetCursorState(display,windows,MagickFalse);
3997 if (composite_image == (Image *) NULL)
3998 return(MagickFalse);
4002 (void) CloneString(&windows->command.name,"Composite");
4003 windows->command.data=1;
4004 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
4005 (void) XMapRaised(display,windows->command.id);
4006 XClientMessage(display,windows->image.id,windows->im_protocols,
4007 windows->im_update_widget,CurrentTime);
4009 Track pointer until button 1 is pressed.
4011 XQueryPosition(display,windows->image.id,&x,&y);
4012 (void) XSelectInput(display,windows->image.id,
4013 windows->image.attributes.event_mask | PointerMotionMask);
4014 composite_info.x=(ssize_t) windows->image.x+x;
4015 composite_info.y=(ssize_t) windows->image.y+y;
4016 composite_info.width=0;
4017 composite_info.height=0;
4018 cursor=XCreateFontCursor(display,XC_ul_angle);
4019 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4024 if (windows->info.mapped != MagickFalse)
4027 Display pointer position.
4029 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4030 (long) composite_info.x,(long) composite_info.y);
4031 XInfoWidget(display,windows,text);
4033 highlight_info=composite_info;
4034 highlight_info.x=composite_info.x-windows->image.x;
4035 highlight_info.y=composite_info.y-windows->image.y;
4036 XHighlightRectangle(display,windows->image.id,
4037 windows->image.highlight_context,&highlight_info);
4039 Wait for next event.
4041 XScreenEvent(display,windows,&event,exception);
4042 XHighlightRectangle(display,windows->image.id,
4043 windows->image.highlight_context,&highlight_info);
4044 if (event.xany.window == windows->command.id)
4047 Select a command from the Command widget.
4049 id=XCommandWidget(display,windows,CompositeMenu,&event);
4052 switch (CompositeCommands[id])
4054 case CompositeOperatorsCommand:
4057 command[MaxTextExtent],
4061 Select a command from the pop-up menu.
4063 operators=GetCommandOptions(MagickComposeOptions);
4064 if (operators == (char **) NULL)
4066 entry=XMenuWidget(display,windows,CompositeMenu[id],
4067 (const char **) operators,command);
4069 compose=(CompositeOperator) ParseCommandOption(
4070 MagickComposeOptions,MagickFalse,operators[entry]);
4071 operators=DestroyStringList(operators);
4074 case CompositeDissolveCommand:
4077 factor[MaxTextExtent] = "20.0";
4080 Dissolve the two images a given percent.
4082 (void) XSetFunction(display,windows->image.highlight_context,
4084 (void) XDialogWidget(display,windows,"Dissolve",
4085 "Enter the blend factor (0.0 - 99.9%):",factor);
4086 (void) XSetFunction(display,windows->image.highlight_context,
4088 if (*factor == '\0')
4090 blend=StringToDouble(factor,(char **) NULL);
4091 compose=DissolveCompositeOp;
4094 case CompositeDisplaceCommand:
4097 Get horizontal and vertical scale displacement geometry.
4099 (void) XSetFunction(display,windows->image.highlight_context,
4101 (void) XDialogWidget(display,windows,"Displace",
4102 "Enter the horizontal and vertical scale:",displacement_geometry);
4103 (void) XSetFunction(display,windows->image.highlight_context,
4105 if (*displacement_geometry == '\0')
4107 compose=DisplaceCompositeOp;
4110 case CompositeHelpCommand:
4112 (void) XSetFunction(display,windows->image.highlight_context,
4114 XTextViewWidget(display,resource_info,windows,MagickFalse,
4115 "Help Viewer - Image Composite",ImageCompositeHelp);
4116 (void) XSetFunction(display,windows->image.highlight_context,
4120 case CompositeDismissCommand:
4138 if (image->debug != MagickFalse)
4139 (void) LogMagickEvent(X11Event,GetMagickModule(),
4140 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4141 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4142 if (event.xbutton.button != Button1)
4144 if (event.xbutton.window != windows->image.id)
4149 composite_info.width=composite_image->columns;
4150 composite_info.height=composite_image->rows;
4151 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4152 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4153 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4158 if (image->debug != MagickFalse)
4159 (void) LogMagickEvent(X11Event,GetMagickModule(),
4160 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4161 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4162 if (event.xbutton.button != Button1)
4164 if (event.xbutton.window != windows->image.id)
4166 if ((composite_info.width != 0) && (composite_info.height != 0))
4169 User has selected the location of the composite image.
4171 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4172 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4182 command[MaxTextExtent];
4190 if (event.xkey.window != windows->image.id)
4193 Respond to a user key press.
4195 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4196 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4197 *(command+length)='\0';
4198 if (image->debug != MagickFalse)
4199 (void) LogMagickEvent(X11Event,GetMagickModule(),
4200 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4201 switch ((int) key_symbol)
4209 composite_image=DestroyImage(composite_image);
4217 (void) XSetFunction(display,windows->image.highlight_context,
4219 XTextViewWidget(display,resource_info,windows,MagickFalse,
4220 "Help Viewer - Image Composite",ImageCompositeHelp);
4221 (void) XSetFunction(display,windows->image.highlight_context,
4227 (void) XBell(display,0);
4236 Map and unmap Info widget as text cursor crosses its boundaries.
4240 if (windows->info.mapped != MagickFalse)
4242 if ((x < (int) (windows->info.x+windows->info.width)) &&
4243 (y < (int) (windows->info.y+windows->info.height)))
4244 (void) XWithdrawWindow(display,windows->info.id,
4245 windows->info.screen);
4248 if ((x > (int) (windows->info.x+windows->info.width)) ||
4249 (y > (int) (windows->info.y+windows->info.height)))
4250 (void) XMapWindow(display,windows->info.id);
4251 composite_info.x=(ssize_t) windows->image.x+x;
4252 composite_info.y=(ssize_t) windows->image.y+y;
4257 if (image->debug != MagickFalse)
4258 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4263 } while ((state & ExitState) == 0);
4264 (void) XSelectInput(display,windows->image.id,
4265 windows->image.attributes.event_mask);
4266 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4267 XSetCursorState(display,windows,MagickFalse);
4268 (void) XFreeCursor(display,cursor);
4269 if ((state & EscapeState) != 0)
4272 Image compositing is relative to image configuration.
4274 XSetCursorState(display,windows,MagickTrue);
4275 XCheckRefreshWindows(display,windows);
4276 width=(unsigned int) image->columns;
4277 height=(unsigned int) image->rows;
4280 if (windows->image.crop_geometry != (char *) NULL)
4281 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4282 scale_factor=(MagickRealType) width/windows->image.ximage->width;
4283 composite_info.x+=x;
4284 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4285 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4286 scale_factor=(MagickRealType) height/windows->image.ximage->height;
4287 composite_info.y+=y;
4288 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4289 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4290 if ((composite_info.width != composite_image->columns) ||
4291 (composite_info.height != composite_image->rows))
4297 Scale composite image.
4299 resize_image=ResizeImage(composite_image,composite_info.width,
4300 composite_info.height,composite_image->filter,exception);
4301 composite_image=DestroyImage(composite_image);
4302 if (resize_image == (Image *) NULL)
4304 XSetCursorState(display,windows,MagickFalse);
4305 return(MagickFalse);
4307 composite_image=resize_image;
4309 if (compose == DisplaceCompositeOp)
4310 (void) SetImageArtifact(composite_image,"compose:args",
4311 displacement_geometry);
4330 Create mattes for blending.
4332 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4333 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
4334 ((ssize_t) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
4335 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4336 return(MagickFalse);
4337 image->matte=MagickTrue;
4338 image_view=AcquireAuthenticCacheView(image,exception);
4339 for (y=0; y < (int) image->rows; y++)
4341 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4343 if (q == (Quantum *) NULL)
4345 for (x=0; x < (int) image->columns; x++)
4347 SetPixelAlpha(image,opacity,q);
4348 q+=GetPixelChannels(image);
4350 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4353 image_view=DestroyCacheView(image_view);
4356 Composite image with X Image window.
4358 (void) CompositeImage(image,composite_image,compose,MagickTrue,
4359 composite_info.x,composite_info.y,exception);
4360 composite_image=DestroyImage(composite_image);
4361 XSetCursorState(display,windows,MagickFalse);
4363 Update image configuration.
4365 XConfigureImageColormap(display,resource_info,windows,image,exception);
4366 (void) XConfigureImage(display,resource_info,windows,image,exception);
4371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4375 + X C o n f i g u r e I m a g e %
4379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4381 % XConfigureImage() creates a new X image. It also notifies the window
4382 % manager of the new image size and configures the transient widows.
4384 % The format of the XConfigureImage method is:
4386 % MagickBooleanType XConfigureImage(Display *display,
4387 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4388 % ExceptionInfo *exception)
4390 % A description of each parameter follows:
4392 % o display: Specifies a connection to an X server; returned from
4395 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4397 % o windows: Specifies a pointer to a XWindows structure.
4399 % o image: the image.
4401 % o exception: return any errors or warnings in this structure.
4403 % o exception: return any errors or warnings in this structure.
4406 static MagickBooleanType XConfigureImage(Display *display,
4407 XResourceInfo *resource_info,XWindows *windows,Image *image,
4408 ExceptionInfo *exception)
4411 geometry[MaxTextExtent];
4432 Dismiss if window dimensions are zero.
4434 width=(unsigned int) windows->image.window_changes.width;
4435 height=(unsigned int) windows->image.window_changes.height;
4436 if (image->debug != MagickFalse)
4437 (void) LogMagickEvent(X11Event,GetMagickModule(),
4438 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4439 windows->image.ximage->height,(double) width,(double) height);
4440 if ((width*height) == 0)
4445 Resize image to fit Image window dimensions.
4447 XSetCursorState(display,windows,MagickTrue);
4448 (void) XFlush(display);
4449 if (((int) width != windows->image.ximage->width) ||
4450 ((int) height != windows->image.ximage->height))
4451 image->taint=MagickTrue;
4452 windows->magnify.x=(int)
4453 width*windows->magnify.x/windows->image.ximage->width;
4454 windows->magnify.y=(int)
4455 height*windows->magnify.y/windows->image.ximage->height;
4456 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4457 windows->image.y=(int)
4458 (height*windows->image.y/windows->image.ximage->height);
4459 status=XMakeImage(display,resource_info,&windows->image,image,
4460 (unsigned int) width,(unsigned int) height,exception);
4461 if (status == MagickFalse)
4462 XNoticeWidget(display,windows,"Unable to configure X image:",
4463 windows->image.name);
4465 Notify window manager of the new configuration.
4467 if (resource_info->image_geometry != (char *) NULL)
4468 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4469 resource_info->image_geometry);
4471 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4472 XDisplayWidth(display,windows->image.screen),
4473 XDisplayHeight(display,windows->image.screen));
4474 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4475 window_changes.width=(int) width;
4476 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4477 window_changes.width=XDisplayWidth(display,windows->image.screen);
4478 window_changes.height=(int) height;
4479 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4480 window_changes.height=XDisplayHeight(display,windows->image.screen);
4481 mask=(size_t) (CWWidth | CWHeight);
4482 if (resource_info->backdrop)
4485 window_changes.x=(int)
4486 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4487 window_changes.y=(int)
4488 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4490 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4491 (unsigned int) mask,&window_changes);
4492 (void) XClearWindow(display,windows->image.id);
4493 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4495 Update Magnify window configuration.
4497 if (windows->magnify.mapped != MagickFalse)
4498 XMakeMagnifyImage(display,windows,exception);
4499 windows->pan.crop_geometry=windows->image.crop_geometry;
4500 XBestIconSize(display,&windows->pan,image);
4501 while (((windows->pan.width << 1) < MaxIconSize) &&
4502 ((windows->pan.height << 1) < MaxIconSize))
4504 windows->pan.width<<=1;
4505 windows->pan.height<<=1;
4507 if (windows->pan.geometry != (char *) NULL)
4508 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4509 &windows->pan.width,&windows->pan.height);
4510 window_changes.width=(int) windows->pan.width;
4511 window_changes.height=(int) windows->pan.height;
4512 size_hints=XAllocSizeHints();
4513 if (size_hints != (XSizeHints *) NULL)
4518 size_hints->flags=PSize | PMinSize | PMaxSize;
4519 size_hints->width=window_changes.width;
4520 size_hints->height=window_changes.height;
4521 size_hints->min_width=size_hints->width;
4522 size_hints->min_height=size_hints->height;
4523 size_hints->max_width=size_hints->width;
4524 size_hints->max_height=size_hints->height;
4525 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4526 (void) XFree((void *) size_hints);
4528 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4529 (unsigned int) (CWWidth | CWHeight),&window_changes);
4531 Update icon window configuration.
4533 windows->icon.crop_geometry=windows->image.crop_geometry;
4534 XBestIconSize(display,&windows->icon,image);
4535 window_changes.width=(int) windows->icon.width;
4536 window_changes.height=(int) windows->icon.height;
4537 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4538 (unsigned int) (CWWidth | CWHeight),&window_changes);
4539 XSetCursorState(display,windows,MagickFalse);
4540 return(status != 0 ? MagickTrue : MagickFalse);
4544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4548 + X C r o p I m a g e %
4552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4554 % XCropImage() allows the user to select a region of the image and crop, copy,
4555 % or cut it. For copy or cut, the image can subsequently be composited onto
4556 % the image with XPasteImage.
4558 % The format of the XCropImage method is:
4560 % MagickBooleanType XCropImage(Display *display,
4561 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4562 % const ClipboardMode mode,ExceptionInfo *exception)
4564 % A description of each parameter follows:
4566 % o display: Specifies a connection to an X server; returned from
4569 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4571 % o windows: Specifies a pointer to a XWindows structure.
4573 % o image: the image; returned from ReadImage.
4575 % o mode: This unsigned value specified whether the image should be
4576 % cropped, copied, or cut.
4578 % o exception: return any errors or warnings in this structure.
4581 static MagickBooleanType XCropImage(Display *display,
4582 XResourceInfo *resource_info,XWindows *windows,Image *image,
4583 const ClipboardMode mode,ExceptionInfo *exception)
4592 *RectifyModeMenu[] =
4600 static const ModeType
4610 RectifyDismissCommand
4617 command[MaxTextExtent],
4618 text[MaxTextExtent];
4661 (void) CloneString(&windows->command.name,"Copy");
4666 (void) CloneString(&windows->command.name,"Crop");
4671 (void) CloneString(&windows->command.name,"Cut");
4675 RectifyModeMenu[0]=windows->command.name;
4676 windows->command.data=0;
4677 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4678 (void) XMapRaised(display,windows->command.id);
4679 XClientMessage(display,windows->image.id,windows->im_protocols,
4680 windows->im_update_widget,CurrentTime);
4682 Track pointer until button 1 is pressed.
4684 XQueryPosition(display,windows->image.id,&x,&y);
4685 (void) XSelectInput(display,windows->image.id,
4686 windows->image.attributes.event_mask | PointerMotionMask);
4687 crop_info.x=(ssize_t) windows->image.x+x;
4688 crop_info.y=(ssize_t) windows->image.y+y;
4691 cursor=XCreateFontCursor(display,XC_fleur);
4695 if (windows->info.mapped != MagickFalse)
4698 Display pointer position.
4700 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4701 (long) crop_info.x,(long) crop_info.y);
4702 XInfoWidget(display,windows,text);
4705 Wait for next event.
4707 XScreenEvent(display,windows,&event,exception);
4708 if (event.xany.window == windows->command.id)
4711 Select a command from the Command widget.
4713 id=XCommandWidget(display,windows,CropModeMenu,&event);
4716 switch (CropCommands[id])
4718 case CropHelpCommand:
4724 XTextViewWidget(display,resource_info,windows,MagickFalse,
4725 "Help Viewer - Image Copy",ImageCopyHelp);
4730 XTextViewWidget(display,resource_info,windows,MagickFalse,
4731 "Help Viewer - Image Crop",ImageCropHelp);
4736 XTextViewWidget(display,resource_info,windows,MagickFalse,
4737 "Help Viewer - Image Cut",ImageCutHelp);
4743 case CropDismissCommand:
4761 if (event.xbutton.button != Button1)
4763 if (event.xbutton.window != windows->image.id)
4766 Note first corner of cropping rectangle-- exit loop.
4768 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4769 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4770 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4780 if (event.xkey.window != windows->image.id)
4783 Respond to a user key press.
4785 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4786 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4787 switch ((int) key_symbol)
4806 XTextViewWidget(display,resource_info,windows,MagickFalse,
4807 "Help Viewer - Image Copy",ImageCopyHelp);
4812 XTextViewWidget(display,resource_info,windows,MagickFalse,
4813 "Help Viewer - Image Crop",ImageCropHelp);
4818 XTextViewWidget(display,resource_info,windows,MagickFalse,
4819 "Help Viewer - Image Cut",ImageCutHelp);
4827 (void) XBell(display,0);
4835 if (event.xmotion.window != windows->image.id)
4838 Map and unmap Info widget as text cursor crosses its boundaries.
4842 if (windows->info.mapped != MagickFalse)
4844 if ((x < (int) (windows->info.x+windows->info.width)) &&
4845 (y < (int) (windows->info.y+windows->info.height)))
4846 (void) XWithdrawWindow(display,windows->info.id,
4847 windows->info.screen);
4850 if ((x > (int) (windows->info.x+windows->info.width)) ||
4851 (y > (int) (windows->info.y+windows->info.height)))
4852 (void) XMapWindow(display,windows->info.id);
4853 crop_info.x=(ssize_t) windows->image.x+x;
4854 crop_info.y=(ssize_t) windows->image.y+y;
4860 } while ((state & ExitState) == 0);
4861 (void) XSelectInput(display,windows->image.id,
4862 windows->image.attributes.event_mask);
4863 if ((state & EscapeState) != 0)
4866 User want to exit without cropping.
4868 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4869 (void) XFreeCursor(display,cursor);
4872 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4876 Size rectangle as pointer moves until the mouse button is released.
4878 x=(int) crop_info.x;
4879 y=(int) crop_info.y;
4885 highlight_info=crop_info;
4886 highlight_info.x=crop_info.x-windows->image.x;
4887 highlight_info.y=crop_info.y-windows->image.y;
4888 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4891 Display info and draw cropping rectangle.
4893 if (windows->info.mapped == MagickFalse)
4894 (void) XMapWindow(display,windows->info.id);
4895 (void) FormatLocaleString(text,MaxTextExtent,
4896 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4897 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4898 XInfoWidget(display,windows,text);
4899 XHighlightRectangle(display,windows->image.id,
4900 windows->image.highlight_context,&highlight_info);
4903 if (windows->info.mapped != MagickFalse)
4904 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4906 Wait for next event.
4908 XScreenEvent(display,windows,&event,exception);
4909 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4910 XHighlightRectangle(display,windows->image.id,
4911 windows->image.highlight_context,&highlight_info);
4916 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4917 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4923 User has committed to cropping rectangle.
4925 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4926 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4927 XSetCursorState(display,windows,MagickFalse);
4929 windows->command.data=0;
4930 (void) XCommandWidget(display,windows,RectifyModeMenu,
4938 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4939 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4944 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4945 ((state & ExitState) != 0))
4948 Check boundary conditions.
4950 if (crop_info.x < 0)
4953 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4954 crop_info.x=(ssize_t) windows->image.ximage->width;
4955 if ((int) crop_info.x < x)
4956 crop_info.width=(unsigned int) (x-crop_info.x);
4959 crop_info.width=(unsigned int) (crop_info.x-x);
4960 crop_info.x=(ssize_t) x;
4962 if (crop_info.y < 0)
4965 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4966 crop_info.y=(ssize_t) windows->image.ximage->height;
4967 if ((int) crop_info.y < y)
4968 crop_info.height=(unsigned int) (y-crop_info.y);
4971 crop_info.height=(unsigned int) (crop_info.y-y);
4972 crop_info.y=(ssize_t) y;
4975 } while ((state & ExitState) == 0);
4977 Wait for user to grab a corner of the rectangle or press return.
4980 (void) XMapWindow(display,windows->info.id);
4983 if (windows->info.mapped != MagickFalse)
4986 Display pointer position.
4988 (void) FormatLocaleString(text,MaxTextExtent,
4989 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4990 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4991 XInfoWidget(display,windows,text);
4993 highlight_info=crop_info;
4994 highlight_info.x=crop_info.x-windows->image.x;
4995 highlight_info.y=crop_info.y-windows->image.y;
4996 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
5002 XHighlightRectangle(display,windows->image.id,
5003 windows->image.highlight_context,&highlight_info);
5004 XScreenEvent(display,windows,&event,exception);
5005 if (event.xany.window == windows->command.id)
5008 Select a command from the Command widget.
5010 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5011 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5012 (void) XSetFunction(display,windows->image.highlight_context,
5014 XHighlightRectangle(display,windows->image.id,
5015 windows->image.highlight_context,&highlight_info);
5017 switch (RectifyCommands[id])
5019 case RectifyCopyCommand:
5024 case RectifyHelpCommand:
5026 (void) XSetFunction(display,windows->image.highlight_context,
5032 XTextViewWidget(display,resource_info,windows,MagickFalse,
5033 "Help Viewer - Image Copy",ImageCopyHelp);
5038 XTextViewWidget(display,resource_info,windows,MagickFalse,
5039 "Help Viewer - Image Crop",ImageCropHelp);
5044 XTextViewWidget(display,resource_info,windows,MagickFalse,
5045 "Help Viewer - Image Cut",ImageCutHelp);
5049 (void) XSetFunction(display,windows->image.highlight_context,
5053 case RectifyDismissCommand:
5067 XHighlightRectangle(display,windows->image.id,
5068 windows->image.highlight_context,&highlight_info);
5073 if (event.xbutton.button != Button1)
5075 if (event.xbutton.window != windows->image.id)
5077 x=windows->image.x+event.xbutton.x;
5078 y=windows->image.y+event.xbutton.y;
5079 if ((x < (int) (crop_info.x+RoiDelta)) &&
5080 (x > (int) (crop_info.x-RoiDelta)) &&
5081 (y < (int) (crop_info.y+RoiDelta)) &&
5082 (y > (int) (crop_info.y-RoiDelta)))
5084 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5085 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5086 state|=UpdateConfigurationState;
5089 if ((x < (int) (crop_info.x+RoiDelta)) &&
5090 (x > (int) (crop_info.x-RoiDelta)) &&
5091 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5092 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5094 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5095 state|=UpdateConfigurationState;
5098 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5099 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5100 (y < (int) (crop_info.y+RoiDelta)) &&
5101 (y > (int) (crop_info.y-RoiDelta)))
5103 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5104 state|=UpdateConfigurationState;
5107 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5108 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5109 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5110 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5112 state|=UpdateConfigurationState;
5118 if (event.xbutton.window == windows->pan.id)
5119 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5120 (highlight_info.y != crop_info.y-windows->image.y))
5121 XHighlightRectangle(display,windows->image.id,
5122 windows->image.highlight_context,&highlight_info);
5123 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5124 event.xbutton.time);
5129 if (event.xexpose.window == windows->image.id)
5130 if (event.xexpose.count == 0)
5132 event.xexpose.x=(int) highlight_info.x;
5133 event.xexpose.y=(int) highlight_info.y;
5134 event.xexpose.width=(int) highlight_info.width;
5135 event.xexpose.height=(int) highlight_info.height;
5136 XRefreshWindow(display,&windows->image,&event);
5138 if (event.xexpose.window == windows->info.id)
5139 if (event.xexpose.count == 0)
5140 XInfoWidget(display,windows,text);
5145 if (event.xkey.window != windows->image.id)
5148 Respond to a user key press.
5150 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5151 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5152 switch ((int) key_symbol)
5165 crop_info.x=(ssize_t) (windows->image.width/2L-
5166 crop_info.width/2L);
5167 crop_info.y=(ssize_t) (windows->image.height/2L-
5168 crop_info.height/2L);
5200 (void) XSetFunction(display,windows->image.highlight_context,
5206 XTextViewWidget(display,resource_info,windows,MagickFalse,
5207 "Help Viewer - Image Copy",ImageCopyHelp);
5212 XTextViewWidget(display,resource_info,windows,MagickFalse,
5213 "Help Viewer - Image Cropg",ImageCropHelp);
5218 XTextViewWidget(display,resource_info,windows,MagickFalse,
5219 "Help Viewer - Image Cutg",ImageCutHelp);
5223 (void) XSetFunction(display,windows->image.highlight_context,
5229 (void) XBell(display,0);
5233 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5241 if (event.xmotion.window != windows->image.id)
5244 Map and unmap Info widget as text cursor crosses its boundaries.
5248 if (windows->info.mapped != MagickFalse)
5250 if ((x < (int) (windows->info.x+windows->info.width)) &&
5251 (y < (int) (windows->info.y+windows->info.height)))
5252 (void) XWithdrawWindow(display,windows->info.id,
5253 windows->info.screen);
5256 if ((x > (int) (windows->info.x+windows->info.width)) ||
5257 (y > (int) (windows->info.y+windows->info.height)))
5258 (void) XMapWindow(display,windows->info.id);
5259 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5260 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5263 case SelectionRequest:
5268 XSelectionRequestEvent
5272 Set primary selection.
5274 (void) FormatLocaleString(text,MaxTextExtent,
5275 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5276 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5277 request=(&(event.xselectionrequest));
5278 (void) XChangeProperty(request->display,request->requestor,
5279 request->property,request->target,8,PropModeReplace,
5280 (unsigned char *) text,(int) strlen(text));
5281 notify.type=SelectionNotify;
5282 notify.display=request->display;
5283 notify.requestor=request->requestor;
5284 notify.selection=request->selection;
5285 notify.target=request->target;
5286 notify.time=request->time;
5287 if (request->property == None)
5288 notify.property=request->target;
5290 notify.property=request->property;
5291 (void) XSendEvent(request->display,request->requestor,False,0,
5292 (XEvent *) ¬ify);
5297 if ((state & UpdateConfigurationState) != 0)
5299 (void) XPutBackEvent(display,&event);
5300 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5303 } while ((state & ExitState) == 0);
5304 } while ((state & ExitState) == 0);
5305 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5306 XSetCursorState(display,windows,MagickFalse);
5307 if ((state & EscapeState) != 0)
5309 if (mode == CropMode)
5310 if (((int) crop_info.width != windows->image.ximage->width) ||
5311 ((int) crop_info.height != windows->image.ximage->height))
5314 Reconfigure Image window as defined by cropping rectangle.
5316 XSetCropGeometry(display,windows,&crop_info,image);
5317 windows->image.window_changes.width=(int) crop_info.width;
5318 windows->image.window_changes.height=(int) crop_info.height;
5319 (void) XConfigureImage(display,resource_info,windows,image,exception);
5323 Copy image before applying image transforms.
5325 XSetCursorState(display,windows,MagickTrue);
5326 XCheckRefreshWindows(display,windows);
5327 width=(unsigned int) image->columns;
5328 height=(unsigned int) image->rows;
5331 if (windows->image.crop_geometry != (char *) NULL)
5332 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5333 scale_factor=(MagickRealType) width/windows->image.ximage->width;
5335 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5336 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5337 scale_factor=(MagickRealType) height/windows->image.ximage->height;
5339 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5340 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5341 crop_image=CropImage(image,&crop_info,exception);
5342 XSetCursorState(display,windows,MagickFalse);
5343 if (crop_image == (Image *) NULL)
5344 return(MagickFalse);
5345 if (resource_info->copy_image != (Image *) NULL)
5346 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5347 resource_info->copy_image=crop_image;
5348 if (mode == CopyMode)
5350 (void) XConfigureImage(display,resource_info,windows,image,exception);
5356 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
5357 return(MagickFalse);
5358 image->matte=MagickTrue;
5359 image_view=AcquireAuthenticCacheView(image,exception);
5360 for (y=0; y < (int) crop_info.height; y++)
5362 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5363 crop_info.width,1,exception);
5364 if (q == (Quantum *) NULL)
5366 for (x=0; x < (int) crop_info.width; x++)
5368 SetPixelAlpha(image,TransparentAlpha,q);
5369 q+=GetPixelChannels(image);
5371 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
5374 image_view=DestroyCacheView(image_view);
5376 Update image configuration.
5378 XConfigureImageColormap(display,resource_info,windows,image,exception);
5379 (void) XConfigureImage(display,resource_info,windows,image,exception);
5384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5388 + X D r a w I m a g e %
5392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5394 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5397 % The format of the XDrawEditImage method is:
5399 % MagickBooleanType XDrawEditImage(Display *display,
5400 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5401 % ExceptionInfo *exception)
5403 % A description of each parameter follows:
5405 % o display: Specifies a connection to an X server; returned from
5408 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5410 % o windows: Specifies a pointer to a XWindows structure.
5412 % o image: the image.
5414 % o exception: return any errors or warnings in this structure.
5417 static MagickBooleanType XDrawEditImage(Display *display,
5418 XResourceInfo *resource_info,XWindows *windows,Image **image,
5419 ExceptionInfo *exception)
5435 element = PointElement;
5437 static const ModeType
5450 stipple = (Pixmap) NULL;
5457 command[MaxTextExtent],
5458 text[MaxTextExtent];
5507 Allocate polygon info.
5509 max_coordinates=2048;
5510 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5511 sizeof(*coordinate_info));
5512 if (coordinate_info == (XPoint *) NULL)
5514 (void) ThrowMagickException(exception,GetMagickModule(),
5515 ResourceLimitError,"MemoryAllocationFailed","'%s'","...");
5516 return(MagickFalse);
5521 (void) CloneString(&windows->command.name,"Draw");
5522 windows->command.data=4;
5523 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5524 (void) XMapRaised(display,windows->command.id);
5525 XClientMessage(display,windows->image.id,windows->im_protocols,
5526 windows->im_update_widget,CurrentTime);
5528 Wait for first button press.
5530 root_window=XRootWindow(display,XDefaultScreen(display));
5531 draw_info.stencil=OpaqueStencil;
5533 cursor=XCreateFontCursor(display,XC_tcross);
5536 XQueryPosition(display,windows->image.id,&x,&y);
5537 (void) XSelectInput(display,windows->image.id,
5538 windows->image.attributes.event_mask | PointerMotionMask);
5539 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5543 if (windows->info.mapped != MagickFalse)
5546 Display pointer position.
5548 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5549 x+windows->image.x,y+windows->image.y);
5550 XInfoWidget(display,windows,text);
5553 Wait for next event.
5555 XScreenEvent(display,windows,&event,exception);
5556 if (event.xany.window == windows->command.id)
5559 Select a command from the Command widget.
5561 id=XCommandWidget(display,windows,DrawMenu,&event);
5564 switch (DrawCommands[id])
5566 case DrawElementCommand:
5585 Select a command from the pop-up menu.
5587 element=(ElementType) (XMenuWidget(display,windows,
5588 DrawMenu[id],Elements,command)+1);
5591 case DrawColorCommand:
5594 *ColorMenu[MaxNumberPens+1];
5606 Initialize menu selections.
5608 for (i=0; i < (int) (MaxNumberPens-2); i++)
5609 ColorMenu[i]=resource_info->pen_colors[i];
5610 ColorMenu[MaxNumberPens-2]="transparent";
5611 ColorMenu[MaxNumberPens-1]="Browser...";
5612 ColorMenu[MaxNumberPens]=(char *) NULL;
5614 Select a pen color from the pop-up menu.
5616 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5617 (const char **) ColorMenu,command);
5620 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5622 if (transparent != MagickFalse)
5624 draw_info.stencil=TransparentStencil;
5627 if (pen_number == (MaxNumberPens-1))
5630 color_name[MaxTextExtent] = "gray";
5633 Select a pen color from a dialog.
5635 resource_info->pen_colors[pen_number]=color_name;
5636 XColorBrowserWidget(display,windows,"Select",color_name);
5637 if (*color_name == '\0')
5643 (void) XParseColor(display,windows->map_info->colormap,
5644 resource_info->pen_colors[pen_number],&color);
5645 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5646 (unsigned int) MaxColors,&color);
5647 windows->pixel_info->pen_colors[pen_number]=color;
5648 pen_id=(unsigned int) pen_number;
5649 draw_info.stencil=OpaqueStencil;
5652 case DrawStippleCommand:
5664 filename[MaxTextExtent] = "\0";
5681 Select a command from the pop-up menu.
5683 StipplesMenu[7]="Open...";
5684 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5688 if (stipple != (Pixmap) NULL)
5689 (void) XFreePixmap(display,stipple);
5690 stipple=(Pixmap) NULL;
5697 stipple=XCreateBitmapFromData(display,root_window,
5698 (char *) BricksBitmap,BricksWidth,BricksHeight);
5703 stipple=XCreateBitmapFromData(display,root_window,
5704 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5709 stipple=XCreateBitmapFromData(display,root_window,
5710 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5715 stipple=XCreateBitmapFromData(display,root_window,
5716 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5721 stipple=XCreateBitmapFromData(display,root_window,
5722 (char *) WavyBitmap,WavyWidth,WavyHeight);
5727 stipple=XCreateBitmapFromData(display,root_window,
5728 (char *) HighlightBitmap,HighlightWidth,
5735 stipple=XCreateBitmapFromData(display,root_window,
5736 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5742 XFileBrowserWidget(display,windows,"Stipple",filename);
5743 if (*filename == '\0')
5748 XSetCursorState(display,windows,MagickTrue);
5749 XCheckRefreshWindows(display,windows);
5750 image_info=AcquireImageInfo();
5751 (void) CopyMagickString(image_info->filename,filename,
5753 stipple_image=ReadImage(image_info,exception);
5754 CatchException(exception);
5755 XSetCursorState(display,windows,MagickFalse);
5756 if (stipple_image == (Image *) NULL)
5758 (void) AcquireUniqueFileResource(filename);
5759 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5761 (void) WriteImage(image_info,stipple_image,exception);
5762 stipple_image=DestroyImage(stipple_image);
5763 image_info=DestroyImageInfo(image_info);
5764 status=XReadBitmapFile(display,root_window,filename,&width,
5765 &height,&stipple,&x,&y);
5766 (void) RelinquishUniqueFileResource(filename);
5767 if ((status != BitmapSuccess) != 0)
5768 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5772 case DrawWidthCommand:
5775 width[MaxTextExtent] = "0";
5790 Select a command from the pop-up menu.
5792 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5798 line_width=(unsigned int) StringToUnsignedLong(
5802 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5806 line_width=(unsigned int) StringToUnsignedLong(width);
5809 case DrawUndoCommand:
5811 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5815 case DrawHelpCommand:
5817 XTextViewWidget(display,resource_info,windows,MagickFalse,
5818 "Help Viewer - Image Rotation",ImageDrawHelp);
5819 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5822 case DrawDismissCommand:
5834 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5841 if (event.xbutton.button != Button1)
5843 if (event.xbutton.window != windows->image.id)
5862 if (event.xkey.window != windows->image.id)
5865 Respond to a user key press.
5867 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5868 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5869 switch ((int) key_symbol)
5884 XTextViewWidget(display,resource_info,windows,MagickFalse,
5885 "Help Viewer - Image Rotation",ImageDrawHelp);
5890 (void) XBell(display,0);
5899 Map and unmap Info widget as text cursor crosses its boundaries.
5903 if (windows->info.mapped != MagickFalse)
5905 if ((x < (int) (windows->info.x+windows->info.width)) &&
5906 (y < (int) (windows->info.y+windows->info.height)))
5907 (void) XWithdrawWindow(display,windows->info.id,
5908 windows->info.screen);
5911 if ((x > (int) (windows->info.x+windows->info.width)) ||
5912 (y > (int) (windows->info.y+windows->info.height)))
5913 (void) XMapWindow(display,windows->info.id);
5917 } while ((state & ExitState) == 0);
5918 (void) XSelectInput(display,windows->image.id,
5919 windows->image.attributes.event_mask);
5920 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5921 if ((state & EscapeState) != 0)
5924 Draw element as pointer moves until the button is released.
5932 rectangle_info.x=(ssize_t) x;
5933 rectangle_info.y=(ssize_t) y;
5934 rectangle_info.width=0;
5935 rectangle_info.height=0;
5936 number_coordinates=1;
5937 coordinate_info->x=x;
5938 coordinate_info->y=y;
5939 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5948 if (number_coordinates > 1)
5950 (void) XDrawLines(display,windows->image.id,
5951 windows->image.highlight_context,coordinate_info,
5952 number_coordinates,CoordModeOrigin);
5953 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5954 coordinate_info[number_coordinates-1].x,
5955 coordinate_info[number_coordinates-1].y);
5956 XInfoWidget(display,windows,text);
5965 Display angle of the line.
5967 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5968 line_info.y1),(double) (line_info.x2-line_info.x1)));
5969 (void) FormatLocaleString(text,MaxTextExtent," %g",
5971 XInfoWidget(display,windows,text);
5972 XHighlightLine(display,windows->image.id,
5973 windows->image.highlight_context,&line_info);
5976 if (windows->info.mapped != MagickFalse)
5977 (void) XWithdrawWindow(display,windows->info.id,
5978 windows->info.screen);
5981 case RectangleElement:
5982 case FillRectangleElement:
5984 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5987 Display info and draw drawing rectangle.
5989 (void) FormatLocaleString(text,MaxTextExtent,
5990 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5991 (double) rectangle_info.height,(double) rectangle_info.x,
5992 (double) rectangle_info.y);
5993 XInfoWidget(display,windows,text);
5994 XHighlightRectangle(display,windows->image.id,
5995 windows->image.highlight_context,&rectangle_info);
5998 if (windows->info.mapped != MagickFalse)
5999 (void) XWithdrawWindow(display,windows->info.id,
6000 windows->info.screen);
6004 case FillCircleElement:
6005 case EllipseElement:
6006 case FillEllipseElement:
6008 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6011 Display info and draw drawing rectangle.
6013 (void) FormatLocaleString(text,MaxTextExtent,
6014 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6015 (double) rectangle_info.height,(double) rectangle_info.x,
6016 (double) rectangle_info.y);
6017 XInfoWidget(display,windows,text);
6018 XHighlightEllipse(display,windows->image.id,
6019 windows->image.highlight_context,&rectangle_info);
6022 if (windows->info.mapped != MagickFalse)
6023 (void) XWithdrawWindow(display,windows->info.id,
6024 windows->info.screen);
6027 case PolygonElement:
6028 case FillPolygonElement:
6030 if (number_coordinates > 1)
6031 (void) XDrawLines(display,windows->image.id,
6032 windows->image.highlight_context,coordinate_info,
6033 number_coordinates,CoordModeOrigin);
6037 Display angle of the line.
6039 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6040 line_info.y1),(double) (line_info.x2-line_info.x1)));
6041 (void) FormatLocaleString(text,MaxTextExtent," %g",
6043 XInfoWidget(display,windows,text);
6044 XHighlightLine(display,windows->image.id,
6045 windows->image.highlight_context,&line_info);
6048 if (windows->info.mapped != MagickFalse)
6049 (void) XWithdrawWindow(display,windows->info.id,
6050 windows->info.screen);
6055 Wait for next event.
6057 XScreenEvent(display,windows,&event,exception);
6063 if (number_coordinates > 1)
6064 (void) XDrawLines(display,windows->image.id,
6065 windows->image.highlight_context,coordinate_info,
6066 number_coordinates,CoordModeOrigin);
6072 XHighlightLine(display,windows->image.id,
6073 windows->image.highlight_context,&line_info);
6076 case RectangleElement:
6077 case FillRectangleElement:
6079 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6080 XHighlightRectangle(display,windows->image.id,
6081 windows->image.highlight_context,&rectangle_info);
6085 case FillCircleElement:
6086 case EllipseElement:
6087 case FillEllipseElement:
6089 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6090 XHighlightEllipse(display,windows->image.id,
6091 windows->image.highlight_context,&rectangle_info);
6094 case PolygonElement:
6095 case FillPolygonElement:
6097 if (number_coordinates > 1)
6098 (void) XDrawLines(display,windows->image.id,
6099 windows->image.highlight_context,coordinate_info,
6100 number_coordinates,CoordModeOrigin);
6102 XHighlightLine(display,windows->image.id,
6103 windows->image.highlight_context,&line_info);
6114 User has committed to element.
6116 line_info.x2=event.xbutton.x;
6117 line_info.y2=event.xbutton.y;
6118 rectangle_info.x=(ssize_t) event.xbutton.x;
6119 rectangle_info.y=(ssize_t) event.xbutton.y;
6120 coordinate_info[number_coordinates].x=event.xbutton.x;
6121 coordinate_info[number_coordinates].y=event.xbutton.y;
6122 if (((element != PolygonElement) &&
6123 (element != FillPolygonElement)) || (distance <= 9))
6128 number_coordinates++;
6129 if (number_coordinates < (int) max_coordinates)
6131 line_info.x1=event.xbutton.x;
6132 line_info.y1=event.xbutton.y;
6135 max_coordinates<<=1;
6136 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6137 max_coordinates,sizeof(*coordinate_info));
6138 if (coordinate_info == (XPoint *) NULL)
6139 (void) ThrowMagickException(exception,GetMagickModule(),
6140 ResourceLimitError,"MemoryAllocationFailed","'%s'","...");
6147 if (event.xmotion.window != windows->image.id)
6149 if (element != PointElement)
6151 line_info.x2=event.xmotion.x;
6152 line_info.y2=event.xmotion.y;
6153 rectangle_info.x=(ssize_t) event.xmotion.x;
6154 rectangle_info.y=(ssize_t) event.xmotion.y;
6157 coordinate_info[number_coordinates].x=event.xbutton.x;
6158 coordinate_info[number_coordinates].y=event.xbutton.y;
6159 number_coordinates++;
6160 if (number_coordinates < (int) max_coordinates)
6162 max_coordinates<<=1;
6163 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6164 max_coordinates,sizeof(*coordinate_info));
6165 if (coordinate_info == (XPoint *) NULL)
6166 (void) ThrowMagickException(exception,GetMagickModule(),
6167 ResourceLimitError,"MemoryAllocationFailed","'%s'","...");
6174 Check boundary conditions.
6176 if (line_info.x2 < 0)
6179 if (line_info.x2 > (int) windows->image.width)
6180 line_info.x2=(short) windows->image.width;
6181 if (line_info.y2 < 0)
6184 if (line_info.y2 > (int) windows->image.height)
6185 line_info.y2=(short) windows->image.height;
6186 distance=(unsigned int)
6187 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6188 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6189 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6190 ((state & ExitState) != 0))
6192 if (rectangle_info.x < 0)
6195 if (rectangle_info.x > (ssize_t) windows->image.width)
6196 rectangle_info.x=(ssize_t) windows->image.width;
6197 if ((int) rectangle_info.x < x)
6198 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6201 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6202 rectangle_info.x=(ssize_t) x;
6204 if (rectangle_info.y < 0)
6207 if (rectangle_info.y > (ssize_t) windows->image.height)
6208 rectangle_info.y=(ssize_t) windows->image.height;
6209 if ((int) rectangle_info.y < y)
6210 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6213 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6214 rectangle_info.y=(ssize_t) y;
6217 } while ((state & ExitState) == 0);
6218 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6219 if ((element == PointElement) || (element == PolygonElement) ||
6220 (element == FillPolygonElement))
6223 Determine polygon bounding box.
6225 rectangle_info.x=(ssize_t) coordinate_info->x;
6226 rectangle_info.y=(ssize_t) coordinate_info->y;
6227 x=coordinate_info->x;
6228 y=coordinate_info->y;
6229 for (i=1; i < number_coordinates; i++)
6231 if (coordinate_info[i].x > x)
6232 x=coordinate_info[i].x;
6233 if (coordinate_info[i].y > y)
6234 y=coordinate_info[i].y;
6235 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6236 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6237 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6238 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6240 rectangle_info.width=(size_t) (x-rectangle_info.x);
6241 rectangle_info.height=(size_t) (y-rectangle_info.y);
6242 for (i=0; i < number_coordinates; i++)
6244 coordinate_info[i].x-=rectangle_info.x;
6245 coordinate_info[i].y-=rectangle_info.y;
6252 if ((element == RectangleElement) ||
6253 (element == CircleElement) || (element == EllipseElement))
6255 rectangle_info.width--;
6256 rectangle_info.height--;
6259 Drawing is relative to image configuration.
6261 draw_info.x=(int) rectangle_info.x;
6262 draw_info.y=(int) rectangle_info.y;
6263 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6265 width=(unsigned int) (*image)->columns;
6266 height=(unsigned int) (*image)->rows;
6269 if (windows->image.crop_geometry != (char *) NULL)
6270 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6271 draw_info.x+=windows->image.x-(line_width/2);
6272 if (draw_info.x < 0)
6274 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6275 draw_info.y+=windows->image.y-(line_width/2);
6276 if (draw_info.y < 0)
6278 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6279 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6280 if (draw_info.width > (unsigned int) (*image)->columns)
6281 draw_info.width=(unsigned int) (*image)->columns;
6282 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6283 if (draw_info.height > (unsigned int) (*image)->rows)
6284 draw_info.height=(unsigned int) (*image)->rows;
6285 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6286 width*draw_info.width/windows->image.ximage->width,
6287 height*draw_info.height/windows->image.ximage->height,
6288 draw_info.x+x,draw_info.y+y);
6290 Initialize drawing attributes.
6292 draw_info.degrees=0.0;
6293 draw_info.element=element;
6294 draw_info.stipple=stipple;
6295 draw_info.line_width=line_width;
6296 draw_info.line_info=line_info;
6297 if (line_info.x1 > (int) (line_width/2))
6298 draw_info.line_info.x1=(short) line_width/2;
6299 if (line_info.y1 > (int) (line_width/2))
6300 draw_info.line_info.y1=(short) line_width/2;
6301 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6302 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6303 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6305 draw_info.line_info.x2=(-draw_info.line_info.x2);
6306 draw_info.line_info.y2=(-draw_info.line_info.y2);
6308 if (draw_info.line_info.x2 < 0)
6310 draw_info.line_info.x2=(-draw_info.line_info.x2);
6311 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6313 if (draw_info.line_info.y2 < 0)
6315 draw_info.line_info.y2=(-draw_info.line_info.y2);
6316 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6318 draw_info.rectangle_info=rectangle_info;
6319 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6320 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6321 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6322 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6323 draw_info.number_coordinates=(unsigned int) number_coordinates;
6324 draw_info.coordinate_info=coordinate_info;
6325 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6327 Draw element on image.
6329 XSetCursorState(display,windows,MagickTrue);
6330 XCheckRefreshWindows(display,windows);
6331 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6332 XSetCursorState(display,windows,MagickFalse);
6334 Update image colormap and return to image drawing.
6336 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6337 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6339 XSetCursorState(display,windows,MagickFalse);
6340 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6341 return(status != 0 ? MagickTrue : MagickFalse);
6345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6349 + X D r a w P a n R e c t a n g l e %
6353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6355 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6356 % displays a zoom image and the rectangle shows which portion of the image is
6357 % displayed in the Image window.
6359 % The format of the XDrawPanRectangle method is:
6361 % XDrawPanRectangle(Display *display,XWindows *windows)
6363 % A description of each parameter follows:
6365 % o display: Specifies a connection to an X server; returned from
6368 % o windows: Specifies a pointer to a XWindows structure.
6371 static void XDrawPanRectangle(Display *display,XWindows *windows)
6380 Determine dimensions of the panning rectangle.
6382 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
6383 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6384 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6385 scale_factor=(MagickRealType)
6386 windows->pan.height/windows->image.ximage->height;
6387 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6388 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6390 Display the panning rectangle.
6392 (void) XClearWindow(display,windows->pan.id);
6393 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6402 + X I m a g e C a c h e %
6406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6408 % XImageCache() handles the creation, manipulation, and destruction of the
6409 % image cache (undo and redo buffers).
6411 % The format of the XImageCache method is:
6413 % void XImageCache(Display *display,XResourceInfo *resource_info,
6414 % XWindows *windows,const CommandType command,Image **image,
6415 % ExceptionInfo *exception)
6417 % A description of each parameter follows:
6419 % o display: Specifies a connection to an X server; returned from
6422 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6424 % o windows: Specifies a pointer to a XWindows structure.
6426 % o command: Specifies a command to perform.
6428 % o image: the image; XImageCache may transform the image and return a new
6431 % o exception: return any errors or warnings in this structure.
6434 static void XImageCache(Display *display,XResourceInfo *resource_info,
6435 XWindows *windows,const CommandType command,Image **image,
6436 ExceptionInfo *exception)
6442 *redo_image = (Image *) NULL,
6443 *undo_image = (Image *) NULL;
6447 case FreeBuffersCommand:
6450 Free memory from the undo and redo cache.
6452 while (undo_image != (Image *) NULL)
6454 cache_image=undo_image;
6455 undo_image=GetPreviousImageInList(undo_image);
6456 cache_image->list=DestroyImage(cache_image->list);
6457 cache_image=DestroyImage(cache_image);
6459 undo_image=NewImageList();
6460 if (redo_image != (Image *) NULL)
6461 redo_image=DestroyImage(redo_image);
6462 redo_image=NewImageList();
6468 image_geometry[MaxTextExtent];
6471 Undo the last image transformation.
6473 if (undo_image == (Image *) NULL)
6475 (void) XBell(display,0);
6478 cache_image=undo_image;
6479 undo_image=GetPreviousImageInList(undo_image);
6480 windows->image.window_changes.width=(int) cache_image->columns;
6481 windows->image.window_changes.height=(int) cache_image->rows;
6482 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6483 windows->image.ximage->width,windows->image.ximage->height);
6484 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6486 if (windows->image.crop_geometry != (char *) NULL)
6487 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6488 windows->image.crop_geometry);
6489 windows->image.crop_geometry=cache_image->geometry;
6490 if (redo_image != (Image *) NULL)
6491 redo_image=DestroyImage(redo_image);
6492 redo_image=(*image);
6493 *image=cache_image->list;
6494 cache_image=DestroyImage(cache_image);
6495 if (windows->image.orphan != MagickFalse)
6497 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6498 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6504 case HalfSizeCommand:
6505 case OriginalSizeCommand:
6506 case DoubleSizeCommand:
6513 case RotateRightCommand:
6514 case RotateLeftCommand:
6519 case ContrastStretchCommand:
6520 case SigmoidalContrastCommand:
6521 case NormalizeCommand:
6522 case EqualizeCommand:
6524 case SaturationCommand:
6525 case BrightnessCommand:
6529 case GrayscaleCommand:
6531 case QuantizeCommand:
6532 case DespeckleCommand:
6534 case ReduceNoiseCommand:
6535 case AddNoiseCommand:
6536 case SharpenCommand:
6538 case ThresholdCommand:
6539 case EdgeDetectCommand:
6543 case SegmentCommand:
6544 case SolarizeCommand:
6545 case SepiaToneCommand:
6547 case ImplodeCommand:
6548 case VignetteCommand:
6550 case OilPaintCommand:
6551 case CharcoalDrawCommand:
6552 case AnnotateCommand:
6553 case AddBorderCommand:
6554 case AddFrameCommand:
6555 case CompositeCommand:
6556 case CommentCommand:
6558 case RegionofInterestCommand:
6559 case SaveToUndoBufferCommand:
6568 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6569 if (undo_image != (Image *) NULL)
6572 Ensure the undo cache has enough memory available.
6574 previous_image=undo_image;
6575 while (previous_image != (Image *) NULL)
6577 bytes+=previous_image->list->columns*previous_image->list->rows*
6579 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6581 previous_image=GetPreviousImageInList(previous_image);
6584 bytes-=previous_image->list->columns*previous_image->list->rows*
6586 if (previous_image == undo_image)
6587 undo_image=NewImageList();
6589 previous_image->next->previous=NewImageList();
6592 while (previous_image != (Image *) NULL)
6595 Delete any excess memory from undo cache.
6597 cache_image=previous_image;
6598 previous_image=GetPreviousImageInList(previous_image);
6599 cache_image->list=DestroyImage(cache_image->list);
6600 cache_image=DestroyImage(cache_image);
6603 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6606 Save image before transformations are applied.
6608 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6609 if (cache_image == (Image *) NULL)
6611 XSetCursorState(display,windows,MagickTrue);
6612 XCheckRefreshWindows(display,windows);
6613 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6614 XSetCursorState(display,windows,MagickFalse);
6615 if (cache_image->list == (Image *) NULL)
6617 cache_image=DestroyImage(cache_image);
6620 cache_image->columns=(size_t) windows->image.ximage->width;
6621 cache_image->rows=(size_t) windows->image.ximage->height;
6622 cache_image->geometry=windows->image.crop_geometry;
6623 if (windows->image.crop_geometry != (char *) NULL)
6625 cache_image->geometry=AcquireString((char *) NULL);
6626 (void) CopyMagickString(cache_image->geometry,
6627 windows->image.crop_geometry,MaxTextExtent);
6629 if (undo_image == (Image *) NULL)
6631 undo_image=cache_image;
6634 undo_image->next=cache_image;
6635 undo_image->next->previous=undo_image;
6636 undo_image=undo_image->next;
6642 if (command == RedoCommand)
6645 Redo the last image transformation.
6647 if (redo_image == (Image *) NULL)
6649 (void) XBell(display,0);
6652 windows->image.window_changes.width=(int) redo_image->columns;
6653 windows->image.window_changes.height=(int) redo_image->rows;
6654 if (windows->image.crop_geometry != (char *) NULL)
6655 windows->image.crop_geometry=(char *)
6656 RelinquishMagickMemory(windows->image.crop_geometry);
6657 windows->image.crop_geometry=redo_image->geometry;
6658 *image=DestroyImage(*image);
6660 redo_image=NewImageList();
6661 if (windows->image.orphan != MagickFalse)
6663 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6664 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6667 if (command != InfoCommand)
6672 XSetCursorState(display,windows,MagickTrue);
6673 XCheckRefreshWindows(display,windows);
6674 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6675 XSetCursorState(display,windows,MagickFalse);
6679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6683 + X I m a g e W i n d o w C o m m a n d %
6687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6689 % XImageWindowCommand() makes a transform to the image or Image window as
6690 % specified by a user menu button or keyboard command.
6692 % The format of the XImageWindowCommand method is:
6694 % CommandType XImageWindowCommand(Display *display,
6695 % XResourceInfo *resource_info,XWindows *windows,
6696 % const MagickStatusType state,KeySym key_symbol,Image **image,
6697 % ExceptionInfo *exception)
6699 % A description of each parameter follows:
6701 % o nexus: Method XImageWindowCommand returns an image when the
6702 % user chooses 'Open Image' from the command menu. Otherwise a null
6703 % image is returned.
6705 % o display: Specifies a connection to an X server; returned from
6708 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6710 % o windows: Specifies a pointer to a XWindows structure.
6712 % o state: key mask.
6714 % o key_symbol: Specifies a command to perform.
6716 % o image: the image; XImageWIndowCommand may transform the image and
6717 % return a new image pointer.
6719 % o exception: return any errors or warnings in this structure.
6722 static CommandType XImageWindowCommand(Display *display,
6723 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6724 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6727 delta[MaxTextExtent] = "";
6730 Digits[] = "01234567890";
6735 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6737 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6740 resource_info->quantum=1;
6742 last_symbol=key_symbol;
6743 delta[strlen(delta)+1]='\0';
6744 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6745 resource_info->quantum=StringToLong(delta);
6746 return(NullCommand);
6748 last_symbol=key_symbol;
6749 if (resource_info->immutable)
6752 Virtual image window has a restricted command set.
6757 return(InfoCommand);
6760 return(PrintCommand);
6762 return(NextCommand);
6765 return(QuitCommand);
6769 return(NullCommand);
6771 switch ((int) key_symbol)
6775 if ((state & ControlMask) == 0)
6777 return(OpenCommand);
6780 return(NextCommand);
6782 return(FormerCommand);
6785 if ((state & Mod1Mask) != 0)
6786 return(SwirlCommand);
6787 if ((state & ControlMask) == 0)
6788 return(ShearCommand);
6789 return(SaveCommand);
6794 if ((state & Mod1Mask) != 0)
6795 return(OilPaintCommand);
6796 if ((state & Mod4Mask) != 0)
6797 return(ColorCommand);
6798 if ((state & ControlMask) == 0)
6799 return(NullCommand);
6800 return(PrintCommand);
6804 if ((state & Mod4Mask) != 0)
6805 return(DrawCommand);
6806 if ((state & ControlMask) == 0)
6807 return(NullCommand);
6808 return(DeleteCommand);
6812 if ((state & ControlMask) == 0)
6813 return(NullCommand);
6814 return(SelectCommand);
6818 if ((state & ControlMask) == 0)
6819 return(NullCommand);
6824 return(QuitCommand);
6828 if ((state & ControlMask) == 0)
6829 return(NullCommand);
6830 return(UndoCommand);
6835 if ((state & ControlMask) == 0)
6836 return(RollCommand);
6837 return(RedoCommand);
6841 if ((state & ControlMask) == 0)
6842 return(NullCommand);
6847 if ((state & Mod1Mask) != 0)
6848 return(CharcoalDrawCommand);
6849 if ((state & ControlMask) == 0)
6850 return(CropCommand);
6851 return(CopyCommand);
6856 if ((state & Mod4Mask) != 0)
6857 return(CompositeCommand);
6858 if ((state & ControlMask) == 0)
6859 return(FlipCommand);
6860 return(PasteCommand);
6863 return(HalfSizeCommand);
6865 return(OriginalSizeCommand);
6867 return(DoubleSizeCommand);
6869 return(ResizeCommand);
6871 return(RefreshCommand);
6872 case XK_bracketleft:
6873 return(ChopCommand);
6875 return(FlopCommand);
6877 return(RotateRightCommand);
6879 return(RotateLeftCommand);
6881 return(RotateCommand);
6883 return(TrimCommand);
6887 return(SaturationCommand);
6889 return(BrightnessCommand);
6891 return(GammaCommand);
6893 return(SpiffCommand);
6895 return(DullCommand);
6897 return(NormalizeCommand);
6899 return(EqualizeCommand);
6901 return(NegateCommand);
6903 return(GrayscaleCommand);
6905 return(QuantizeCommand);
6907 return(DespeckleCommand);
6909 return(EmbossCommand);
6911 return(ReduceNoiseCommand);
6913 return(AddNoiseCommand);
6915 return(SharpenCommand);
6917 return(BlurCommand);
6919 return(ThresholdCommand);
6921 return(EdgeDetectCommand);
6923 return(SpreadCommand);
6925 return(ShadeCommand);
6927 return(RaiseCommand);
6929 return(SegmentCommand);
6932 if ((state & Mod1Mask) == 0)
6933 return(NullCommand);
6934 return(ImplodeCommand);
6938 if ((state & Mod1Mask) == 0)
6939 return(NullCommand);
6940 return(WaveCommand);
6944 if ((state & Mod4Mask) == 0)
6945 return(NullCommand);
6946 return(MatteCommand);
6950 if ((state & Mod4Mask) == 0)
6951 return(NullCommand);
6952 return(AddBorderCommand);
6956 if ((state & Mod4Mask) == 0)
6957 return(NullCommand);
6958 return(AddFrameCommand);
6962 if ((state & Mod4Mask) == 0)
6963 return(NullCommand);
6964 return(CommentCommand);
6968 if ((state & Mod1Mask) != 0)
6969 return(ApplyCommand);
6970 if ((state & Mod4Mask) != 0)
6971 return(AnnotateCommand);
6972 if ((state & ControlMask) == 0)
6973 return(NullCommand);
6974 return(RegionofInterestCommand);
6977 return(InfoCommand);
6979 return(ZoomCommand);
6982 if ((state & ShiftMask) == 0)
6983 return(NullCommand);
6984 return(ShowPreviewCommand);
6987 return(LaunchCommand);
6989 return(HelpCommand);
6991 return(BrowseDocumentationCommand);
6994 (void) XMapRaised(display,windows->command.id);
6995 return(NullCommand);
7002 XTranslateImage(display,windows,*image,key_symbol);
7003 return(NullCommand);
7014 if ((state & Mod1Mask) != 0)
7020 Trim one pixel from edge of image.
7024 crop_info.width=(size_t) windows->image.ximage->width;
7025 crop_info.height=(size_t) windows->image.ximage->height;
7026 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7028 if (resource_info->quantum >= (int) crop_info.height)
7029 resource_info->quantum=(int) crop_info.height-1;
7030 crop_info.height-=resource_info->quantum;
7032 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7034 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7035 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7036 crop_info.y+=resource_info->quantum;
7037 crop_info.height-=resource_info->quantum;
7039 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7041 if (resource_info->quantum >= (int) crop_info.width)
7042 resource_info->quantum=(int) crop_info.width-1;
7043 crop_info.width-=resource_info->quantum;
7045 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7047 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7048 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7049 crop_info.x+=resource_info->quantum;
7050 crop_info.width-=resource_info->quantum;
7052 if ((int) (windows->image.x+windows->image.width) >
7053 (int) crop_info.width)
7054 windows->image.x=(int) (crop_info.width-windows->image.width);
7055 if ((int) (windows->image.y+windows->image.height) >
7056 (int) crop_info.height)
7057 windows->image.y=(int) (crop_info.height-windows->image.height);
7058 XSetCropGeometry(display,windows,&crop_info,*image);
7059 windows->image.window_changes.width=(int) crop_info.width;
7060 windows->image.window_changes.height=(int) crop_info.height;
7061 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7062 (void) XConfigureImage(display,resource_info,windows,*image,
7064 return(NullCommand);
7066 XTranslateImage(display,windows,*image,key_symbol);
7067 return(NullCommand);
7070 return(NullCommand);
7072 return(NullCommand);
7076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7080 + X M a g i c k C o m m a n d %
7084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7086 % XMagickCommand() makes a transform to the image or Image window as
7087 % specified by a user menu button or keyboard command.
7089 % The format of the XMagickCommand method is:
7091 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7092 % XWindows *windows,const CommandType command,Image **image,
7093 % ExceptionInfo *exception)
7095 % A description of each parameter follows:
7097 % o display: Specifies a connection to an X server; returned from
7100 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7102 % o windows: Specifies a pointer to a XWindows structure.
7104 % o command: Specifies a command to perform.
7106 % o image: the image; XMagickCommand may transform the image and return a
7107 % new image pointer.
7109 % o exception: return any errors or warnings in this structure.
7112 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7113 XWindows *windows,const CommandType command,Image **image,
7114 ExceptionInfo *exception)
7117 filename[MaxTextExtent],
7118 geometry[MaxTextExtent],
7119 modulate_factors[MaxTextExtent];
7148 color[MaxTextExtent] = "gray";
7155 Process user command.
7157 XCheckRefreshWindows(display,windows);
7158 XImageCache(display,resource_info,windows,command,image,exception);
7159 nexus=NewImageList();
7160 windows->image.window_changes.width=windows->image.ximage->width;
7161 windows->image.window_changes.height=windows->image.ximage->height;
7162 image_info=CloneImageInfo(resource_info->image_info);
7163 SetGeometryInfo(&geometry_info);
7164 GetQuantizeInfo(&quantize_info);
7172 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7180 for (i=0; i < resource_info->quantum; i++)
7181 XClientMessage(display,windows->image.id,windows->im_protocols,
7182 windows->im_next_image,CurrentTime);
7188 Display former image.
7190 for (i=0; i < resource_info->quantum; i++)
7191 XClientMessage(display,windows->image.id,windows->im_protocols,
7192 windows->im_former_image,CurrentTime);
7203 status=chdir(resource_info->home_directory);
7205 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7206 "UnableToOpenFile","%s",resource_info->home_directory);
7207 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7215 status=XSaveImage(display,resource_info,windows,*image,exception);
7216 if (status == MagickFalse)
7219 message[MaxTextExtent];
7221 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7222 exception->reason != (char *) NULL ? exception->reason : "",
7223 exception->description != (char *) NULL ? exception->description :
7225 XNoticeWidget(display,windows,"Unable to save file:",message);
7235 status=XPrintImage(display,resource_info,windows,*image,exception);
7236 if (status == MagickFalse)
7239 message[MaxTextExtent];
7241 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7242 exception->reason != (char *) NULL ? exception->reason : "",
7243 exception->description != (char *) NULL ? exception->description :
7245 XNoticeWidget(display,windows,"Unable to print file:",message);
7253 filename[MaxTextExtent] = "\0";
7258 XFileBrowserWidget(display,windows,"Delete",filename);
7259 if (*filename == '\0')
7261 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
7262 if (status != MagickFalse)
7263 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7272 color[MaxTextExtent] = "gray",
7273 geometry[MaxTextExtent] = "640x480";
7276 *format = "gradient";
7279 Query user for canvas geometry.
7281 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7283 if (*geometry == '\0')
7287 XColorBrowserWidget(display,windows,"Select",color);
7293 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7294 "%s:%s",format,color);
7295 (void) CloneString(&image_info->size,geometry);
7296 nexus=ReadImage(image_info,exception);
7297 CatchException(exception);
7298 XClientMessage(display,windows->image.id,windows->im_protocols,
7299 windows->im_next_image,CurrentTime);
7302 case VisualDirectoryCommand:
7305 Visual Image directory.
7307 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7315 if (resource_info->confirm_exit == MagickFalse)
7316 XClientMessage(display,windows->image.id,windows->im_protocols,
7317 windows->im_exit,CurrentTime);
7324 Confirm program exit.
7326 status=XConfirmWidget(display,windows,"Do you really want to exit",
7327 resource_info->client_name);
7329 XClientMessage(display,windows->image.id,windows->im_protocols,
7330 windows->im_exit,CurrentTime);
7339 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7347 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7356 status=XPasteImage(display,resource_info,windows,*image,exception);
7357 if (status == MagickFalse)
7359 XNoticeWidget(display,windows,"Unable to paste X image",
7360 (*image)->filename);
7365 case HalfSizeCommand:
7370 windows->image.window_changes.width=windows->image.ximage->width/2;
7371 windows->image.window_changes.height=windows->image.ximage->height/2;
7372 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7375 case OriginalSizeCommand:
7378 Original image size.
7380 windows->image.window_changes.width=(int) (*image)->columns;
7381 windows->image.window_changes.height=(int) (*image)->rows;
7382 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7385 case DoubleSizeCommand:
7388 Double the image size.
7390 windows->image.window_changes.width=windows->image.ximage->width << 1;
7391 windows->image.window_changes.height=windows->image.ximage->height << 1;
7392 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7411 width=(size_t) windows->image.ximage->width;
7412 height=(size_t) windows->image.ximage->height;
7415 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7416 (double) width,(double) height);
7417 status=XDialogWidget(display,windows,"Resize",
7418 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7419 if (*geometry == '\0')
7422 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7423 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7424 windows->image.window_changes.width=(int) width;
7425 windows->image.window_changes.height=(int) height;
7426 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7432 image_geometry[MaxTextExtent];
7434 if ((windows->image.crop_geometry == (char *) NULL) &&
7435 ((int) (*image)->columns == windows->image.ximage->width) &&
7436 ((int) (*image)->rows == windows->image.ximage->height))
7439 Apply size transforms to image.
7441 XSetCursorState(display,windows,MagickTrue);
7442 XCheckRefreshWindows(display,windows);
7444 Crop and/or scale displayed image.
7446 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7447 windows->image.ximage->width,windows->image.ximage->height);
7448 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7450 if (windows->image.crop_geometry != (char *) NULL)
7451 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7452 windows->image.crop_geometry);
7455 XConfigureImageColormap(display,resource_info,windows,*image,exception);
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,exception);
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,exception);
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,exception);
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=StringToDoubleInterval(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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,
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,exception);
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,
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,exception);
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=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8309 (void) BilevelImage(*image,threshold,exception);
8310 XSetCursorState(display,windows,MagickFalse);
8311 if (windows->image.orphan != MagickFalse)
8313 XConfigureImageColormap(display,resource_info,windows,*image,exception);
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,exception);
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,exception);
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,exception);
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,exception);
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,sRGBColorspace,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,exception);
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=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
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,exception);
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=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8546 (void) SolarizeImage(*image,threshold,exception);
8547 XSetCursorState(display,windows,MagickFalse);
8548 if (windows->image.orphan != MagickFalse)
8550 XConfigureImageColormap(display,resource_info,windows,*image,exception);
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,exception);
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,exception);
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,0.0,(ssize_t)
8654 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
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,exception);
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,exception);
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,exception);
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,
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,exception);
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,exception);
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,exception);
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",exception);
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,exception);
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",exception);
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",exception);
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",exception);
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,
9329 % ExceptionInfo *exception)
9331 % A description of each parameter follows:
9333 % o display: Specifies a connection to an X server; returned from
9336 % o windows: Specifies a pointer to a XWindows structure.
9338 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9339 % the entire image is refreshed.
9341 % o exception: return any errors or warnings in this structure.
9344 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9345 ExceptionInfo *exception)
9348 text[MaxTextExtent];
9358 Update magnified image until the mouse button is released.
9360 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9364 windows->magnify.x=(int) windows->image.x+x;
9365 windows->magnify.y=(int) windows->image.y+y;
9369 Map and unmap Info widget as text cursor crosses its boundaries.
9371 if (windows->info.mapped != MagickFalse)
9373 if ((x < (int) (windows->info.x+windows->info.width)) &&
9374 (y < (int) (windows->info.y+windows->info.height)))
9375 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9378 if ((x > (int) (windows->info.x+windows->info.width)) ||
9379 (y > (int) (windows->info.y+windows->info.height)))
9380 (void) XMapWindow(display,windows->info.id);
9381 if (windows->info.mapped != MagickFalse)
9384 Display pointer position.
9386 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9387 windows->magnify.x,windows->magnify.y);
9388 XInfoWidget(display,windows,text);
9391 Wait for next event.
9393 XScreenEvent(display,windows,event,exception);
9394 switch (event->type)
9401 User has finished magnifying image.
9420 Check boundary conditions.
9425 if (x >= (int) windows->image.width)
9426 x=(int) windows->image.width-1;
9430 if (y >= (int) windows->image.height)
9431 y=(int) windows->image.height-1;
9432 } while ((state & ExitState) == 0);
9434 Display magnified image.
9436 XSetCursorState(display,windows,MagickFalse);
9440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9444 + X M a g n i f y W i n d o w C o m m a n d %
9448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9450 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9451 % pixel as specified by the key symbol.
9453 % The format of the XMagnifyWindowCommand method is:
9455 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9456 % const MagickStatusType state,const KeySym key_symbol,
9457 % ExceptionInfo *exception)
9459 % A description of each parameter follows:
9461 % o display: Specifies a connection to an X server; returned from
9464 % o windows: Specifies a pointer to a XWindows structure.
9466 % o state: key mask.
9468 % o key_symbol: Specifies a KeySym which indicates which side of the image
9471 % o exception: return any errors or warnings in this structure.
9474 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9475 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9481 User specified a magnify factor or position.
9484 if ((state & Mod1Mask) != 0)
9486 switch ((int) key_symbol)
9490 (void) XWithdrawWindow(display,windows->magnify.id,
9491 windows->magnify.screen);
9497 windows->magnify.x=(int) windows->image.width/2;
9498 windows->magnify.y=(int) windows->image.height/2;
9504 if (windows->magnify.x > 0)
9505 windows->magnify.x-=quantum;
9511 if (windows->magnify.y > 0)
9512 windows->magnify.y-=quantum;
9518 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9519 windows->magnify.x+=quantum;
9525 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9526 windows->magnify.y+=quantum;
9540 windows->magnify.data=(key_symbol-XK_0);
9554 windows->magnify.data=(key_symbol-XK_KP_0);
9560 XMakeMagnifyImage(display,windows,exception);
9564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9568 + X M a k e P a n I m a g e %
9572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9574 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9577 % The format of the XMakePanImage method is:
9579 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9580 % XWindows *windows,Image *image,ExceptionInfo *exception)
9582 % A description of each parameter follows:
9584 % o display: Specifies a connection to an X server; returned from
9587 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9589 % o windows: Specifies a pointer to a XWindows structure.
9591 % o image: the image.
9593 % o exception: return any errors or warnings in this structure.
9596 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9597 XWindows *windows,Image *image,ExceptionInfo *exception)
9603 Create and display image for panning icon.
9605 XSetCursorState(display,windows,MagickTrue);
9606 XCheckRefreshWindows(display,windows);
9607 windows->pan.x=(int) windows->image.x;
9608 windows->pan.y=(int) windows->image.y;
9609 status=XMakeImage(display,resource_info,&windows->pan,image,
9610 windows->pan.width,windows->pan.height,exception);
9611 if (status == MagickFalse)
9612 ThrowXWindowFatalException(ResourceLimitError,
9613 "MemoryAllocationFailed",image->filename);
9614 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9615 windows->pan.pixmap);
9616 (void) XClearWindow(display,windows->pan.id);
9617 XDrawPanRectangle(display,windows);
9618 XSetCursorState(display,windows,MagickFalse);
9622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9626 + X M a t t a E d i t I m a g e %
9630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9632 % XMatteEditImage() allows the user to interactively change the Matte channel
9633 % of an image. If the image is PseudoClass it is promoted to DirectClass
9634 % before the matte information is stored.
9636 % The format of the XMatteEditImage method is:
9638 % MagickBooleanType XMatteEditImage(Display *display,
9639 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9640 % ExceptionInfo *exception)
9642 % A description of each parameter follows:
9644 % o display: Specifies a connection to an X server; returned from
9647 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9649 % o windows: Specifies a pointer to a XWindows structure.
9651 % o image: the image; returned from ReadImage.
9653 % o exception: return any errors or warnings in this structure.
9656 static MagickBooleanType XMatteEditImage(Display *display,
9657 XResourceInfo *resource_info,XWindows *windows,Image **image,
9658 ExceptionInfo *exception)
9661 matte[MaxTextExtent] = "0";
9676 static const ModeType
9677 MatteEditCommands[] =
9680 MatteEditBorderCommand,
9681 MatteEditFuzzCommand,
9682 MatteEditValueCommand,
9683 MatteEditUndoCommand,
9684 MatteEditHelpCommand,
9685 MatteEditDismissCommand
9689 method = PointMethod;
9692 border_color = { 0, 0, 0, 0, 0, 0 };
9695 command[MaxTextExtent],
9696 text[MaxTextExtent];
9728 (void) CloneString(&windows->command.name,"Matte Edit");
9729 windows->command.data=4;
9730 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9731 (void) XMapRaised(display,windows->command.id);
9732 XClientMessage(display,windows->image.id,windows->im_protocols,
9733 windows->im_update_widget,CurrentTime);
9737 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9738 resource_info->background_color,resource_info->foreground_color);
9739 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9741 Track pointer until button 1 is pressed.
9743 XQueryPosition(display,windows->image.id,&x,&y);
9744 (void) XSelectInput(display,windows->image.id,
9745 windows->image.attributes.event_mask | PointerMotionMask);
9749 if (windows->info.mapped != MagickFalse)
9752 Display pointer position.
9754 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9755 x+windows->image.x,y+windows->image.y);
9756 XInfoWidget(display,windows,text);
9759 Wait for next event.
9761 XScreenEvent(display,windows,&event,exception);
9762 if (event.xany.window == windows->command.id)
9765 Select a command from the Command widget.
9767 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9770 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9773 switch (MatteEditCommands[id])
9775 case MatteEditMethod:
9781 Select a method from the pop-up menu.
9783 methods=GetCommandOptions(MagickMethodOptions);
9784 if (methods == (char **) NULL)
9786 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9787 (const char **) methods,command);
9789 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9790 MagickFalse,methods[entry]);
9791 methods=DestroyStringList(methods);
9794 case MatteEditBorderCommand:
9797 *ColorMenu[MaxNumberPens];
9803 Initialize menu selections.
9805 for (i=0; i < (int) (MaxNumberPens-2); i++)
9806 ColorMenu[i]=resource_info->pen_colors[i];
9807 ColorMenu[MaxNumberPens-2]="Browser...";
9808 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9810 Select a pen color from the pop-up menu.
9812 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9813 (const char **) ColorMenu,command);
9816 if (pen_number == (MaxNumberPens-2))
9819 color_name[MaxTextExtent] = "gray";
9822 Select a pen color from a dialog.
9824 resource_info->pen_colors[pen_number]=color_name;
9825 XColorBrowserWidget(display,windows,"Select",color_name);
9826 if (*color_name == '\0')
9832 (void) XParseColor(display,windows->map_info->colormap,
9833 resource_info->pen_colors[pen_number],&border_color);
9836 case MatteEditFuzzCommand:
9839 fuzz[MaxTextExtent];
9854 Select a command from the pop-up menu.
9856 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9862 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9866 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9867 (void) XDialogWidget(display,windows,"Ok",
9868 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9871 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9872 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9876 case MatteEditValueCommand:
9879 message[MaxTextExtent];
9891 Select a command from the pop-up menu.
9893 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9899 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9901 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9902 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9903 (Quantum) TransparentAlpha);
9906 (void) FormatLocaleString(message,MaxTextExtent,
9907 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9909 (void) XDialogWidget(display,windows,"Matte",message,matte);
9914 case MatteEditUndoCommand:
9916 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9920 case MatteEditHelpCommand:
9922 XTextViewWidget(display,resource_info,windows,MagickFalse,
9923 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9926 case MatteEditDismissCommand:
9938 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9945 if (event.xbutton.button != Button1)
9947 if ((event.xbutton.window != windows->image.id) &&
9948 (event.xbutton.window != windows->magnify.id))
9955 (void) XMagickCommand(display,resource_info,windows,
9956 SaveToUndoBufferCommand,image,exception);
9957 state|=UpdateConfigurationState;
9962 if (event.xbutton.button != Button1)
9964 if ((event.xbutton.window != windows->image.id) &&
9965 (event.xbutton.window != windows->magnify.id))
9968 Update colormap information.
9972 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9973 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9974 XInfoWidget(display,windows,text);
9975 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9976 state&=(~UpdateConfigurationState);
9984 command[MaxTextExtent];
9989 if (event.xkey.window == windows->magnify.id)
9994 window=windows->magnify.id;
9995 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
9997 if (event.xkey.window != windows->image.id)
10000 Respond to a user key press.
10002 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10003 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10004 switch ((int) key_symbol)
10018 XTextViewWidget(display,resource_info,windows,MagickFalse,
10019 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10024 (void) XBell(display,0);
10033 Map and unmap Info widget as cursor crosses its boundaries.
10037 if (windows->info.mapped != MagickFalse)
10039 if ((x < (int) (windows->info.x+windows->info.width)) &&
10040 (y < (int) (windows->info.y+windows->info.height)))
10041 (void) XWithdrawWindow(display,windows->info.id,
10042 windows->info.screen);
10045 if ((x > (int) (windows->info.x+windows->info.width)) ||
10046 (y > (int) (windows->info.y+windows->info.height)))
10047 (void) XMapWindow(display,windows->info.id);
10053 if (event.xany.window == windows->magnify.id)
10055 x=windows->magnify.x-windows->image.x;
10056 y=windows->magnify.y-windows->image.y;
10060 if ((state & UpdateConfigurationState) != 0)
10070 Matte edit is relative to image configuration.
10072 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10074 XPutPixel(windows->image.ximage,x_offset,y_offset,
10075 windows->pixel_info->background_color.pixel);
10076 width=(unsigned int) (*image)->columns;
10077 height=(unsigned int) (*image)->rows;
10080 if (windows->image.crop_geometry != (char *) NULL)
10081 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10083 x_offset=(int) (width*(windows->image.x+x_offset)/
10084 windows->image.ximage->width+x);
10085 y_offset=(int) (height*(windows->image.y+y_offset)/
10086 windows->image.ximage->height+y);
10087 if ((x_offset < 0) || (y_offset < 0))
10089 if ((x_offset >= (int) (*image)->columns) ||
10090 (y_offset >= (int) (*image)->rows))
10092 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10093 return(MagickFalse);
10094 if ((*image)->matte == MagickFalse)
10095 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10096 image_view=AcquireAuthenticCacheView(*image,exception);
10103 Update matte information using point algorithm.
10105 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10106 (ssize_t) y_offset,1,1,exception);
10107 if (q == (Quantum *) NULL)
10109 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10110 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10113 case ReplaceMethod:
10120 Update matte information using replace algorithm.
10122 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
10123 x_offset,(ssize_t) y_offset,&target,exception);
10124 for (y=0; y < (int) (*image)->rows; y++)
10126 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10127 (*image)->columns,1,exception);
10128 if (q == (Quantum *) NULL)
10130 for (x=0; x < (int) (*image)->columns; x++)
10132 GetPixelInfoPixel(*image,q,&pixel);
10133 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10134 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10135 q+=GetPixelChannels(*image);
10137 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10142 case FloodfillMethod:
10143 case FillToBorderMethod:
10155 Update matte information using floodfill algorithm.
10157 (void) GetOneVirtualPixelInfo(*image,
10158 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10159 y_offset,&target,exception);
10160 if (method == FillToBorderMethod)
10162 target.red=(MagickRealType) ScaleShortToQuantum(
10164 target.green=(MagickRealType) ScaleShortToQuantum(
10165 border_color.green);
10166 target.blue=(MagickRealType) ScaleShortToQuantum(
10167 border_color.blue);
10169 draw_info=CloneDrawInfo(resource_info->image_info,
10170 (DrawInfo *) NULL);
10171 draw_info->fill.alpha=(MagickRealType) ClampToQuantum(
10172 StringToDouble(matte,(char **) NULL));
10173 channel_mask=SetPixelChannelMask(*image,AlphaChannel);
10174 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10175 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
10176 MagickFalse : MagickTrue,exception);
10177 (void) SetPixelChannelMapMask(*image,channel_mask);
10178 draw_info=DestroyDrawInfo(draw_info);
10184 Update matte information using reset algorithm.
10186 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10187 return(MagickFalse);
10188 for (y=0; y < (int) (*image)->rows; y++)
10190 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10191 (*image)->columns,1,exception);
10192 if (q == (Quantum *) NULL)
10194 for (x=0; x < (int) (*image)->columns; x++)
10196 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10197 q+=GetPixelChannels(*image);
10199 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10202 if (StringToLong(matte) == (long) OpaqueAlpha)
10203 (*image)->matte=MagickFalse;
10207 image_view=DestroyCacheView(image_view);
10208 state&=(~UpdateConfigurationState);
10210 } while ((state & ExitState) == 0);
10211 (void) XSelectInput(display,windows->image.id,
10212 windows->image.attributes.event_mask);
10213 XSetCursorState(display,windows,MagickFalse);
10214 (void) XFreeCursor(display,cursor);
10215 return(MagickTrue);
10219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10223 + X O p e n I m a g e %
10227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10229 % XOpenImage() loads an image from a file.
10231 % The format of the XOpenImage method is:
10233 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10234 % XWindows *windows,const unsigned int command)
10236 % A description of each parameter follows:
10238 % o display: Specifies a connection to an X server; returned from
10241 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10243 % o windows: Specifies a pointer to a XWindows structure.
10245 % o command: A value other than zero indicates that the file is selected
10246 % from the command line argument list.
10249 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10250 XWindows *windows,const MagickBooleanType command)
10265 filename[MaxTextExtent] = "\0";
10268 Request file name from user.
10270 if (command == MagickFalse)
10271 XFileBrowserWidget(display,windows,"Open",filename);
10287 Select next image from the command line.
10289 status=XGetCommand(display,windows->image.id,&files,&count);
10292 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10293 return((Image *) NULL);
10295 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10296 if (filelist == (char **) NULL)
10298 ThrowXWindowFatalException(ResourceLimitError,
10299 "MemoryAllocationFailed","...");
10300 (void) XFreeStringList(files);
10301 return((Image *) NULL);
10304 for (i=1; i < count; i++)
10305 if (*files[i] != '-')
10306 filelist[j++]=files[i];
10307 filelist[j]=(char *) NULL;
10308 XListBrowserWidget(display,windows,&windows->widget,
10309 (const char **) filelist,"Load","Select Image to Load:",filename);
10310 filelist=(char **) RelinquishMagickMemory(filelist);
10311 (void) XFreeStringList(files);
10313 if (*filename == '\0')
10314 return((Image *) NULL);
10315 image_info=CloneImageInfo(resource_info->image_info);
10316 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10318 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10319 exception=AcquireExceptionInfo();
10320 (void) SetImageInfo(image_info,0,exception);
10321 if (LocaleCompare(image_info->magick,"X") == 0)
10324 seconds[MaxTextExtent];
10327 User may want to delay the X server screen grab.
10329 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10330 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10332 if (*seconds == '\0')
10333 return((Image *) NULL);
10334 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10336 magick_info=GetMagickInfo(image_info->magick,exception);
10337 if ((magick_info != (const MagickInfo *) NULL) &&
10338 (magick_info->raw != MagickFalse))
10341 geometry[MaxTextExtent];
10344 Request image size from the user.
10346 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10347 if (image_info->size != (char *) NULL)
10348 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10349 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10351 (void) CloneString(&image_info->size,geometry);
10356 XSetCursorState(display,windows,MagickTrue);
10357 XCheckRefreshWindows(display,windows);
10358 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10359 nexus=ReadImage(image_info,exception);
10360 CatchException(exception);
10361 XSetCursorState(display,windows,MagickFalse);
10362 if (nexus != (Image *) NULL)
10363 XClientMessage(display,windows->image.id,windows->im_protocols,
10364 windows->im_next_image,CurrentTime);
10372 Unknown image format.
10374 text=FileToString(filename,~0,exception);
10375 if (text == (char *) NULL)
10376 return((Image *) NULL);
10377 textlist=StringToList(text);
10378 if (textlist != (char **) NULL)
10381 title[MaxTextExtent];
10386 (void) FormatLocaleString(title,MaxTextExtent,
10387 "Unknown format: %s",filename);
10388 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10389 (const char **) textlist);
10390 for (i=0; textlist[i] != (char *) NULL; i++)
10391 textlist[i]=DestroyString(textlist[i]);
10392 textlist=(char **) RelinquishMagickMemory(textlist);
10394 text=DestroyString(text);
10396 exception=DestroyExceptionInfo(exception);
10397 image_info=DestroyImageInfo(image_info);
10402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10406 + X P a n I m a g e %
10410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10412 % XPanImage() pans the image until the mouse button is released.
10414 % The format of the XPanImage method is:
10416 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10417 % ExceptionInfo *exception)
10419 % A description of each parameter follows:
10421 % o display: Specifies a connection to an X server; returned from
10424 % o windows: Specifies a pointer to a XWindows structure.
10426 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10427 % the entire image is refreshed.
10429 % o exception: return any errors or warnings in this structure.
10432 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10433 ExceptionInfo *exception)
10436 text[MaxTextExtent];
10454 if ((windows->image.ximage->width > (int) windows->image.width) &&
10455 (windows->image.ximage->height > (int) windows->image.height))
10456 cursor=XCreateFontCursor(display,XC_fleur);
10458 if (windows->image.ximage->width > (int) windows->image.width)
10459 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10461 if (windows->image.ximage->height > (int) windows->image.height)
10462 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10464 cursor=XCreateFontCursor(display,XC_arrow);
10465 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10467 Pan image as pointer moves until the mouse button is released.
10469 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10470 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10471 pan_info.width=windows->pan.width*windows->image.width/
10472 windows->image.ximage->width;
10473 pan_info.height=windows->pan.height*windows->image.height/
10474 windows->image.ximage->height;
10477 state=UpdateConfigurationState;
10480 switch (event->type)
10485 User choose an initial pan location.
10487 pan_info.x=(ssize_t) event->xbutton.x;
10488 pan_info.y=(ssize_t) event->xbutton.y;
10489 state|=UpdateConfigurationState;
10492 case ButtonRelease:
10495 User has finished panning the image.
10497 pan_info.x=(ssize_t) event->xbutton.x;
10498 pan_info.y=(ssize_t) event->xbutton.y;
10499 state|=UpdateConfigurationState | ExitState;
10504 pan_info.x=(ssize_t) event->xmotion.x;
10505 pan_info.y=(ssize_t) event->xmotion.y;
10506 state|=UpdateConfigurationState;
10511 if ((state & UpdateConfigurationState) != 0)
10514 Check boundary conditions.
10516 if (pan_info.x < (ssize_t) (pan_info.width/2))
10519 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10520 if (pan_info.x < 0)
10523 if ((int) (pan_info.x+windows->image.width) >
10524 windows->image.ximage->width)
10525 pan_info.x=(ssize_t)
10526 (windows->image.ximage->width-windows->image.width);
10527 if (pan_info.y < (ssize_t) (pan_info.height/2))
10530 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10531 if (pan_info.y < 0)
10534 if ((int) (pan_info.y+windows->image.height) >
10535 windows->image.ximage->height)
10536 pan_info.y=(ssize_t)
10537 (windows->image.ximage->height-windows->image.height);
10538 if ((windows->image.x != (int) pan_info.x) ||
10539 (windows->image.y != (int) pan_info.y))
10542 Display image pan offset.
10544 windows->image.x=(int) pan_info.x;
10545 windows->image.y=(int) pan_info.y;
10546 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10547 windows->image.width,windows->image.height,windows->image.x,
10549 XInfoWidget(display,windows,text);
10551 Refresh Image window.
10553 XDrawPanRectangle(display,windows);
10554 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10556 state&=(~UpdateConfigurationState);
10559 Wait for next event.
10561 if ((state & ExitState) == 0)
10562 XScreenEvent(display,windows,event,exception);
10563 } while ((state & ExitState) == 0);
10567 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10568 (void) XFreeCursor(display,cursor);
10569 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10577 + X P a s t e I m a g e %
10581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10583 % XPasteImage() pastes an image previously saved with XCropImage in the X
10584 % window image at a location the user chooses with the pointer.
10586 % The format of the XPasteImage method is:
10588 % MagickBooleanType XPasteImage(Display *display,
10589 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10590 % ExceptionInfo *exception)
10592 % A description of each parameter follows:
10594 % o display: Specifies a connection to an X server; returned from
10597 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10599 % o windows: Specifies a pointer to a XWindows structure.
10601 % o image: the image; returned from ReadImage.
10603 % o exception: return any errors or warnings in this structure.
10606 static MagickBooleanType XPasteImage(Display *display,
10607 XResourceInfo *resource_info,XWindows *windows,Image *image,
10608 ExceptionInfo *exception)
10619 static const ModeType
10622 PasteOperatorsCommand,
10624 PasteDismissCommand
10627 static CompositeOperator
10628 compose = CopyCompositeOp;
10631 text[MaxTextExtent];
10665 if (resource_info->copy_image == (Image *) NULL)
10666 return(MagickFalse);
10667 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10669 Map Command widget.
10671 (void) CloneString(&windows->command.name,"Paste");
10672 windows->command.data=1;
10673 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10674 (void) XMapRaised(display,windows->command.id);
10675 XClientMessage(display,windows->image.id,windows->im_protocols,
10676 windows->im_update_widget,CurrentTime);
10678 Track pointer until button 1 is pressed.
10680 XSetCursorState(display,windows,MagickFalse);
10681 XQueryPosition(display,windows->image.id,&x,&y);
10682 (void) XSelectInput(display,windows->image.id,
10683 windows->image.attributes.event_mask | PointerMotionMask);
10684 paste_info.x=(ssize_t) windows->image.x+x;
10685 paste_info.y=(ssize_t) windows->image.y+y;
10686 paste_info.width=0;
10687 paste_info.height=0;
10688 cursor=XCreateFontCursor(display,XC_ul_angle);
10689 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10690 state=DefaultState;
10693 if (windows->info.mapped != MagickFalse)
10696 Display pointer position.
10698 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10699 (long) paste_info.x,(long) paste_info.y);
10700 XInfoWidget(display,windows,text);
10702 highlight_info=paste_info;
10703 highlight_info.x=paste_info.x-windows->image.x;
10704 highlight_info.y=paste_info.y-windows->image.y;
10705 XHighlightRectangle(display,windows->image.id,
10706 windows->image.highlight_context,&highlight_info);
10708 Wait for next event.
10710 XScreenEvent(display,windows,&event,exception);
10711 XHighlightRectangle(display,windows->image.id,
10712 windows->image.highlight_context,&highlight_info);
10713 if (event.xany.window == windows->command.id)
10716 Select a command from the Command widget.
10718 id=XCommandWidget(display,windows,PasteMenu,&event);
10721 switch (PasteCommands[id])
10723 case PasteOperatorsCommand:
10726 command[MaxTextExtent],
10730 Select a command from the pop-up menu.
10732 operators=GetCommandOptions(MagickComposeOptions);
10733 if (operators == (char **) NULL)
10735 entry=XMenuWidget(display,windows,PasteMenu[id],
10736 (const char **) operators,command);
10738 compose=(CompositeOperator) ParseCommandOption(
10739 MagickComposeOptions,MagickFalse,operators[entry]);
10740 operators=DestroyStringList(operators);
10743 case PasteHelpCommand:
10745 XTextViewWidget(display,resource_info,windows,MagickFalse,
10746 "Help Viewer - Image Composite",ImagePasteHelp);
10749 case PasteDismissCommand:
10754 state|=EscapeState;
10763 switch (event.type)
10767 if (image->debug != MagickFalse)
10768 (void) LogMagickEvent(X11Event,GetMagickModule(),
10769 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10770 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10771 if (event.xbutton.button != Button1)
10773 if (event.xbutton.window != windows->image.id)
10776 Paste rectangle is relative to image configuration.
10778 width=(unsigned int) image->columns;
10779 height=(unsigned int) image->rows;
10782 if (windows->image.crop_geometry != (char *) NULL)
10783 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10785 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10786 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10787 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10788 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10789 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10790 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10791 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10794 case ButtonRelease:
10796 if (image->debug != MagickFalse)
10797 (void) LogMagickEvent(X11Event,GetMagickModule(),
10798 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10799 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10800 if (event.xbutton.button != Button1)
10802 if (event.xbutton.window != windows->image.id)
10804 if ((paste_info.width != 0) && (paste_info.height != 0))
10807 User has selected the location of the paste image.
10809 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10810 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10820 command[MaxTextExtent];
10828 if (event.xkey.window != windows->image.id)
10831 Respond to a user key press.
10833 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10834 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10835 *(command+length)='\0';
10836 if (image->debug != MagickFalse)
10837 (void) LogMagickEvent(X11Event,GetMagickModule(),
10838 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10839 switch ((int) key_symbol)
10847 paste_image=DestroyImage(paste_image);
10848 state|=EscapeState;
10855 (void) XSetFunction(display,windows->image.highlight_context,
10857 XTextViewWidget(display,resource_info,windows,MagickFalse,
10858 "Help Viewer - Image Composite",ImagePasteHelp);
10859 (void) XSetFunction(display,windows->image.highlight_context,
10865 (void) XBell(display,0);
10874 Map and unmap Info widget as text cursor crosses its boundaries.
10878 if (windows->info.mapped != MagickFalse)
10880 if ((x < (int) (windows->info.x+windows->info.width)) &&
10881 (y < (int) (windows->info.y+windows->info.height)))
10882 (void) XWithdrawWindow(display,windows->info.id,
10883 windows->info.screen);
10886 if ((x > (int) (windows->info.x+windows->info.width)) ||
10887 (y > (int) (windows->info.y+windows->info.height)))
10888 (void) XMapWindow(display,windows->info.id);
10889 paste_info.x=(ssize_t) windows->image.x+x;
10890 paste_info.y=(ssize_t) windows->image.y+y;
10895 if (image->debug != MagickFalse)
10896 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10901 } while ((state & ExitState) == 0);
10902 (void) XSelectInput(display,windows->image.id,
10903 windows->image.attributes.event_mask);
10904 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10905 XSetCursorState(display,windows,MagickFalse);
10906 (void) XFreeCursor(display,cursor);
10907 if ((state & EscapeState) != 0)
10908 return(MagickTrue);
10910 Image pasting is relative to image configuration.
10912 XSetCursorState(display,windows,MagickTrue);
10913 XCheckRefreshWindows(display,windows);
10914 width=(unsigned int) image->columns;
10915 height=(unsigned int) image->rows;
10918 if (windows->image.crop_geometry != (char *) NULL)
10919 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10920 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10922 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10923 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10924 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10926 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10927 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10929 Paste image with X Image window.
10931 (void) CompositeImage(image,paste_image,compose,MagickTrue,paste_info.x,
10932 paste_info.y,exception);
10933 paste_image=DestroyImage(paste_image);
10934 XSetCursorState(display,windows,MagickFalse);
10936 Update image colormap.
10938 XConfigureImageColormap(display,resource_info,windows,image,exception);
10939 (void) XConfigureImage(display,resource_info,windows,image,exception);
10940 return(MagickTrue);
10944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10948 + X P r i n t I m a g e %
10952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10954 % XPrintImage() prints an image to a Postscript printer.
10956 % The format of the XPrintImage method is:
10958 % MagickBooleanType XPrintImage(Display *display,
10959 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10960 % ExceptionInfo *exception)
10962 % A description of each parameter follows:
10964 % o display: Specifies a connection to an X server; returned from
10967 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10969 % o windows: Specifies a pointer to a XWindows structure.
10971 % o image: the image.
10973 % o exception: return any errors or warnings in this structure.
10976 static MagickBooleanType XPrintImage(Display *display,
10977 XResourceInfo *resource_info,XWindows *windows,Image *image,
10978 ExceptionInfo *exception)
10981 filename[MaxTextExtent],
10982 geometry[MaxTextExtent];
10994 Request Postscript page geometry from user.
10996 image_info=CloneImageInfo(resource_info->image_info);
10997 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
10998 if (image_info->page != (char *) NULL)
10999 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11000 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11001 "Select Postscript Page Geometry:",geometry);
11002 if (*geometry == '\0')
11003 return(MagickTrue);
11004 image_info->page=GetPageGeometry(geometry);
11006 Apply image transforms.
11008 XSetCursorState(display,windows,MagickTrue);
11009 XCheckRefreshWindows(display,windows);
11010 print_image=CloneImage(image,0,0,MagickTrue,exception);
11011 if (print_image == (Image *) NULL)
11012 return(MagickFalse);
11013 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11014 windows->image.ximage->width,windows->image.ximage->height);
11015 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11020 (void) AcquireUniqueFilename(filename);
11021 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11023 status=WriteImage(image_info,print_image,exception);
11024 (void) RelinquishUniqueFileResource(filename);
11025 print_image=DestroyImage(print_image);
11026 image_info=DestroyImageInfo(image_info);
11027 XSetCursorState(display,windows,MagickFalse);
11028 return(status != 0 ? MagickTrue : MagickFalse);
11032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11036 + X R O I I m a g e %
11040 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11042 % XROIImage() applies an image processing technique to a region of interest.
11044 % The format of the XROIImage method is:
11046 % MagickBooleanType XROIImage(Display *display,
11047 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11048 % ExceptionInfo *exception)
11050 % A description of each parameter follows:
11052 % o display: Specifies a connection to an X server; returned from
11055 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11057 % o windows: Specifies a pointer to a XWindows structure.
11059 % o image: the image; returned from ReadImage.
11061 % o exception: return any errors or warnings in this structure.
11064 static MagickBooleanType XROIImage(Display *display,
11065 XResourceInfo *resource_info,XWindows *windows,Image **image,
11066 ExceptionInfo *exception)
11068 #define ApplyMenus 7
11118 "Contrast Stretch...",
11119 "Sigmoidal Contrast...",
11153 "Charcoal Draw...",
11156 *MiscellanyMenu[] =
11167 **Menus[ApplyMenus] =
11178 static const CommandType
11201 TransformCommands[] =
11205 RotateRightCommand,
11208 EnhanceCommands[] =
11216 ContrastStretchCommand,
11217 SigmoidalContrastCommand,
11225 EffectsCommands[] =
11229 ReduceNoiseCommand,
11248 CharcoalDrawCommand
11250 MiscellanyCommands[] =
11254 ShowPreviewCommand,
11255 ShowHistogramCommand,
11264 static const CommandType
11265 *Commands[ApplyMenus] =
11277 command[MaxTextExtent],
11278 text[MaxTextExtent];
11298 MagickProgressMonitor
11317 Map Command widget.
11319 (void) CloneString(&windows->command.name,"ROI");
11320 windows->command.data=0;
11321 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11322 (void) XMapRaised(display,windows->command.id);
11323 XClientMessage(display,windows->image.id,windows->im_protocols,
11324 windows->im_update_widget,CurrentTime);
11326 Track pointer until button 1 is pressed.
11328 XQueryPosition(display,windows->image.id,&x,&y);
11329 (void) XSelectInput(display,windows->image.id,
11330 windows->image.attributes.event_mask | PointerMotionMask);
11331 roi_info.x=(ssize_t) windows->image.x+x;
11332 roi_info.y=(ssize_t) windows->image.y+y;
11335 cursor=XCreateFontCursor(display,XC_fleur);
11336 state=DefaultState;
11339 if (windows->info.mapped != MagickFalse)
11342 Display pointer position.
11344 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11345 (long) roi_info.x,(long) roi_info.y);
11346 XInfoWidget(display,windows,text);
11349 Wait for next event.
11351 XScreenEvent(display,windows,&event,exception);
11352 if (event.xany.window == windows->command.id)
11355 Select a command from the Command widget.
11357 id=XCommandWidget(display,windows,ROIMenu,&event);
11360 switch (ROICommands[id])
11362 case ROIHelpCommand:
11364 XTextViewWidget(display,resource_info,windows,MagickFalse,
11365 "Help Viewer - Region of Interest",ImageROIHelp);
11368 case ROIDismissCommand:
11373 state|=EscapeState;
11382 switch (event.type)
11386 if (event.xbutton.button != Button1)
11388 if (event.xbutton.window != windows->image.id)
11391 Note first corner of region of interest rectangle-- exit loop.
11393 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11394 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11395 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11399 case ButtonRelease:
11408 if (event.xkey.window != windows->image.id)
11411 Respond to a user key press.
11413 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11414 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11415 switch ((int) key_symbol)
11423 state|=EscapeState;
11430 XTextViewWidget(display,resource_info,windows,MagickFalse,
11431 "Help Viewer - Region of Interest",ImageROIHelp);
11436 (void) XBell(display,0);
11445 Map and unmap Info widget as text cursor crosses its boundaries.
11449 if (windows->info.mapped != MagickFalse)
11451 if ((x < (int) (windows->info.x+windows->info.width)) &&
11452 (y < (int) (windows->info.y+windows->info.height)))
11453 (void) XWithdrawWindow(display,windows->info.id,
11454 windows->info.screen);
11457 if ((x > (int) (windows->info.x+windows->info.width)) ||
11458 (y > (int) (windows->info.y+windows->info.height)))
11459 (void) XMapWindow(display,windows->info.id);
11460 roi_info.x=(ssize_t) windows->image.x+x;
11461 roi_info.y=(ssize_t) windows->image.y+y;
11467 } while ((state & ExitState) == 0);
11468 (void) XSelectInput(display,windows->image.id,
11469 windows->image.attributes.event_mask);
11470 if ((state & EscapeState) != 0)
11473 User want to exit without region of interest.
11475 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11476 (void) XFreeCursor(display,cursor);
11477 return(MagickTrue);
11479 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11483 Size rectangle as pointer moves until the mouse button is released.
11485 x=(int) roi_info.x;
11486 y=(int) roi_info.y;
11489 state=DefaultState;
11492 highlight_info=roi_info;
11493 highlight_info.x=roi_info.x-windows->image.x;
11494 highlight_info.y=roi_info.y-windows->image.y;
11495 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11498 Display info and draw region of interest rectangle.
11500 if (windows->info.mapped == MagickFalse)
11501 (void) XMapWindow(display,windows->info.id);
11502 (void) FormatLocaleString(text,MaxTextExtent,
11503 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11504 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11505 XInfoWidget(display,windows,text);
11506 XHighlightRectangle(display,windows->image.id,
11507 windows->image.highlight_context,&highlight_info);
11510 if (windows->info.mapped != MagickFalse)
11511 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11513 Wait for next event.
11515 XScreenEvent(display,windows,&event,exception);
11516 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11517 XHighlightRectangle(display,windows->image.id,
11518 windows->image.highlight_context,&highlight_info);
11519 switch (event.type)
11523 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11524 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11527 case ButtonRelease:
11530 User has committed to region of interest rectangle.
11532 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11533 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11534 XSetCursorState(display,windows,MagickFalse);
11536 if (LocaleCompare(windows->command.name,"Apply") == 0)
11538 (void) CloneString(&windows->command.name,"Apply");
11539 windows->command.data=ApplyMenus;
11540 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11547 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11548 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11553 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11554 ((state & ExitState) != 0))
11557 Check boundary conditions.
11559 if (roi_info.x < 0)
11562 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11563 roi_info.x=(ssize_t) windows->image.ximage->width;
11564 if ((int) roi_info.x < x)
11565 roi_info.width=(unsigned int) (x-roi_info.x);
11568 roi_info.width=(unsigned int) (roi_info.x-x);
11569 roi_info.x=(ssize_t) x;
11571 if (roi_info.y < 0)
11574 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11575 roi_info.y=(ssize_t) windows->image.ximage->height;
11576 if ((int) roi_info.y < y)
11577 roi_info.height=(unsigned int) (y-roi_info.y);
11580 roi_info.height=(unsigned int) (roi_info.y-y);
11581 roi_info.y=(ssize_t) y;
11584 } while ((state & ExitState) == 0);
11586 Wait for user to grab a corner of the rectangle or press return.
11588 state=DefaultState;
11589 command_type=NullCommand;
11590 (void) XMapWindow(display,windows->info.id);
11593 if (windows->info.mapped != MagickFalse)
11596 Display pointer position.
11598 (void) FormatLocaleString(text,MaxTextExtent,
11599 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11600 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11601 XInfoWidget(display,windows,text);
11603 highlight_info=roi_info;
11604 highlight_info.x=roi_info.x-windows->image.x;
11605 highlight_info.y=roi_info.y-windows->image.y;
11606 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11608 state|=EscapeState;
11612 if ((state & UpdateRegionState) != 0)
11614 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11615 switch (command_type)
11620 (void) XMagickCommand(display,resource_info,windows,command_type,
11627 Region of interest is relative to image configuration.
11629 progress_monitor=SetImageProgressMonitor(*image,
11630 (MagickProgressMonitor) NULL,(*image)->client_data);
11631 crop_info=roi_info;
11632 width=(unsigned int) (*image)->columns;
11633 height=(unsigned int) (*image)->rows;
11636 if (windows->image.crop_geometry != (char *) NULL)
11637 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11639 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11641 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11642 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11643 scale_factor=(MagickRealType)
11644 height/windows->image.ximage->height;
11646 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11647 crop_info.height=(unsigned int)
11648 (scale_factor*crop_info.height+0.5);
11649 roi_image=CropImage(*image,&crop_info,exception);
11650 (void) SetImageProgressMonitor(*image,progress_monitor,
11651 (*image)->client_data);
11652 if (roi_image == (Image *) NULL)
11655 Apply image processing technique to the region of interest.
11657 windows->image.orphan=MagickTrue;
11658 (void) XMagickCommand(display,resource_info,windows,command_type,
11659 &roi_image,exception);
11660 progress_monitor=SetImageProgressMonitor(*image,
11661 (MagickProgressMonitor) NULL,(*image)->client_data);
11662 (void) XMagickCommand(display,resource_info,windows,
11663 SaveToUndoBufferCommand,image,exception);
11664 windows->image.orphan=MagickFalse;
11665 (void) CompositeImage(*image,roi_image,CopyCompositeOp,
11666 MagickTrue,crop_info.x,crop_info.y,exception);
11667 roi_image=DestroyImage(roi_image);
11668 (void) SetImageProgressMonitor(*image,progress_monitor,
11669 (*image)->client_data);
11673 if (command_type != InfoCommand)
11675 XConfigureImageColormap(display,resource_info,windows,*image,
11677 (void) XConfigureImage(display,resource_info,windows,*image,
11680 XCheckRefreshWindows(display,windows);
11681 XInfoWidget(display,windows,text);
11682 (void) XSetFunction(display,windows->image.highlight_context,
11684 state&=(~UpdateRegionState);
11686 XHighlightRectangle(display,windows->image.id,
11687 windows->image.highlight_context,&highlight_info);
11688 XScreenEvent(display,windows,&event,exception);
11689 if (event.xany.window == windows->command.id)
11692 Select a command from the Command widget.
11694 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11695 command_type=NullCommand;
11696 id=XCommandWidget(display,windows,ApplyMenu,&event);
11699 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11700 command_type=ApplyCommands[id];
11701 if (id < ApplyMenus)
11704 Select a command from a pop-up menu.
11706 entry=XMenuWidget(display,windows,ApplyMenu[id],
11707 (const char **) Menus[id],command);
11710 (void) CopyMagickString(command,Menus[id][entry],
11712 command_type=Commands[id][entry];
11716 (void) XSetFunction(display,windows->image.highlight_context,
11718 XHighlightRectangle(display,windows->image.id,
11719 windows->image.highlight_context,&highlight_info);
11720 if (command_type == HelpCommand)
11722 (void) XSetFunction(display,windows->image.highlight_context,
11724 XTextViewWidget(display,resource_info,windows,MagickFalse,
11725 "Help Viewer - Region of Interest",ImageROIHelp);
11726 (void) XSetFunction(display,windows->image.highlight_context,
11730 if (command_type == QuitCommand)
11735 state|=EscapeState;
11739 if (command_type != NullCommand)
11740 state|=UpdateRegionState;
11743 XHighlightRectangle(display,windows->image.id,
11744 windows->image.highlight_context,&highlight_info);
11745 switch (event.type)
11749 x=windows->image.x;
11750 y=windows->image.y;
11751 if (event.xbutton.button != Button1)
11753 if (event.xbutton.window != windows->image.id)
11755 x=windows->image.x+event.xbutton.x;
11756 y=windows->image.y+event.xbutton.y;
11757 if ((x < (int) (roi_info.x+RoiDelta)) &&
11758 (x > (int) (roi_info.x-RoiDelta)) &&
11759 (y < (int) (roi_info.y+RoiDelta)) &&
11760 (y > (int) (roi_info.y-RoiDelta)))
11762 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11763 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11764 state|=UpdateConfigurationState;
11767 if ((x < (int) (roi_info.x+RoiDelta)) &&
11768 (x > (int) (roi_info.x-RoiDelta)) &&
11769 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11770 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11772 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11773 state|=UpdateConfigurationState;
11776 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11777 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11778 (y < (int) (roi_info.y+RoiDelta)) &&
11779 (y > (int) (roi_info.y-RoiDelta)))
11781 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11782 state|=UpdateConfigurationState;
11785 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11786 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11787 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11788 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11790 state|=UpdateConfigurationState;
11794 case ButtonRelease:
11796 if (event.xbutton.window == windows->pan.id)
11797 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11798 (highlight_info.y != crop_info.y-windows->image.y))
11799 XHighlightRectangle(display,windows->image.id,
11800 windows->image.highlight_context,&highlight_info);
11801 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11802 event.xbutton.time);
11807 if (event.xexpose.window == windows->image.id)
11808 if (event.xexpose.count == 0)
11810 event.xexpose.x=(int) highlight_info.x;
11811 event.xexpose.y=(int) highlight_info.y;
11812 event.xexpose.width=(int) highlight_info.width;
11813 event.xexpose.height=(int) highlight_info.height;
11814 XRefreshWindow(display,&windows->image,&event);
11816 if (event.xexpose.window == windows->info.id)
11817 if (event.xexpose.count == 0)
11818 XInfoWidget(display,windows,text);
11826 if (event.xkey.window != windows->image.id)
11829 Respond to a user key press.
11831 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11832 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11833 switch ((int) key_symbol)
11840 state|=EscapeState;
11849 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11850 roi_info.y=(ssize_t) (windows->image.height/2L-
11851 roi_info.height/2L);
11883 (void) XSetFunction(display,windows->image.highlight_context,
11885 XTextViewWidget(display,resource_info,windows,MagickFalse,
11886 "Help Viewer - Region of Interest",ImageROIHelp);
11887 (void) XSetFunction(display,windows->image.highlight_context,
11893 command_type=XImageWindowCommand(display,resource_info,windows,
11894 event.xkey.state,key_symbol,image,exception);
11895 if (command_type != NullCommand)
11896 state|=UpdateRegionState;
11900 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11908 if (event.xbutton.window != windows->image.id)
11911 Map and unmap Info widget as text cursor crosses its boundaries.
11915 if (windows->info.mapped != MagickFalse)
11917 if ((x < (int) (windows->info.x+windows->info.width)) &&
11918 (y < (int) (windows->info.y+windows->info.height)))
11919 (void) XWithdrawWindow(display,windows->info.id,
11920 windows->info.screen);
11923 if ((x > (int) (windows->info.x+windows->info.width)) ||
11924 (y > (int) (windows->info.y+windows->info.height)))
11925 (void) XMapWindow(display,windows->info.id);
11926 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11927 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11930 case SelectionRequest:
11935 XSelectionRequestEvent
11939 Set primary selection.
11941 (void) FormatLocaleString(text,MaxTextExtent,
11942 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11943 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11944 request=(&(event.xselectionrequest));
11945 (void) XChangeProperty(request->display,request->requestor,
11946 request->property,request->target,8,PropModeReplace,
11947 (unsigned char *) text,(int) strlen(text));
11948 notify.type=SelectionNotify;
11949 notify.display=request->display;
11950 notify.requestor=request->requestor;
11951 notify.selection=request->selection;
11952 notify.target=request->target;
11953 notify.time=request->time;
11954 if (request->property == None)
11955 notify.property=request->target;
11957 notify.property=request->property;
11958 (void) XSendEvent(request->display,request->requestor,False,0,
11959 (XEvent *) ¬ify);
11964 if ((state & UpdateConfigurationState) != 0)
11966 (void) XPutBackEvent(display,&event);
11967 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11970 } while ((state & ExitState) == 0);
11971 } while ((state & ExitState) == 0);
11972 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11973 XSetCursorState(display,windows,MagickFalse);
11974 if ((state & EscapeState) != 0)
11975 return(MagickTrue);
11976 return(MagickTrue);
11980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11984 + X R o t a t e I m a g e %
11988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11990 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11991 % rotation angle is computed from the slope of a line drawn by the user.
11993 % The format of the XRotateImage method is:
11995 % MagickBooleanType XRotateImage(Display *display,
11996 % XResourceInfo *resource_info,XWindows *windows,double degrees,
11997 % Image **image,ExceptionInfo *exception)
11999 % A description of each parameter follows:
12001 % o display: Specifies a connection to an X server; returned from
12004 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12006 % o windows: Specifies a pointer to a XWindows structure.
12008 % o degrees: Specifies the number of degrees to rotate the image.
12010 % o image: the image.
12012 % o exception: return any errors or warnings in this structure.
12015 static MagickBooleanType XRotateImage(Display *display,
12016 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12017 ExceptionInfo *exception)
12030 direction = HorizontalRotateCommand;
12032 static const ModeType
12033 DirectionCommands[] =
12035 HorizontalRotateCommand,
12036 VerticalRotateCommand
12040 RotateColorCommand,
12041 RotateDirectionCommand,
12043 RotateDismissCommand
12046 static unsigned int
12050 command[MaxTextExtent],
12051 text[MaxTextExtent];
12062 normalized_degrees;
12072 if (degrees == 0.0)
12087 Map Command widget.
12089 (void) CloneString(&windows->command.name,"Rotate");
12090 windows->command.data=2;
12091 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12092 (void) XMapRaised(display,windows->command.id);
12093 XClientMessage(display,windows->image.id,windows->im_protocols,
12094 windows->im_update_widget,CurrentTime);
12096 Wait for first button press.
12098 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12099 XQueryPosition(display,windows->image.id,&x,&y);
12104 state=DefaultState;
12107 XHighlightLine(display,windows->image.id,
12108 windows->image.highlight_context,&rotate_info);
12110 Wait for next event.
12112 XScreenEvent(display,windows,&event,exception);
12113 XHighlightLine(display,windows->image.id,
12114 windows->image.highlight_context,&rotate_info);
12115 if (event.xany.window == windows->command.id)
12118 Select a command from the Command widget.
12120 id=XCommandWidget(display,windows,RotateMenu,&event);
12123 (void) XSetFunction(display,windows->image.highlight_context,
12125 switch (RotateCommands[id])
12127 case RotateColorCommand:
12130 *ColorMenu[MaxNumberPens];
12139 Initialize menu selections.
12141 for (i=0; i < (int) (MaxNumberPens-2); i++)
12142 ColorMenu[i]=resource_info->pen_colors[i];
12143 ColorMenu[MaxNumberPens-2]="Browser...";
12144 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12146 Select a pen color from the pop-up menu.
12148 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12149 (const char **) ColorMenu,command);
12150 if (pen_number < 0)
12152 if (pen_number == (MaxNumberPens-2))
12155 color_name[MaxTextExtent] = "gray";
12158 Select a pen color from a dialog.
12160 resource_info->pen_colors[pen_number]=color_name;
12161 XColorBrowserWidget(display,windows,"Select",color_name);
12162 if (*color_name == '\0')
12168 (void) XParseColor(display,windows->map_info->colormap,
12169 resource_info->pen_colors[pen_number],&color);
12170 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12171 (unsigned int) MaxColors,&color);
12172 windows->pixel_info->pen_colors[pen_number]=color;
12173 pen_id=(unsigned int) pen_number;
12176 case RotateDirectionCommand:
12187 Select a command from the pop-up menu.
12189 id=XMenuWidget(display,windows,RotateMenu[id],
12190 Directions,command);
12192 direction=DirectionCommands[id];
12195 case RotateHelpCommand:
12197 XTextViewWidget(display,resource_info,windows,MagickFalse,
12198 "Help Viewer - Image Rotation",ImageRotateHelp);
12201 case RotateDismissCommand:
12206 state|=EscapeState;
12213 (void) XSetFunction(display,windows->image.highlight_context,
12217 switch (event.type)
12221 if (event.xbutton.button != Button1)
12223 if (event.xbutton.window != windows->image.id)
12228 (void) XSetFunction(display,windows->image.highlight_context,
12230 rotate_info.x1=event.xbutton.x;
12231 rotate_info.y1=event.xbutton.y;
12235 case ButtonRelease:
12242 command[MaxTextExtent];
12247 if (event.xkey.window != windows->image.id)
12250 Respond to a user key press.
12252 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12253 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12254 switch ((int) key_symbol)
12262 state|=EscapeState;
12269 (void) XSetFunction(display,windows->image.highlight_context,
12271 XTextViewWidget(display,resource_info,windows,MagickFalse,
12272 "Help Viewer - Image Rotation",ImageRotateHelp);
12273 (void) XSetFunction(display,windows->image.highlight_context,
12279 (void) XBell(display,0);
12287 rotate_info.x1=event.xmotion.x;
12288 rotate_info.y1=event.xmotion.y;
12291 rotate_info.x2=rotate_info.x1;
12292 rotate_info.y2=rotate_info.y1;
12293 if (direction == HorizontalRotateCommand)
12294 rotate_info.x2+=32;
12296 rotate_info.y2-=32;
12297 } while ((state & ExitState) == 0);
12298 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12299 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12300 if ((state & EscapeState) != 0)
12301 return(MagickTrue);
12303 Draw line as pointer moves until the mouse button is released.
12306 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12307 state=DefaultState;
12313 Display info and draw rotation line.
12315 if (windows->info.mapped == MagickFalse)
12316 (void) XMapWindow(display,windows->info.id);
12317 (void) FormatLocaleString(text,MaxTextExtent," %g",
12318 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12319 XInfoWidget(display,windows,text);
12320 XHighlightLine(display,windows->image.id,
12321 windows->image.highlight_context,&rotate_info);
12324 if (windows->info.mapped != MagickFalse)
12325 (void) XWithdrawWindow(display,windows->info.id,
12326 windows->info.screen);
12328 Wait for next event.
12330 XScreenEvent(display,windows,&event,exception);
12332 XHighlightLine(display,windows->image.id,
12333 windows->image.highlight_context,&rotate_info);
12334 switch (event.type)
12338 case ButtonRelease:
12341 User has committed to rotation line.
12343 rotate_info.x2=event.xbutton.x;
12344 rotate_info.y2=event.xbutton.y;
12352 rotate_info.x2=event.xmotion.x;
12353 rotate_info.y2=event.xmotion.y;
12359 Check boundary conditions.
12361 if (rotate_info.x2 < 0)
12364 if (rotate_info.x2 > (int) windows->image.width)
12365 rotate_info.x2=(short) windows->image.width;
12366 if (rotate_info.y2 < 0)
12369 if (rotate_info.y2 > (int) windows->image.height)
12370 rotate_info.y2=(short) windows->image.height;
12372 Compute rotation angle from the slope of the line.
12375 distance=(unsigned int)
12376 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12377 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12379 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12380 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12381 } while ((state & ExitState) == 0);
12382 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12383 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12385 return(MagickTrue);
12387 if (direction == VerticalRotateCommand)
12389 if (degrees == 0.0)
12390 return(MagickTrue);
12394 normalized_degrees=degrees;
12395 while (normalized_degrees < -45.0)
12396 normalized_degrees+=360.0;
12397 for (rotations=0; normalized_degrees > 45.0; rotations++)
12398 normalized_degrees-=90.0;
12399 if (normalized_degrees != 0.0)
12400 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12402 XSetCursorState(display,windows,MagickTrue);
12403 XCheckRefreshWindows(display,windows);
12404 (*image)->background_color.red=(double) ScaleShortToQuantum(
12405 windows->pixel_info->pen_colors[pen_id].red);
12406 (*image)->background_color.green=(double) ScaleShortToQuantum(
12407 windows->pixel_info->pen_colors[pen_id].green);
12408 (*image)->background_color.blue=(double) ScaleShortToQuantum(
12409 windows->pixel_info->pen_colors[pen_id].blue);
12410 rotate_image=RotateImage(*image,degrees,exception);
12411 XSetCursorState(display,windows,MagickFalse);
12412 if (rotate_image == (Image *) NULL)
12413 return(MagickFalse);
12414 *image=DestroyImage(*image);
12415 *image=rotate_image;
12416 if (windows->image.crop_geometry != (char *) NULL)
12419 Rotate crop geometry.
12421 width=(unsigned int) (*image)->columns;
12422 height=(unsigned int) (*image)->rows;
12423 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12424 switch (rotations % 4)
12434 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12435 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12442 Rotate 180 degrees.
12444 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12445 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12451 Rotate 270 degrees.
12453 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12454 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12459 if (windows->image.orphan != MagickFalse)
12460 return(MagickTrue);
12461 if (normalized_degrees != 0.0)
12464 Update image colormap.
12466 windows->image.window_changes.width=(int) (*image)->columns;
12467 windows->image.window_changes.height=(int) (*image)->rows;
12468 if (windows->image.crop_geometry != (char *) NULL)
12471 Obtain dimensions of image from crop geometry.
12473 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12475 windows->image.window_changes.width=(int) width;
12476 windows->image.window_changes.height=(int) height;
12478 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12481 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12483 windows->image.window_changes.width=windows->image.ximage->height;
12484 windows->image.window_changes.height=windows->image.ximage->width;
12487 Update image configuration.
12489 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12490 return(MagickTrue);
12494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12498 + X S a v e I m a g e %
12502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12504 % XSaveImage() saves an image to a file.
12506 % The format of the XSaveImage method is:
12508 % MagickBooleanType XSaveImage(Display *display,
12509 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12510 % ExceptionInfo *exception)
12512 % A description of each parameter follows:
12514 % o display: Specifies a connection to an X server; returned from
12517 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12519 % o windows: Specifies a pointer to a XWindows structure.
12521 % o image: the image.
12523 % o exception: return any errors or warnings in this structure.
12526 static MagickBooleanType XSaveImage(Display *display,
12527 XResourceInfo *resource_info,XWindows *windows,Image *image,
12528 ExceptionInfo *exception)
12531 filename[MaxTextExtent],
12532 geometry[MaxTextExtent];
12544 Request file name from user.
12546 if (resource_info->write_filename != (char *) NULL)
12547 (void) CopyMagickString(filename,resource_info->write_filename,
12552 path[MaxTextExtent];
12557 GetPathComponent(image->filename,HeadPath,path);
12558 GetPathComponent(image->filename,TailPath,filename);
12561 status=chdir(path);
12563 (void) ThrowMagickException(exception,GetMagickModule(),
12564 FileOpenError,"UnableToOpenFile","%s",path);
12567 XFileBrowserWidget(display,windows,"Save",filename);
12568 if (*filename == '\0')
12569 return(MagickTrue);
12570 if (IsPathAccessible(filename) != MagickFalse)
12576 File exists-- seek user's permission before overwriting.
12578 status=XConfirmWidget(display,windows,"Overwrite",filename);
12580 return(MagickTrue);
12582 image_info=CloneImageInfo(resource_info->image_info);
12583 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12584 (void) SetImageInfo(image_info,1,exception);
12585 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12586 (LocaleCompare(image_info->magick,"JPG") == 0))
12589 quality[MaxTextExtent];
12595 Request JPEG quality from user.
12597 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12599 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12601 if (*quality == '\0')
12602 return(MagickTrue);
12603 image->quality=StringToUnsignedLong(quality);
12604 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12606 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12607 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12608 (LocaleCompare(image_info->magick,"PS") == 0) ||
12609 (LocaleCompare(image_info->magick,"PS2") == 0))
12612 geometry[MaxTextExtent];
12615 Request page geometry from user.
12617 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12618 if (LocaleCompare(image_info->magick,"PDF") == 0)
12619 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12620 if (image_info->page != (char *) NULL)
12621 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12622 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12623 "Select page geometry:",geometry);
12624 if (*geometry != '\0')
12625 image_info->page=GetPageGeometry(geometry);
12628 Apply image transforms.
12630 XSetCursorState(display,windows,MagickTrue);
12631 XCheckRefreshWindows(display,windows);
12632 save_image=CloneImage(image,0,0,MagickTrue,exception);
12633 if (save_image == (Image *) NULL)
12634 return(MagickFalse);
12635 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12636 windows->image.ximage->width,windows->image.ximage->height);
12637 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12642 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12643 status=WriteImage(image_info,save_image,exception);
12644 if (status != MagickFalse)
12645 image->taint=MagickFalse;
12646 save_image=DestroyImage(save_image);
12647 image_info=DestroyImageInfo(image_info);
12648 XSetCursorState(display,windows,MagickFalse);
12649 return(status != 0 ? MagickTrue : MagickFalse);
12653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12657 + X S c r e e n E v e n t %
12661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12663 % XScreenEvent() handles global events associated with the Pan and Magnify
12666 % The format of the XScreenEvent function is:
12668 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12669 % ExceptionInfo *exception)
12671 % A description of each parameter follows:
12673 % o display: Specifies a pointer to the Display structure; returned from
12676 % o windows: Specifies a pointer to a XWindows structure.
12678 % o event: Specifies a pointer to a X11 XEvent structure.
12680 % o exception: return any errors or warnings in this structure.
12684 #if defined(__cplusplus) || defined(c_plusplus)
12688 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12693 windows=(XWindows *) data;
12694 if ((event->type == ClientMessage) &&
12695 (event->xclient.window == windows->image.id))
12696 return(MagickFalse);
12697 return(MagickTrue);
12700 #if defined(__cplusplus) || defined(c_plusplus)
12704 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12705 ExceptionInfo *exception)
12711 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12712 if (event->xany.window == windows->command.id)
12714 switch (event->type)
12717 case ButtonRelease:
12719 if ((event->xbutton.button == Button3) &&
12720 (event->xbutton.state & Mod1Mask))
12723 Convert Alt-Button3 to Button2.
12725 event->xbutton.button=Button2;
12726 event->xbutton.state&=(~Mod1Mask);
12728 if (event->xbutton.window == windows->backdrop.id)
12730 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12731 event->xbutton.time);
12734 if (event->xbutton.window == windows->pan.id)
12736 XPanImage(display,windows,event,exception);
12739 if (event->xbutton.window == windows->image.id)
12740 if (event->xbutton.button == Button2)
12743 Update magnified image.
12745 x=event->xbutton.x;
12746 y=event->xbutton.y;
12750 if (x >= (int) windows->image.width)
12751 x=(int) (windows->image.width-1);
12752 windows->magnify.x=(int) windows->image.x+x;
12756 if (y >= (int) windows->image.height)
12757 y=(int) (windows->image.height-1);
12758 windows->magnify.y=windows->image.y+y;
12759 if (windows->magnify.mapped == MagickFalse)
12760 (void) XMapRaised(display,windows->magnify.id);
12761 XMakeMagnifyImage(display,windows,exception);
12762 if (event->type == ButtonRelease)
12763 (void) XWithdrawWindow(display,windows->info.id,
12764 windows->info.screen);
12769 case ClientMessage:
12772 If client window delete message, exit.
12774 if (event->xclient.message_type != windows->wm_protocols)
12776 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12778 if (event->xclient.window == windows->magnify.id)
12780 (void) XWithdrawWindow(display,windows->magnify.id,
12781 windows->magnify.screen);
12786 case ConfigureNotify:
12788 if (event->xconfigure.window == windows->magnify.id)
12794 Magnify window has a new configuration.
12796 windows->magnify.width=(unsigned int) event->xconfigure.width;
12797 windows->magnify.height=(unsigned int) event->xconfigure.height;
12798 if (windows->magnify.mapped == MagickFalse)
12801 while ((int) magnify <= event->xconfigure.width)
12803 while ((int) magnify <= event->xconfigure.height)
12806 if (((int) magnify != event->xconfigure.width) ||
12807 ((int) magnify != event->xconfigure.height))
12812 window_changes.width=(int) magnify;
12813 window_changes.height=(int) magnify;
12814 (void) XReconfigureWMWindow(display,windows->magnify.id,
12815 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12819 XMakeMagnifyImage(display,windows,exception);
12826 if (event->xexpose.window == windows->image.id)
12828 XRefreshWindow(display,&windows->image,event);
12831 if (event->xexpose.window == windows->pan.id)
12832 if (event->xexpose.count == 0)
12834 XDrawPanRectangle(display,windows);
12837 if (event->xexpose.window == windows->magnify.id)
12838 if (event->xexpose.count == 0)
12840 XMakeMagnifyImage(display,windows,exception);
12848 command[MaxTextExtent];
12853 if (event->xkey.window != windows->magnify.id)
12856 Respond to a user key press.
12858 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12859 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12860 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12866 if (event->xmap.window == windows->magnify.id)
12868 windows->magnify.mapped=MagickTrue;
12869 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12872 if (event->xmap.window == windows->info.id)
12874 windows->info.mapped=MagickTrue;
12881 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12882 if (event->xmotion.window == windows->image.id)
12883 if (windows->magnify.mapped != MagickFalse)
12886 Update magnified image.
12888 x=event->xmotion.x;
12889 y=event->xmotion.y;
12893 if (x >= (int) windows->image.width)
12894 x=(int) (windows->image.width-1);
12895 windows->magnify.x=(int) windows->image.x+x;
12899 if (y >= (int) windows->image.height)
12900 y=(int) (windows->image.height-1);
12901 windows->magnify.y=windows->image.y+y;
12902 XMakeMagnifyImage(display,windows,exception);
12908 if (event->xunmap.window == windows->magnify.id)
12910 windows->magnify.mapped=MagickFalse;
12913 if (event->xunmap.window == windows->info.id)
12915 windows->info.mapped=MagickFalse;
12926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12930 + X S e t C r o p G e o m e t r y %
12934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12936 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12937 % and translates it to a cropping geometry relative to the image.
12939 % The format of the XSetCropGeometry method is:
12941 % void XSetCropGeometry(Display *display,XWindows *windows,
12942 % RectangleInfo *crop_info,Image *image)
12944 % A description of each parameter follows:
12946 % o display: Specifies a connection to an X server; returned from
12949 % o windows: Specifies a pointer to a XWindows structure.
12951 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12952 % Image window to crop.
12954 % o image: the image.
12957 static void XSetCropGeometry(Display *display,XWindows *windows,
12958 RectangleInfo *crop_info,Image *image)
12961 text[MaxTextExtent];
12974 if (windows->info.mapped != MagickFalse)
12977 Display info on cropping rectangle.
12979 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12980 (double) crop_info->width,(double) crop_info->height,(double)
12981 crop_info->x,(double) crop_info->y);
12982 XInfoWidget(display,windows,text);
12985 Cropping geometry is relative to any previous crop geometry.
12989 width=(unsigned int) image->columns;
12990 height=(unsigned int) image->rows;
12991 if (windows->image.crop_geometry != (char *) NULL)
12992 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12994 windows->image.crop_geometry=AcquireString((char *) NULL);
12996 Define the crop geometry string from the cropping rectangle.
12998 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12999 if (crop_info->x > 0)
13000 x+=(int) (scale_factor*crop_info->x+0.5);
13001 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13004 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13005 if (crop_info->y > 0)
13006 y+=(int) (scale_factor*crop_info->y+0.5);
13007 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13010 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13011 "%ux%u%+d%+d",width,height,x,y);
13015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13019 + X T i l e I m a g e %
13023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13025 % XTileImage() loads or deletes a selected tile from a visual image directory.
13026 % The load or delete command is chosen from a menu.
13028 % The format of the XTileImage method is:
13030 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13031 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13033 % A description of each parameter follows:
13035 % o tile_image: XTileImage reads or deletes the tile image
13036 % and returns it. A null image is returned if an error occurs.
13038 % o display: Specifies a connection to an X server; returned from
13041 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13043 % o windows: Specifies a pointer to a XWindows structure.
13045 % o image: the image; returned from ReadImage.
13047 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13048 % the entire image is refreshed.
13050 % o exception: return any errors or warnings in this structure.
13053 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13054 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13067 static const ModeType
13078 command[MaxTextExtent],
13079 filename[MaxTextExtent];
13106 Tile image is relative to montage image configuration.
13110 width=(unsigned int) image->columns;
13111 height=(unsigned int) image->rows;
13112 if (windows->image.crop_geometry != (char *) NULL)
13113 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13114 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13115 event->xbutton.x+=windows->image.x;
13116 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13117 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13118 event->xbutton.y+=windows->image.y;
13119 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13121 Determine size and location of each tile in the visual image directory.
13123 width=(unsigned int) image->columns;
13124 height=(unsigned int) image->rows;
13127 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13128 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13129 (event->xbutton.x-x)/width;
13133 Button press is outside any tile.
13135 (void) XBell(display,0);
13136 return((Image *) NULL);
13139 Determine file name from the tile directory.
13141 p=image->directory;
13142 for (i=tile; (i != 0) && (*p != '\0'); )
13151 Button press is outside any tile.
13153 (void) XBell(display,0);
13154 return((Image *) NULL);
13157 Select a command from the pop-up menu.
13159 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13161 return((Image *) NULL);
13163 while ((*q != '\n') && (*q != '\0'))
13165 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13167 Perform command for the selected tile.
13169 XSetCursorState(display,windows,MagickTrue);
13170 XCheckRefreshWindows(display,windows);
13171 tile_image=NewImageList();
13172 switch (TileCommands[id])
13174 case TileLoadCommand:
13179 XCheckRefreshWindows(display,windows);
13180 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13182 (void) CopyMagickString(resource_info->image_info->filename,filename,
13184 tile_image=ReadImage(resource_info->image_info,exception);
13185 CatchException(exception);
13186 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13189 case TileNextCommand:
13192 Display next image.
13194 XClientMessage(display,windows->image.id,windows->im_protocols,
13195 windows->im_next_image,CurrentTime);
13198 case TileFormerCommand:
13201 Display former image.
13203 XClientMessage(display,windows->image.id,windows->im_protocols,
13204 windows->im_former_image,CurrentTime);
13207 case TileDeleteCommand:
13212 if (IsPathAccessible(filename) == MagickFalse)
13214 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13217 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13220 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
13221 if (status != MagickFalse)
13223 XNoticeWidget(display,windows,"Unable to delete image file:",
13228 case TileUpdateCommand:
13244 Ensure all the images exist.
13247 GetPixelInfo(image,&pixel);
13248 for (p=image->directory; *p != '\0'; p++)
13254 while ((*q != '\n') && (*q != '\0'))
13256 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13258 if (IsPathAccessible(filename) != MagickFalse)
13264 Overwrite tile with background color.
13266 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13267 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13268 image_view=AcquireAuthenticCacheView(image,exception);
13269 (void) GetOneCacheViewVirtualPixelInfo(image_view,0,0,&pixel,exception);
13270 for (i=0; i < (int) height; i++)
13272 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13273 y_offset+i,width,1,exception);
13274 if (s == (Quantum *) NULL)
13276 for (j=0; j < (int) width; j++)
13278 SetPixelInfoPixel(image,&pixel,s);
13279 s+=GetPixelChannels(image);
13281 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13284 image_view=DestroyCacheView(image_view);
13287 windows->image.window_changes.width=(int) image->columns;
13288 windows->image.window_changes.height=(int) image->rows;
13289 XConfigureImageColormap(display,resource_info,windows,image,exception);
13290 (void) XConfigureImage(display,resource_info,windows,image,exception);
13296 XSetCursorState(display,windows,MagickFalse);
13297 return(tile_image);
13301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13305 + X T r a n s l a t e I m a g e %
13309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13311 % XTranslateImage() translates the image within an Image window by one pixel
13312 % as specified by the key symbol. If the image has a montage string the
13313 % translation is respect to the width and height contained within the string.
13315 % The format of the XTranslateImage method is:
13317 % void XTranslateImage(Display *display,XWindows *windows,
13318 % Image *image,const KeySym key_symbol)
13320 % A description of each parameter follows:
13322 % o display: Specifies a connection to an X server; returned from
13325 % o windows: Specifies a pointer to a XWindows structure.
13327 % o image: the image.
13329 % o key_symbol: Specifies a KeySym which indicates which side of the image
13333 static void XTranslateImage(Display *display,XWindows *windows,
13334 Image *image,const KeySym key_symbol)
13337 text[MaxTextExtent];
13348 User specified a pan position offset.
13350 x_offset=windows->image.width;
13351 y_offset=windows->image.height;
13352 if (image->montage != (char *) NULL)
13353 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13354 switch ((int) key_symbol)
13359 windows->image.x=(int) windows->image.width/2;
13360 windows->image.y=(int) windows->image.height/2;
13366 windows->image.x-=x_offset;
13373 windows->image.y-=y_offset;
13379 windows->image.x+=x_offset;
13386 windows->image.y+=y_offset;
13393 Check boundary conditions.
13395 if (windows->image.x < 0)
13396 windows->image.x=0;
13398 if ((int) (windows->image.x+windows->image.width) >
13399 windows->image.ximage->width)
13400 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13401 if (windows->image.y < 0)
13402 windows->image.y=0;
13404 if ((int) (windows->image.y+windows->image.height) >
13405 windows->image.ximage->height)
13406 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13408 Refresh Image window.
13410 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13411 windows->image.width,windows->image.height,windows->image.x,
13413 XInfoWidget(display,windows,text);
13414 XCheckRefreshWindows(display,windows);
13415 XDrawPanRectangle(display,windows);
13416 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13417 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13425 + X T r i m I m a g e %
13429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13431 % XTrimImage() trims the edges from the Image window.
13433 % The format of the XTrimImage method is:
13435 % MagickBooleanType XTrimImage(Display *display,
13436 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13437 % ExceptionInfo *exception)
13439 % A description of each parameter follows:
13441 % o display: Specifies a connection to an X server; returned from
13444 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13446 % o windows: Specifies a pointer to a XWindows structure.
13448 % o image: the image.
13450 % o exception: return any errors or warnings in this structure.
13453 static MagickBooleanType XTrimImage(Display *display,
13454 XResourceInfo *resource_info,XWindows *windows,Image *image,
13455 ExceptionInfo *exception)
13469 Trim edges from image.
13471 XSetCursorState(display,windows,MagickTrue);
13472 XCheckRefreshWindows(display,windows);
13474 Crop the left edge.
13476 background=XGetPixel(windows->image.ximage,0,0);
13477 trim_info.width=(size_t) windows->image.ximage->width;
13478 for (x=0; x < windows->image.ximage->width; x++)
13480 for (y=0; y < windows->image.ximage->height; y++)
13482 pixel=XGetPixel(windows->image.ximage,x,y);
13483 if (pixel != background)
13486 if (y < windows->image.ximage->height)
13489 trim_info.x=(ssize_t) x;
13490 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13492 XSetCursorState(display,windows,MagickFalse);
13493 return(MagickFalse);
13496 Crop the right edge.
13498 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13499 for (x=windows->image.ximage->width-1; x != 0; x--)
13501 for (y=0; y < windows->image.ximage->height; y++)
13503 pixel=XGetPixel(windows->image.ximage,x,y);
13504 if (pixel != background)
13507 if (y < windows->image.ximage->height)
13510 trim_info.width=(size_t) (x-trim_info.x+1);
13514 background=XGetPixel(windows->image.ximage,0,0);
13515 trim_info.height=(size_t) windows->image.ximage->height;
13516 for (y=0; y < windows->image.ximage->height; y++)
13518 for (x=0; x < windows->image.ximage->width; x++)
13520 pixel=XGetPixel(windows->image.ximage,x,y);
13521 if (pixel != background)
13524 if (x < windows->image.ximage->width)
13527 trim_info.y=(ssize_t) y;
13529 Crop the bottom edge.
13531 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13532 for (y=windows->image.ximage->height-1; y != 0; y--)
13534 for (x=0; x < windows->image.ximage->width; x++)
13536 pixel=XGetPixel(windows->image.ximage,x,y);
13537 if (pixel != background)
13540 if (x < windows->image.ximage->width)
13543 trim_info.height=(size_t) y-trim_info.y+1;
13544 if (((unsigned int) trim_info.width != windows->image.width) ||
13545 ((unsigned int) trim_info.height != windows->image.height))
13548 Reconfigure Image window as defined by the trimming rectangle.
13550 XSetCropGeometry(display,windows,&trim_info,image);
13551 windows->image.window_changes.width=(int) trim_info.width;
13552 windows->image.window_changes.height=(int) trim_info.height;
13553 (void) XConfigureImage(display,resource_info,windows,image,exception);
13555 XSetCursorState(display,windows,MagickFalse);
13556 return(MagickTrue);
13560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13564 + X V i s u a l D i r e c t o r y I m a g e %
13568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13570 % XVisualDirectoryImage() creates a Visual Image Directory.
13572 % The format of the XVisualDirectoryImage method is:
13574 % Image *XVisualDirectoryImage(Display *display,
13575 % XResourceInfo *resource_info,XWindows *windows,
13576 % ExceptionInfo *exception)
13578 % A description of each parameter follows:
13580 % o display: Specifies a connection to an X server; returned from
13583 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13585 % o windows: Specifies a pointer to a XWindows structure.
13587 % o exception: return any errors or warnings in this structure.
13590 static Image *XVisualDirectoryImage(Display *display,
13591 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13593 #define TileImageTag "Scale/Image"
13594 #define XClientName "montage"
13627 filename[MaxTextExtent] = "\0",
13628 filenames[MaxTextExtent] = "*";
13631 background_resources;
13634 Request file name from user.
13636 XFileBrowserWidget(display,windows,"Directory",filenames);
13637 if (*filenames == '\0')
13638 return((Image *) NULL);
13640 Expand the filenames.
13642 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13643 if (filelist == (char **) NULL)
13645 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13647 return((Image *) NULL);
13650 filelist[0]=filenames;
13651 status=ExpandFilenames(&number_files,&filelist);
13652 if ((status == MagickFalse) || (number_files == 0))
13654 if (number_files == 0)
13655 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13657 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13659 return((Image *) NULL);
13662 Set image background resources.
13664 background_resources=(*resource_info);
13665 background_resources.window_id=AcquireString("");
13666 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13667 "0x%lx",windows->image.id);
13668 background_resources.backdrop=MagickTrue;
13670 Read each image and convert them to a tile.
13672 backdrop=(windows->visual_info->klass == TrueColor) ||
13673 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13674 read_info=CloneImageInfo(resource_info->image_info);
13675 (void) SetImageOption(read_info,"jpeg:size","120x120");
13676 (void) CloneString(&read_info->size,DefaultTileGeometry);
13677 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13679 images=NewImageList();
13680 XSetCursorState(display,windows,MagickTrue);
13681 XCheckRefreshWindows(display,windows);
13682 for (i=0; i < (int) number_files; i++)
13684 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13685 filelist[i]=DestroyString(filelist[i]);
13686 *read_info->magick='\0';
13687 next_image=ReadImage(read_info,exception);
13688 CatchException(exception);
13689 if (next_image != (Image *) NULL)
13691 (void) DeleteImageProperty(next_image,"label");
13692 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13693 read_info,next_image,DefaultTileLabel,exception),exception);
13694 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13696 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13697 geometry.height,exception);
13698 if (thumbnail_image != (Image *) NULL)
13700 next_image=DestroyImage(next_image);
13701 next_image=thumbnail_image;
13705 (void) XDisplayBackgroundImage(display,&background_resources,
13706 next_image,exception);
13707 XSetCursorState(display,windows,MagickTrue);
13709 AppendImageToList(&images,next_image);
13710 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13715 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13716 (MagickSizeType) number_files);
13717 if (proceed == MagickFalse)
13722 filelist=(char **) RelinquishMagickMemory(filelist);
13723 if (images == (Image *) NULL)
13725 read_info=DestroyImageInfo(read_info);
13726 XSetCursorState(display,windows,MagickFalse);
13727 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13728 return((Image *) NULL);
13731 Create the Visual Image Directory.
13733 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13734 montage_info->pointsize=10;
13735 if (resource_info->font != (char *) NULL)
13736 (void) CloneString(&montage_info->font,resource_info->font);
13737 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13738 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13739 images),exception);
13740 images=DestroyImageList(images);
13741 montage_info=DestroyMontageInfo(montage_info);
13742 read_info=DestroyImageInfo(read_info);
13743 XSetCursorState(display,windows,MagickFalse);
13744 if (montage_image == (Image *) NULL)
13745 return(montage_image);
13746 XClientMessage(display,windows->image.id,windows->im_protocols,
13747 windows->im_next_image,CurrentTime);
13748 return(montage_image);
13752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13756 % X D i s p l a y B a c k g r o u n d I m a g e %
13760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13762 % XDisplayBackgroundImage() displays an image in the background of a window.
13764 % The format of the XDisplayBackgroundImage method is:
13766 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13767 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13769 % A description of each parameter follows:
13771 % o display: Specifies a connection to an X server; returned from
13774 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13776 % o image: the image.
13778 % o exception: return any errors or warnings in this structure.
13781 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13782 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13785 geometry[MaxTextExtent],
13786 visual_type[MaxTextExtent];
13799 static XStandardColormap
13803 *visual_info = (XVisualInfo *) NULL;
13824 Determine target window.
13826 assert(image != (Image *) NULL);
13827 assert(image->signature == MagickSignature);
13828 if (image->debug != MagickFalse)
13829 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13830 resources=(*resource_info);
13831 window_info.id=(Window) NULL;
13832 root_window=XRootWindow(display,XDefaultScreen(display));
13833 if (LocaleCompare(resources.window_id,"root") == 0)
13834 window_info.id=root_window;
13837 if (isdigit((unsigned char) *resources.window_id) != 0)
13838 window_info.id=XWindowByID(display,root_window,
13839 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13840 if (window_info.id == (Window) NULL)
13841 window_info.id=XWindowByName(display,root_window,resources.window_id);
13843 if (window_info.id == (Window) NULL)
13845 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13846 resources.window_id);
13847 return(MagickFalse);
13850 Determine window visual id.
13852 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13853 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13854 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13855 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13857 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13858 XVisualIDFromVisual(window_attributes.visual));
13859 if (visual_info == (XVisualInfo *) NULL)
13862 Allocate standard colormap.
13864 map_info=XAllocStandardColormap();
13865 if (map_info == (XStandardColormap *) NULL)
13866 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13868 map_info->colormap=(Colormap) NULL;
13869 pixel.pixels=(unsigned long *) NULL;
13871 Initialize visual info.
13873 resources.map_type=(char *) NULL;
13874 resources.visual_type=visual_type;
13875 visual_info=XBestVisualInfo(display,map_info,&resources);
13876 if (visual_info == (XVisualInfo *) NULL)
13877 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13878 resources.visual_type);
13880 Initialize window info.
13882 window_info.ximage=(XImage *) NULL;
13883 window_info.matte_image=(XImage *) NULL;
13884 window_info.pixmap=(Pixmap) NULL;
13885 window_info.matte_pixmap=(Pixmap) NULL;
13888 Free previous root colors.
13890 if (window_info.id == root_window)
13891 (void) XDestroyWindowColors(display,root_window);
13893 Initialize Standard Colormap.
13895 resources.colormap=SharedColormap;
13896 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13899 Graphic context superclass.
13901 context_values.background=pixel.background_color.pixel;
13902 context_values.foreground=pixel.foreground_color.pixel;
13903 pixel.annotate_context=XCreateGC(display,window_info.id,
13904 (size_t) (GCBackground | GCForeground),&context_values);
13905 if (pixel.annotate_context == (GC) NULL)
13906 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13909 Initialize Image window attributes.
13911 window_info.name=AcquireString("\0");
13912 window_info.icon_name=AcquireString("\0");
13913 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13914 &resources,&window_info);
13916 Create the X image.
13918 window_info.width=(unsigned int) image->columns;
13919 window_info.height=(unsigned int) image->rows;
13920 if ((image->columns != window_info.width) ||
13921 (image->rows != window_info.height))
13922 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13924 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13925 window_attributes.width,window_attributes.height);
13926 geometry_info.width=window_info.width;
13927 geometry_info.height=window_info.height;
13928 geometry_info.x=(ssize_t) window_info.x;
13929 geometry_info.y=(ssize_t) window_info.y;
13930 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13931 &geometry_info.width,&geometry_info.height);
13932 window_info.width=(unsigned int) geometry_info.width;
13933 window_info.height=(unsigned int) geometry_info.height;
13934 window_info.x=(int) geometry_info.x;
13935 window_info.y=(int) geometry_info.y;
13936 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13937 window_info.height,exception);
13938 if (status == MagickFalse)
13939 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13943 if (image->debug != MagickFalse)
13945 (void) LogMagickEvent(X11Event,GetMagickModule(),
13946 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13947 (double) image->columns,(double) image->rows);
13948 if (image->colors != 0)
13949 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13951 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13954 Adjust image dimensions as specified by backdrop or geometry options.
13956 width=(int) window_info.width;
13957 height=(int) window_info.height;
13958 if (resources.backdrop != MagickFalse)
13961 Center image on window.
13963 window_info.x=(window_attributes.width/2)-
13964 (window_info.ximage->width/2);
13965 window_info.y=(window_attributes.height/2)-
13966 (window_info.ximage->height/2);
13967 width=window_attributes.width;
13968 height=window_attributes.height;
13970 if ((resources.image_geometry != (char *) NULL) &&
13971 (*resources.image_geometry != '\0'))
13974 default_geometry[MaxTextExtent];
13984 User specified geometry.
13986 size_hints=XAllocSizeHints();
13987 if (size_hints == (XSizeHints *) NULL)
13988 ThrowXWindowFatalException(ResourceLimitFatalError,
13989 "MemoryAllocationFailed",image->filename);
13990 size_hints->flags=0L;
13991 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
13993 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13994 default_geometry,window_info.border_width,size_hints,&window_info.x,
13995 &window_info.y,&width,&height,&gravity);
13996 if (flags & (XValue | YValue))
13998 width=window_attributes.width;
13999 height=window_attributes.height;
14001 (void) XFree((void *) size_hints);
14004 Create the X pixmap.
14006 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14007 (unsigned int) height,window_info.depth);
14008 if (window_info.pixmap == (Pixmap) NULL)
14009 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14012 Display pixmap on the window.
14014 if (((unsigned int) width > window_info.width) ||
14015 ((unsigned int) height > window_info.height))
14016 (void) XFillRectangle(display,window_info.pixmap,
14017 window_info.annotate_context,0,0,(unsigned int) width,
14018 (unsigned int) height);
14019 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14020 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14021 window_info.width,(unsigned int) window_info.height);
14022 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14023 (void) XClearWindow(display,window_info.id);
14024 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14025 XDelay(display,delay == 0UL ? 10UL : delay);
14026 (void) XSync(display,MagickFalse);
14027 return(window_info.id == root_window ? MagickTrue : MagickFalse);
14031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14035 + X D i s p l a y I m a g e %
14039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14041 % XDisplayImage() displays an image via X11. A new image is created and
14042 % returned if the user interactively transforms the displayed image.
14044 % The format of the XDisplayImage method is:
14046 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14047 % char **argv,int argc,Image **image,size_t *state,
14048 % ExceptionInfo *exception)
14050 % A description of each parameter follows:
14052 % o nexus: Method XDisplayImage returns an image when the
14053 % user chooses 'Open Image' from the command menu or picks a tile
14054 % from the image directory. Otherwise a null image is returned.
14056 % o display: Specifies a connection to an X server; returned from
14059 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14061 % o argv: Specifies the application's argument list.
14063 % o argc: Specifies the number of arguments.
14065 % o image: Specifies an address to an address of an Image structure;
14067 % o exception: return any errors or warnings in this structure.
14070 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14071 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14073 #define MagnifySize 256 /* must be a power of 2 */
14074 #define MagickMenus 10
14075 #define MagickTitle "Commands"
14102 "Visual Directory...",
14148 "Contrast Stretch...",
14149 "Sigmoidal Contrast...",
14183 "Charcoal Draw...",
14197 "Region of Interest...",
14200 *MiscellanyMenu[] =
14215 "Browse Documentation",
14242 **Menus[MagickMenus] =
14280 VisualDirectoryCommand,
14294 OriginalSizeCommand,
14301 TransformCommands[] =
14307 RotateRightCommand,
14314 EnhanceCommands[] =
14322 ContrastStretchCommand,
14323 SigmoidalContrastCommand,
14331 EffectsCommands[] =
14335 ReduceNoiseCommand,
14355 CharcoalDrawCommand
14357 ImageEditCommands[] =
14368 RegionofInterestCommand
14370 MiscellanyCommands[] =
14374 ShowPreviewCommand,
14375 ShowHistogramCommand,
14384 BrowseDocumentationCommand,
14387 ShortCutsCommands[] =
14399 VirtualCommands[] =
14408 *Commands[MagickMenus] =
14418 MiscellanyCommands,
14423 command[MaxTextExtent],
14425 geometry[MaxTextExtent],
14426 resource_name[MaxTextExtent];
14453 working_directory[MaxTextExtent];
14459 *magick_windows[MaxXWindows];
14461 static unsigned int
14521 assert(image != (Image **) NULL);
14522 assert((*image)->signature == MagickSignature);
14523 if ((*image)->debug != MagickFalse)
14524 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14525 display_image=(*image);
14526 warning_handler=(WarningHandler) NULL;
14527 windows=XSetWindows((XWindows *) ~0);
14528 if (windows != (XWindows *) NULL)
14533 status=chdir(working_directory);
14535 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14536 "UnableToOpenFile","%s",working_directory);
14537 warning_handler=resource_info->display_warnings ?
14538 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14539 warning_handler=resource_info->display_warnings ?
14540 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14545 Allocate windows structure.
14547 resource_info->colors=display_image->colors;
14548 windows=XSetWindows(XInitializeWindows(display,resource_info));
14549 if (windows == (XWindows *) NULL)
14550 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14551 (*image)->filename);
14553 Initialize window id's.
14556 magick_windows[number_windows++]=(&windows->icon);
14557 magick_windows[number_windows++]=(&windows->backdrop);
14558 magick_windows[number_windows++]=(&windows->image);
14559 magick_windows[number_windows++]=(&windows->info);
14560 magick_windows[number_windows++]=(&windows->command);
14561 magick_windows[number_windows++]=(&windows->widget);
14562 magick_windows[number_windows++]=(&windows->popup);
14563 magick_windows[number_windows++]=(&windows->magnify);
14564 magick_windows[number_windows++]=(&windows->pan);
14565 for (i=0; i < (int) number_windows; i++)
14566 magick_windows[i]->id=(Window) NULL;
14571 Initialize font info.
14573 if (windows->font_info != (XFontStruct *) NULL)
14574 (void) XFreeFont(display,windows->font_info);
14575 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14576 if (windows->font_info == (XFontStruct *) NULL)
14577 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14578 resource_info->font);
14580 Initialize Standard Colormap.
14582 map_info=windows->map_info;
14583 icon_map=windows->icon_map;
14584 visual_info=windows->visual_info;
14585 icon_visual=windows->icon_visual;
14586 pixel=windows->pixel_info;
14587 icon_pixel=windows->icon_pixel;
14588 font_info=windows->font_info;
14589 icon_resources=windows->icon_resources;
14590 class_hints=windows->class_hints;
14591 manager_hints=windows->manager_hints;
14592 root_window=XRootWindow(display,visual_info->screen);
14593 nexus=NewImageList();
14594 if (display_image->debug != MagickFalse)
14596 (void) LogMagickEvent(X11Event,GetMagickModule(),
14597 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14598 (double) display_image->scene,(double) display_image->columns,
14599 (double) display_image->rows);
14600 if (display_image->colors != 0)
14601 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14602 display_image->colors);
14603 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14604 display_image->magick);
14606 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14607 map_info,pixel,exception);
14608 display_image->taint=MagickFalse;
14610 Initialize graphic context.
14612 windows->context.id=(Window) NULL;
14613 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14614 resource_info,&windows->context);
14615 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14616 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14617 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14618 manager_hints->flags=InputHint | StateHint;
14619 manager_hints->input=MagickFalse;
14620 manager_hints->initial_state=WithdrawnState;
14621 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14622 &windows->context);
14623 if (display_image->debug != MagickFalse)
14624 (void) LogMagickEvent(X11Event,GetMagickModule(),
14625 "Window id: 0x%lx (context)",windows->context.id);
14626 context_values.background=pixel->background_color.pixel;
14627 context_values.font=font_info->fid;
14628 context_values.foreground=pixel->foreground_color.pixel;
14629 context_values.graphics_exposures=MagickFalse;
14630 context_mask=(MagickStatusType)
14631 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14632 if (pixel->annotate_context != (GC) NULL)
14633 (void) XFreeGC(display,pixel->annotate_context);
14634 pixel->annotate_context=XCreateGC(display,windows->context.id,
14635 context_mask,&context_values);
14636 if (pixel->annotate_context == (GC) NULL)
14637 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14638 display_image->filename);
14639 context_values.background=pixel->depth_color.pixel;
14640 if (pixel->widget_context != (GC) NULL)
14641 (void) XFreeGC(display,pixel->widget_context);
14642 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14644 if (pixel->widget_context == (GC) NULL)
14645 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14646 display_image->filename);
14647 context_values.background=pixel->foreground_color.pixel;
14648 context_values.foreground=pixel->background_color.pixel;
14649 context_values.plane_mask=context_values.background ^
14650 context_values.foreground;
14651 if (pixel->highlight_context != (GC) NULL)
14652 (void) XFreeGC(display,pixel->highlight_context);
14653 pixel->highlight_context=XCreateGC(display,windows->context.id,
14654 (size_t) (context_mask | GCPlaneMask),&context_values);
14655 if (pixel->highlight_context == (GC) NULL)
14656 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14657 display_image->filename);
14658 (void) XDestroyWindow(display,windows->context.id);
14660 Initialize icon window.
14662 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14663 icon_resources,&windows->icon);
14664 windows->icon.geometry=resource_info->icon_geometry;
14665 XBestIconSize(display,&windows->icon,display_image);
14666 windows->icon.attributes.colormap=XDefaultColormap(display,
14667 icon_visual->screen);
14668 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14669 manager_hints->flags=InputHint | StateHint;
14670 manager_hints->input=MagickFalse;
14671 manager_hints->initial_state=IconicState;
14672 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14674 if (display_image->debug != MagickFalse)
14675 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14678 Initialize graphic context for icon window.
14680 if (icon_pixel->annotate_context != (GC) NULL)
14681 (void) XFreeGC(display,icon_pixel->annotate_context);
14682 context_values.background=icon_pixel->background_color.pixel;
14683 context_values.foreground=icon_pixel->foreground_color.pixel;
14684 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14685 (size_t) (GCBackground | GCForeground),&context_values);
14686 if (icon_pixel->annotate_context == (GC) NULL)
14687 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14688 display_image->filename);
14689 windows->icon.annotate_context=icon_pixel->annotate_context;
14691 Initialize Image window.
14693 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14695 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14696 if (resource_info->use_shared_memory == MagickFalse)
14697 windows->image.shared_memory=MagickFalse;
14698 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14703 title=InterpretImageProperties(resource_info->image_info,display_image,
14704 resource_info->title,exception);
14705 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14706 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14707 title=DestroyString(title);
14712 filename[MaxTextExtent];
14715 Window name is the base of the filename.
14717 GetPathComponent(display_image->magick_filename,TailPath,filename);
14718 if (display_image->scene == 0)
14719 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14720 "%s: %s",MagickPackageName,filename);
14722 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14723 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14724 (double) display_image->scene,(double) GetImageListLength(
14726 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14728 if (resource_info->immutable)
14729 windows->image.immutable=MagickTrue;
14730 windows->image.use_pixmap=resource_info->use_pixmap;
14731 windows->image.geometry=resource_info->image_geometry;
14732 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14733 XDisplayWidth(display,visual_info->screen),
14734 XDisplayHeight(display,visual_info->screen));
14735 geometry_info.width=display_image->columns;
14736 geometry_info.height=display_image->rows;
14739 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14740 &geometry_info.width,&geometry_info.height);
14741 windows->image.width=(unsigned int) geometry_info.width;
14742 windows->image.height=(unsigned int) geometry_info.height;
14743 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14744 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14745 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14746 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14747 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14748 resource_info,&windows->backdrop);
14749 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14752 Initialize backdrop window.
14754 windows->backdrop.x=0;
14755 windows->backdrop.y=0;
14756 (void) CloneString(&windows->backdrop.name,"Backdrop");
14757 windows->backdrop.flags=(size_t) (USSize | USPosition);
14758 windows->backdrop.width=(unsigned int)
14759 XDisplayWidth(display,visual_info->screen);
14760 windows->backdrop.height=(unsigned int)
14761 XDisplayHeight(display,visual_info->screen);
14762 windows->backdrop.border_width=0;
14763 windows->backdrop.immutable=MagickTrue;
14764 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14766 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14767 StructureNotifyMask;
14768 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14769 manager_hints->icon_window=windows->icon.id;
14770 manager_hints->input=MagickTrue;
14771 manager_hints->initial_state=resource_info->iconic ? IconicState :
14773 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14774 &windows->backdrop);
14775 if (display_image->debug != MagickFalse)
14776 (void) LogMagickEvent(X11Event,GetMagickModule(),
14777 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14778 (void) XMapWindow(display,windows->backdrop.id);
14779 (void) XClearWindow(display,windows->backdrop.id);
14780 if (windows->image.id != (Window) NULL)
14782 (void) XDestroyWindow(display,windows->image.id);
14783 windows->image.id=(Window) NULL;
14786 Position image in the center the backdrop.
14788 windows->image.flags|=USPosition;
14789 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14790 (windows->image.width/2);
14791 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14792 (windows->image.height/2);
14794 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14795 manager_hints->icon_window=windows->icon.id;
14796 manager_hints->input=MagickTrue;
14797 manager_hints->initial_state=resource_info->iconic ? IconicState :
14799 if (windows->group_leader.id != (Window) NULL)
14804 manager_hints->flags|=WindowGroupHint;
14805 manager_hints->window_group=windows->group_leader.id;
14806 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14807 if (display_image->debug != MagickFalse)
14808 (void) LogMagickEvent(X11Event,GetMagickModule(),
14809 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14811 XMakeWindow(display,
14812 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14813 argv,argc,class_hints,manager_hints,&windows->image);
14814 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14815 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14816 if (windows->group_leader.id != (Window) NULL)
14817 (void) XSetTransientForHint(display,windows->image.id,
14818 windows->group_leader.id);
14819 if (display_image->debug != MagickFalse)
14820 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14821 windows->image.id);
14823 Initialize Info widget.
14825 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14827 (void) CloneString(&windows->info.name,"Info");
14828 (void) CloneString(&windows->info.icon_name,"Info");
14829 windows->info.border_width=1;
14832 windows->info.flags|=PPosition;
14833 windows->info.attributes.win_gravity=UnmapGravity;
14834 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14835 StructureNotifyMask;
14836 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14837 manager_hints->input=MagickFalse;
14838 manager_hints->initial_state=NormalState;
14839 manager_hints->window_group=windows->image.id;
14840 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14842 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14843 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14844 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14845 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14846 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14847 if (windows->image.mapped != MagickFalse)
14848 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14849 if (display_image->debug != MagickFalse)
14850 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14853 Initialize Command widget.
14855 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14856 resource_info,&windows->command);
14857 windows->command.data=MagickMenus;
14858 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14859 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14860 resource_info->client_name);
14861 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14862 resource_name,"geometry",(char *) NULL);
14863 (void) CloneString(&windows->command.name,MagickTitle);
14864 windows->command.border_width=0;
14865 windows->command.flags|=PPosition;
14866 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14867 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14868 OwnerGrabButtonMask | StructureNotifyMask;
14869 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14870 manager_hints->input=MagickTrue;
14871 manager_hints->initial_state=NormalState;
14872 manager_hints->window_group=windows->image.id;
14873 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14874 &windows->command);
14875 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14876 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14878 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14879 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14880 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14881 if (windows->command.mapped != MagickFalse)
14882 (void) XMapRaised(display,windows->command.id);
14883 if (display_image->debug != MagickFalse)
14884 (void) LogMagickEvent(X11Event,GetMagickModule(),
14885 "Window id: 0x%lx (command)",windows->command.id);
14887 Initialize Widget window.
14889 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14890 resource_info,&windows->widget);
14891 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14892 resource_info->client_name);
14893 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14894 resource_name,"geometry",(char *) NULL);
14895 windows->widget.border_width=0;
14896 windows->widget.flags|=PPosition;
14897 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14898 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14899 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14900 StructureNotifyMask;
14901 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14902 manager_hints->input=MagickTrue;
14903 manager_hints->initial_state=NormalState;
14904 manager_hints->window_group=windows->image.id;
14905 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14907 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14908 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14909 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14910 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14911 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14912 if (display_image->debug != MagickFalse)
14913 (void) LogMagickEvent(X11Event,GetMagickModule(),
14914 "Window id: 0x%lx (widget)",windows->widget.id);
14916 Initialize popup window.
14918 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14919 resource_info,&windows->popup);
14920 windows->popup.border_width=0;
14921 windows->popup.flags|=PPosition;
14922 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14923 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14924 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14925 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14926 manager_hints->input=MagickTrue;
14927 manager_hints->initial_state=NormalState;
14928 manager_hints->window_group=windows->image.id;
14929 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14931 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14932 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14933 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14934 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14935 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14936 if (display_image->debug != MagickFalse)
14937 (void) LogMagickEvent(X11Event,GetMagickModule(),
14938 "Window id: 0x%lx (pop up)",windows->popup.id);
14940 Initialize Magnify window and cursor.
14942 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14943 resource_info,&windows->magnify);
14944 if (resource_info->use_shared_memory == MagickFalse)
14945 windows->magnify.shared_memory=MagickFalse;
14946 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14947 resource_info->client_name);
14948 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14949 resource_name,"geometry",(char *) NULL);
14950 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14951 resource_info->magnify);
14952 if (windows->magnify.cursor != (Cursor) NULL)
14953 (void) XFreeCursor(display,windows->magnify.cursor);
14954 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14955 map_info->colormap,resource_info->background_color,
14956 resource_info->foreground_color);
14957 if (windows->magnify.cursor == (Cursor) NULL)
14958 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14959 display_image->filename);
14960 windows->magnify.width=MagnifySize;
14961 windows->magnify.height=MagnifySize;
14962 windows->magnify.flags|=PPosition;
14963 windows->magnify.min_width=MagnifySize;
14964 windows->magnify.min_height=MagnifySize;
14965 windows->magnify.width_inc=MagnifySize;
14966 windows->magnify.height_inc=MagnifySize;
14967 windows->magnify.data=resource_info->magnify;
14968 windows->magnify.attributes.cursor=windows->magnify.cursor;
14969 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14970 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14971 StructureNotifyMask;
14972 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14973 manager_hints->input=MagickTrue;
14974 manager_hints->initial_state=NormalState;
14975 manager_hints->window_group=windows->image.id;
14976 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14977 &windows->magnify);
14978 if (display_image->debug != MagickFalse)
14979 (void) LogMagickEvent(X11Event,GetMagickModule(),
14980 "Window id: 0x%lx (magnify)",windows->magnify.id);
14981 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14983 Initialize panning window.
14985 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14986 resource_info,&windows->pan);
14987 (void) CloneString(&windows->pan.name,"Pan Icon");
14988 windows->pan.width=windows->icon.width;
14989 windows->pan.height=windows->icon.height;
14990 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
14991 resource_info->client_name);
14992 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14993 resource_name,"geometry",(char *) NULL);
14994 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14995 &windows->pan.width,&windows->pan.height);
14996 windows->pan.flags|=PPosition;
14997 windows->pan.immutable=MagickTrue;
14998 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14999 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15000 StructureNotifyMask;
15001 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15002 manager_hints->input=MagickFalse;
15003 manager_hints->initial_state=NormalState;
15004 manager_hints->window_group=windows->image.id;
15005 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15007 if (display_image->debug != MagickFalse)
15008 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15010 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15011 if (windows->info.mapped != MagickFalse)
15012 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15013 if ((windows->image.mapped == MagickFalse) ||
15014 (windows->backdrop.id != (Window) NULL))
15015 (void) XMapWindow(display,windows->image.id);
15017 Set our progress monitor and warning handlers.
15019 if (warning_handler == (WarningHandler) NULL)
15021 warning_handler=resource_info->display_warnings ?
15022 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15023 warning_handler=resource_info->display_warnings ?
15024 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15027 Initialize Image and Magnify X images.
15029 windows->image.x=0;
15030 windows->image.y=0;
15031 windows->magnify.shape=MagickFalse;
15032 width=(unsigned int) display_image->columns;
15033 height=(unsigned int) display_image->rows;
15034 if ((display_image->columns != width) || (display_image->rows != height))
15035 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15036 display_image->filename);
15037 status=XMakeImage(display,resource_info,&windows->image,display_image,
15038 width,height,exception);
15039 if (status == MagickFalse)
15040 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15041 display_image->filename);
15042 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15043 windows->magnify.width,windows->magnify.height,exception);
15044 if (status == MagickFalse)
15045 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15046 display_image->filename);
15047 if (windows->magnify.mapped != MagickFalse)
15048 (void) XMapRaised(display,windows->magnify.id);
15049 if (windows->pan.mapped != MagickFalse)
15050 (void) XMapRaised(display,windows->pan.id);
15051 windows->image.window_changes.width=(int) display_image->columns;
15052 windows->image.window_changes.height=(int) display_image->rows;
15053 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15054 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15055 (void) XSync(display,MagickFalse);
15059 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15060 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15062 if (resource_info->update != MagickFalse)
15068 Determine when file data was last modified.
15070 status=GetPathAttributes(display_image->filename,&attributes);
15071 if (status != MagickFalse)
15072 update_time=attributes.st_mtime;
15074 *state&=(~FormerImageState);
15075 *state&=(~MontageImageState);
15076 *state&=(~NextImageState);
15080 Handle a window event.
15082 if (windows->image.mapped != MagickFalse)
15083 if ((display_image->delay != 0) || (resource_info->update != 0))
15085 if (timer < time((time_t *) NULL))
15087 if (resource_info->update == MagickFalse)
15088 *state|=NextImageState | ExitState;
15095 Determine if image file was modified.
15097 status=GetPathAttributes(display_image->filename,&attributes);
15098 if (status != MagickFalse)
15099 if (update_time != attributes.st_mtime)
15104 (void) FormatLocaleString(
15105 resource_info->image_info->filename,MaxTextExtent,
15106 "%s:%s",display_image->magick,
15107 display_image->filename);
15108 nexus=ReadImage(resource_info->image_info,exception);
15109 if (nexus != (Image *) NULL)
15111 nexus=DestroyImage(nexus);
15112 *state|=NextImageState | ExitState;
15115 delay=display_image->delay/MagickMax(
15116 display_image->ticks_per_second,1L);
15117 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15120 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15123 Do not block if delay > 0.
15125 XDelay(display,SuspendTime << 2);
15129 timestamp=time((time_t *) NULL);
15130 (void) XNextEvent(display,&event);
15131 if (windows->image.stasis == MagickFalse)
15132 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15133 MagickTrue : MagickFalse;
15134 if (windows->magnify.stasis == MagickFalse)
15135 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15136 MagickTrue : MagickFalse;
15137 if (event.xany.window == windows->command.id)
15140 Select a command from the Command widget.
15142 id=XCommandWidget(display,windows,CommandMenu,&event);
15145 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15146 command_type=CommandMenus[id];
15147 if (id < MagickMenus)
15150 Select a command from a pop-up menu.
15152 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15156 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15157 command_type=Commands[id][entry];
15159 if (command_type != NullCommand)
15160 nexus=XMagickCommand(display,resource_info,windows,command_type,
15161 &display_image,exception);
15164 switch (event.type)
15168 if (display_image->debug != MagickFalse)
15169 (void) LogMagickEvent(X11Event,GetMagickModule(),
15170 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15171 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15172 if ((event.xbutton.button == Button3) &&
15173 (event.xbutton.state & Mod1Mask))
15176 Convert Alt-Button3 to Button2.
15178 event.xbutton.button=Button2;
15179 event.xbutton.state&=(~Mod1Mask);
15181 if (event.xbutton.window == windows->backdrop.id)
15183 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15184 event.xbutton.time);
15187 if (event.xbutton.window == windows->image.id)
15189 switch (event.xbutton.button)
15193 if (resource_info->immutable)
15196 Select a command from the Virtual menu.
15198 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15201 nexus=XMagickCommand(display,resource_info,windows,
15202 VirtualCommands[entry],&display_image,exception);
15206 Map/unmap Command widget.
15208 if (windows->command.mapped != MagickFalse)
15209 (void) XWithdrawWindow(display,windows->command.id,
15210 windows->command.screen);
15213 (void) XCommandWidget(display,windows,CommandMenu,
15215 (void) XMapRaised(display,windows->command.id);
15222 User pressed the image magnify button.
15224 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15225 &display_image,exception);
15226 XMagnifyImage(display,windows,&event,exception);
15231 if (resource_info->immutable)
15234 Select a command from the Virtual menu.
15236 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15239 nexus=XMagickCommand(display,resource_info,windows,
15240 VirtualCommands[entry],&display_image,exception);
15243 if (display_image->montage != (char *) NULL)
15246 Open or delete a tile from a visual image directory.
15248 nexus=XTileImage(display,resource_info,windows,
15249 display_image,&event,exception);
15250 if (nexus != (Image *) NULL)
15251 *state|=MontageImageState | NextImageState | ExitState;
15252 vid_info.x=(short int) windows->image.x;
15253 vid_info.y=(short int) windows->image.y;
15257 Select a command from the Short Cuts menu.
15259 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15262 nexus=XMagickCommand(display,resource_info,windows,
15263 ShortCutsCommands[entry],&display_image,exception);
15271 XTranslateImage(display,windows,*image,XK_Up);
15279 XTranslateImage(display,windows,*image,XK_Down);
15287 if (event.xbutton.window == windows->magnify.id)
15307 MagnifyCommands[] =
15320 Select a magnify factor from the pop-up menu.
15322 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15324 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15328 if (event.xbutton.window == windows->pan.id)
15330 switch (event.xbutton.button)
15337 XTranslateImage(display,windows,*image,XK_Up);
15345 XTranslateImage(display,windows,*image,XK_Down);
15350 XPanImage(display,windows,&event,exception);
15356 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15358 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15361 case ButtonRelease:
15363 if (display_image->debug != MagickFalse)
15364 (void) LogMagickEvent(X11Event,GetMagickModule(),
15365 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15366 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15369 case ClientMessage:
15371 if (display_image->debug != MagickFalse)
15372 (void) LogMagickEvent(X11Event,GetMagickModule(),
15373 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15374 event.xclient.message_type,event.xclient.format,(unsigned long)
15375 event.xclient.data.l[0]);
15376 if (event.xclient.message_type == windows->im_protocols)
15378 if (*event.xclient.data.l == (long) windows->im_update_widget)
15380 (void) CloneString(&windows->command.name,MagickTitle);
15381 windows->command.data=MagickMenus;
15382 (void) XCommandWidget(display,windows,CommandMenu,
15386 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15389 Update graphic context and window colormap.
15391 for (i=0; i < (int) number_windows; i++)
15393 if (magick_windows[i]->id == windows->icon.id)
15395 context_values.background=pixel->background_color.pixel;
15396 context_values.foreground=pixel->foreground_color.pixel;
15397 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15398 context_mask,&context_values);
15399 (void) XChangeGC(display,magick_windows[i]->widget_context,
15400 context_mask,&context_values);
15401 context_values.background=pixel->foreground_color.pixel;
15402 context_values.foreground=pixel->background_color.pixel;
15403 context_values.plane_mask=context_values.background ^
15404 context_values.foreground;
15405 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15406 (size_t) (context_mask | GCPlaneMask),
15408 magick_windows[i]->attributes.background_pixel=
15409 pixel->background_color.pixel;
15410 magick_windows[i]->attributes.border_pixel=
15411 pixel->border_color.pixel;
15412 magick_windows[i]->attributes.colormap=map_info->colormap;
15413 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15414 (unsigned long) magick_windows[i]->mask,
15415 &magick_windows[i]->attributes);
15417 if (windows->pan.mapped != MagickFalse)
15419 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15420 windows->pan.pixmap);
15421 (void) XClearWindow(display,windows->pan.id);
15422 XDrawPanRectangle(display,windows);
15424 if (windows->backdrop.id != (Window) NULL)
15425 (void) XInstallColormap(display,map_info->colormap);
15428 if (*event.xclient.data.l == (long) windows->im_former_image)
15430 *state|=FormerImageState | ExitState;
15433 if (*event.xclient.data.l == (long) windows->im_next_image)
15435 *state|=NextImageState | ExitState;
15438 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15440 *state|=RetainColorsState;
15443 if (*event.xclient.data.l == (long) windows->im_exit)
15450 if (event.xclient.message_type == windows->dnd_protocols)
15468 Display image named by the Drag-and-Drop selection.
15470 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15472 selection=XInternAtom(display,"DndSelection",MagickFalse);
15473 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15474 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15475 &length,&after,&data);
15476 if ((status != Success) || (length == 0))
15478 if (*event.xclient.data.l == 2)
15483 (void) CopyMagickString(resource_info->image_info->filename,
15484 (char *) data,MaxTextExtent);
15491 if (strncmp((char *) data, "file:", 5) != 0)
15493 (void) XFree((void *) data);
15496 (void) CopyMagickString(resource_info->image_info->filename,
15497 ((char *) data)+5,MaxTextExtent);
15499 nexus=ReadImage(resource_info->image_info,exception);
15500 CatchException(exception);
15501 if (nexus != (Image *) NULL)
15502 *state|=NextImageState | ExitState;
15503 (void) XFree((void *) data);
15507 If client window delete message, exit.
15509 if (event.xclient.message_type != windows->wm_protocols)
15511 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15513 (void) XWithdrawWindow(display,event.xclient.window,
15514 visual_info->screen);
15515 if (event.xclient.window == windows->image.id)
15520 if (event.xclient.window == windows->pan.id)
15523 Restore original image size when pan window is deleted.
15525 windows->image.window_changes.width=windows->image.ximage->width;
15526 windows->image.window_changes.height=windows->image.ximage->height;
15527 (void) XConfigureImage(display,resource_info,windows,
15528 display_image,exception);
15532 case ConfigureNotify:
15534 if (display_image->debug != MagickFalse)
15535 (void) LogMagickEvent(X11Event,GetMagickModule(),
15536 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15537 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15538 event.xconfigure.y,event.xconfigure.send_event);
15539 if (event.xconfigure.window == windows->image.id)
15542 Image window has a new configuration.
15544 if (event.xconfigure.send_event != 0)
15550 Position the transient windows relative of the Image window.
15552 if (windows->command.geometry == (char *) NULL)
15553 if (windows->command.mapped == MagickFalse)
15555 windows->command.x=event.xconfigure.x-
15556 windows->command.width-25;
15557 windows->command.y=event.xconfigure.y;
15558 XConstrainWindowPosition(display,&windows->command);
15559 window_changes.x=windows->command.x;
15560 window_changes.y=windows->command.y;
15561 (void) XReconfigureWMWindow(display,windows->command.id,
15562 windows->command.screen,(unsigned int) (CWX | CWY),
15565 if (windows->widget.geometry == (char *) NULL)
15566 if (windows->widget.mapped == MagickFalse)
15568 windows->widget.x=event.xconfigure.x+
15569 event.xconfigure.width/10;
15570 windows->widget.y=event.xconfigure.y+
15571 event.xconfigure.height/10;
15572 XConstrainWindowPosition(display,&windows->widget);
15573 window_changes.x=windows->widget.x;
15574 window_changes.y=windows->widget.y;
15575 (void) XReconfigureWMWindow(display,windows->widget.id,
15576 windows->widget.screen,(unsigned int) (CWX | CWY),
15579 if (windows->magnify.geometry == (char *) NULL)
15580 if (windows->magnify.mapped == MagickFalse)
15582 windows->magnify.x=event.xconfigure.x+
15583 event.xconfigure.width+25;
15584 windows->magnify.y=event.xconfigure.y;
15585 XConstrainWindowPosition(display,&windows->magnify);
15586 window_changes.x=windows->magnify.x;
15587 window_changes.y=windows->magnify.y;
15588 (void) XReconfigureWMWindow(display,windows->magnify.id,
15589 windows->magnify.screen,(unsigned int) (CWX | CWY),
15592 if (windows->pan.geometry == (char *) NULL)
15593 if (windows->pan.mapped == MagickFalse)
15595 windows->pan.x=event.xconfigure.x+
15596 event.xconfigure.width+25;
15597 windows->pan.y=event.xconfigure.y+
15598 windows->magnify.height+50;
15599 XConstrainWindowPosition(display,&windows->pan);
15600 window_changes.x=windows->pan.x;
15601 window_changes.y=windows->pan.y;
15602 (void) XReconfigureWMWindow(display,windows->pan.id,
15603 windows->pan.screen,(unsigned int) (CWX | CWY),
15607 if ((event.xconfigure.width == (int) windows->image.width) &&
15608 (event.xconfigure.height == (int) windows->image.height))
15610 windows->image.width=(unsigned int) event.xconfigure.width;
15611 windows->image.height=(unsigned int) event.xconfigure.height;
15612 windows->image.x=0;
15613 windows->image.y=0;
15614 if (display_image->montage != (char *) NULL)
15616 windows->image.x=vid_info.x;
15617 windows->image.y=vid_info.y;
15619 if ((windows->image.mapped != MagickFalse) &&
15620 (windows->image.stasis != MagickFalse))
15623 Update image window configuration.
15625 windows->image.window_changes.width=event.xconfigure.width;
15626 windows->image.window_changes.height=event.xconfigure.height;
15627 (void) XConfigureImage(display,resource_info,windows,
15628 display_image,exception);
15631 Update pan window configuration.
15633 if ((event.xconfigure.width < windows->image.ximage->width) ||
15634 (event.xconfigure.height < windows->image.ximage->height))
15636 (void) XMapRaised(display,windows->pan.id);
15637 XDrawPanRectangle(display,windows);
15640 if (windows->pan.mapped != MagickFalse)
15641 (void) XWithdrawWindow(display,windows->pan.id,
15642 windows->pan.screen);
15645 if (event.xconfigure.window == windows->magnify.id)
15651 Magnify window has a new configuration.
15653 windows->magnify.width=(unsigned int) event.xconfigure.width;
15654 windows->magnify.height=(unsigned int) event.xconfigure.height;
15655 if (windows->magnify.mapped == MagickFalse)
15658 while ((int) magnify <= event.xconfigure.width)
15660 while ((int) magnify <= event.xconfigure.height)
15663 if (((int) magnify != event.xconfigure.width) ||
15664 ((int) magnify != event.xconfigure.height))
15666 window_changes.width=(int) magnify;
15667 window_changes.height=(int) magnify;
15668 (void) XReconfigureWMWindow(display,windows->magnify.id,
15669 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15673 if ((windows->magnify.mapped != MagickFalse) &&
15674 (windows->magnify.stasis != MagickFalse))
15676 status=XMakeImage(display,resource_info,&windows->magnify,
15677 display_image,windows->magnify.width,windows->magnify.height,
15679 XMakeMagnifyImage(display,windows,exception);
15683 if ((windows->magnify.mapped != MagickFalse) &&
15684 (event.xconfigure.window == windows->pan.id))
15687 Pan icon window has a new configuration.
15689 if (event.xconfigure.send_event != 0)
15691 windows->pan.x=event.xconfigure.x;
15692 windows->pan.y=event.xconfigure.y;
15694 windows->pan.width=(unsigned int) event.xconfigure.width;
15695 windows->pan.height=(unsigned int) event.xconfigure.height;
15698 if (event.xconfigure.window == windows->icon.id)
15701 Icon window has a new configuration.
15703 windows->icon.width=(unsigned int) event.xconfigure.width;
15704 windows->icon.height=(unsigned int) event.xconfigure.height;
15709 case DestroyNotify:
15712 Group leader has exited.
15714 if (display_image->debug != MagickFalse)
15715 (void) LogMagickEvent(X11Event,GetMagickModule(),
15716 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15717 if (event.xdestroywindow.window == windows->group_leader.id)
15727 Selectively install colormap.
15729 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15730 if (event.xcrossing.mode != NotifyUngrab)
15731 XInstallColormap(display,map_info->colormap);
15736 if (display_image->debug != MagickFalse)
15737 (void) LogMagickEvent(X11Event,GetMagickModule(),
15738 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15739 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15742 Refresh windows that are now exposed.
15744 if ((event.xexpose.window == windows->image.id) &&
15745 (windows->image.mapped != MagickFalse))
15747 XRefreshWindow(display,&windows->image,&event);
15748 delay=display_image->delay/MagickMax(
15749 display_image->ticks_per_second,1L);
15750 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15753 if ((event.xexpose.window == windows->magnify.id) &&
15754 (windows->magnify.mapped != MagickFalse))
15756 XMakeMagnifyImage(display,windows,exception);
15759 if (event.xexpose.window == windows->pan.id)
15761 XDrawPanRectangle(display,windows);
15764 if (event.xexpose.window == windows->icon.id)
15766 XRefreshWindow(display,&windows->icon,&event);
15777 Respond to a user key press.
15779 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15780 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15781 *(command+length)='\0';
15782 if (display_image->debug != MagickFalse)
15783 (void) LogMagickEvent(X11Event,GetMagickModule(),
15784 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15785 key_symbol,command);
15786 if (event.xkey.window == windows->image.id)
15788 command_type=XImageWindowCommand(display,resource_info,windows,
15789 event.xkey.state,key_symbol,&display_image,exception);
15790 if (command_type != NullCommand)
15791 nexus=XMagickCommand(display,resource_info,windows,command_type,
15792 &display_image,exception);
15794 if (event.xkey.window == windows->magnify.id)
15795 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15797 if (event.xkey.window == windows->pan.id)
15799 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15800 (void) XWithdrawWindow(display,windows->pan.id,
15801 windows->pan.screen);
15803 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15804 XTextViewWidget(display,resource_info,windows,MagickFalse,
15805 "Help Viewer - Image Pan",ImagePanHelp);
15807 XTranslateImage(display,windows,*image,key_symbol);
15809 delay=display_image->delay/MagickMax(
15810 display_image->ticks_per_second,1L);
15811 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15817 Respond to a user key release.
15819 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15820 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15821 if (display_image->debug != MagickFalse)
15822 (void) LogMagickEvent(X11Event,GetMagickModule(),
15823 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15829 Selectively uninstall colormap.
15831 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15832 if (event.xcrossing.mode != NotifyUngrab)
15833 XUninstallColormap(display,map_info->colormap);
15838 if (display_image->debug != MagickFalse)
15839 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15840 event.xmap.window);
15841 if (event.xmap.window == windows->backdrop.id)
15843 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15845 windows->backdrop.mapped=MagickTrue;
15848 if (event.xmap.window == windows->image.id)
15850 if (windows->backdrop.id != (Window) NULL)
15851 (void) XInstallColormap(display,map_info->colormap);
15852 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15854 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15855 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15857 if (((int) windows->image.width < windows->image.ximage->width) ||
15858 ((int) windows->image.height < windows->image.ximage->height))
15859 (void) XMapRaised(display,windows->pan.id);
15860 windows->image.mapped=MagickTrue;
15863 if (event.xmap.window == windows->magnify.id)
15865 XMakeMagnifyImage(display,windows,exception);
15866 windows->magnify.mapped=MagickTrue;
15867 (void) XWithdrawWindow(display,windows->info.id,
15868 windows->info.screen);
15871 if (event.xmap.window == windows->pan.id)
15873 XMakePanImage(display,resource_info,windows,display_image,
15875 windows->pan.mapped=MagickTrue;
15878 if (event.xmap.window == windows->info.id)
15880 windows->info.mapped=MagickTrue;
15883 if (event.xmap.window == windows->icon.id)
15889 Create an icon image.
15891 taint=display_image->taint;
15892 XMakeStandardColormap(display,icon_visual,icon_resources,
15893 display_image,icon_map,icon_pixel,exception);
15894 (void) XMakeImage(display,icon_resources,&windows->icon,
15895 display_image,windows->icon.width,windows->icon.height,
15897 display_image->taint=taint;
15898 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15899 windows->icon.pixmap);
15900 (void) XClearWindow(display,windows->icon.id);
15901 (void) XWithdrawWindow(display,windows->info.id,
15902 windows->info.screen);
15903 windows->icon.mapped=MagickTrue;
15906 if (event.xmap.window == windows->command.id)
15908 windows->command.mapped=MagickTrue;
15911 if (event.xmap.window == windows->popup.id)
15913 windows->popup.mapped=MagickTrue;
15916 if (event.xmap.window == windows->widget.id)
15918 windows->widget.mapped=MagickTrue;
15923 case MappingNotify:
15925 (void) XRefreshKeyboardMapping(&event.xmapping);
15930 case PropertyNotify:
15946 if (display_image->debug != MagickFalse)
15947 (void) LogMagickEvent(X11Event,GetMagickModule(),
15948 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15949 event.xproperty.atom,event.xproperty.state);
15950 if (event.xproperty.atom != windows->im_remote_command)
15953 Display image named by the remote command protocol.
15955 status=XGetWindowProperty(display,event.xproperty.window,
15956 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15957 AnyPropertyType,&type,&format,&length,&after,&data);
15958 if ((status != Success) || (length == 0))
15960 if (LocaleCompare((char *) data,"-quit") == 0)
15962 XClientMessage(display,windows->image.id,windows->im_protocols,
15963 windows->im_exit,CurrentTime);
15964 (void) XFree((void *) data);
15967 (void) CopyMagickString(resource_info->image_info->filename,
15968 (char *) data,MaxTextExtent);
15969 (void) XFree((void *) data);
15970 nexus=ReadImage(resource_info->image_info,exception);
15971 CatchException(exception);
15972 if (nexus != (Image *) NULL)
15973 *state|=NextImageState | ExitState;
15976 case ReparentNotify:
15978 if (display_image->debug != MagickFalse)
15979 (void) LogMagickEvent(X11Event,GetMagickModule(),
15980 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15981 event.xreparent.window);
15986 if (display_image->debug != MagickFalse)
15987 (void) LogMagickEvent(X11Event,GetMagickModule(),
15988 "Unmap Notify: 0x%lx",event.xunmap.window);
15989 if (event.xunmap.window == windows->backdrop.id)
15991 windows->backdrop.mapped=MagickFalse;
15994 if (event.xunmap.window == windows->image.id)
15996 windows->image.mapped=MagickFalse;
15999 if (event.xunmap.window == windows->magnify.id)
16001 windows->magnify.mapped=MagickFalse;
16004 if (event.xunmap.window == windows->pan.id)
16006 windows->pan.mapped=MagickFalse;
16009 if (event.xunmap.window == windows->info.id)
16011 windows->info.mapped=MagickFalse;
16014 if (event.xunmap.window == windows->icon.id)
16016 if (map_info->colormap == icon_map->colormap)
16017 XConfigureImageColormap(display,resource_info,windows,
16018 display_image,exception);
16019 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16021 windows->icon.mapped=MagickFalse;
16024 if (event.xunmap.window == windows->command.id)
16026 windows->command.mapped=MagickFalse;
16029 if (event.xunmap.window == windows->popup.id)
16031 if (windows->backdrop.id != (Window) NULL)
16032 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16034 windows->popup.mapped=MagickFalse;
16037 if (event.xunmap.window == windows->widget.id)
16039 if (windows->backdrop.id != (Window) NULL)
16040 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16042 windows->widget.mapped=MagickFalse;
16049 if (display_image->debug != MagickFalse)
16050 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16055 } while (!(*state & ExitState));
16056 if ((*state & ExitState) == 0)
16057 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16058 &display_image,exception);
16060 if (resource_info->confirm_edit != MagickFalse)
16063 Query user if image has changed.
16065 if ((resource_info->immutable == MagickFalse) &&
16066 (display_image->taint != MagickFalse))
16071 status=XConfirmWidget(display,windows,"Your image changed.",
16072 "Do you want to save it");
16074 *state&=(~ExitState);
16077 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16078 &display_image,exception);
16081 if ((windows->visual_info->klass == GrayScale) ||
16082 (windows->visual_info->klass == PseudoColor) ||
16083 (windows->visual_info->klass == DirectColor))
16086 Withdraw pan and Magnify window.
16088 if (windows->info.mapped != MagickFalse)
16089 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16090 if (windows->magnify.mapped != MagickFalse)
16091 (void) XWithdrawWindow(display,windows->magnify.id,
16092 windows->magnify.screen);
16093 if (windows->command.mapped != MagickFalse)
16094 (void) XWithdrawWindow(display,windows->command.id,
16095 windows->command.screen);
16097 if (windows->pan.mapped != MagickFalse)
16098 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16099 if (resource_info->backdrop == MagickFalse)
16100 if (windows->backdrop.mapped)
16102 (void) XWithdrawWindow(display,windows->backdrop.id,
16103 windows->backdrop.screen);
16104 (void) XDestroyWindow(display,windows->backdrop.id);
16105 windows->backdrop.id=(Window) NULL;
16106 (void) XWithdrawWindow(display,windows->image.id,
16107 windows->image.screen);
16108 (void) XDestroyWindow(display,windows->image.id);
16109 windows->image.id=(Window) NULL;
16111 XSetCursorState(display,windows,MagickTrue);
16112 XCheckRefreshWindows(display,windows);
16113 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16114 *state&=(~ExitState);
16115 if (*state & ExitState)
16118 Free Standard Colormap.
16120 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16121 if (resource_info->map_type == (char *) NULL)
16122 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16126 if (resource_info->copy_image != (Image *) NULL)
16128 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16129 resource_info->copy_image=NewImageList();
16131 DestroyXResources();
16133 (void) XSync(display,MagickFalse);
16135 Restore our progress monitor and warning handlers.
16137 (void) SetErrorHandler(warning_handler);
16138 (void) SetWarningHandler(warning_handler);
16140 Change to home directory.
16142 directory=getcwd(working_directory,MaxTextExtent);
16148 status=chdir(resource_info->home_directory);
16150 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16151 "UnableToOpenFile","%s",resource_info->home_directory);
16153 *image=display_image;
16159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16163 + D i s p l a y I m a g e s %
16167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16169 % DisplayImages() displays an image sequence to any X window screen. It
16170 % returns a value other than 0 if successful. Check the exception member
16171 % of image to determine the reason for any failure.
16173 % The format of the DisplayImages method is:
16175 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16176 % Image *images,ExceptionInfo *exception)
16178 % A description of each parameter follows:
16180 % o image_info: the image info.
16182 % o image: the image.
16184 % o exception: return any errors or warnings in this structure.
16187 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16188 Image *image,ExceptionInfo *exception)
16190 assert(image_info != (const ImageInfo *) NULL);
16191 assert(image_info->signature == MagickSignature);
16192 assert(image != (Image *) NULL);
16193 assert(image->signature == MagickSignature);
16194 if (image->debug != MagickFalse)
16195 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16196 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16197 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
16198 return(MagickFalse);
16202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16206 + R e m o t e D i s p l a y C o m m a n d %
16210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16212 % RemoteDisplayCommand() encourages a remote display program to display the
16213 % specified image filename.
16215 % The format of the RemoteDisplayCommand method is:
16217 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16218 % const char *window,const char *filename,ExceptionInfo *exception)
16220 % A description of each parameter follows:
16222 % o image_info: the image info.
16224 % o window: Specifies the name or id of an X window.
16226 % o filename: the name of the image filename to display.
16228 % o exception: return any errors or warnings in this structure.
16231 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16232 const char *window,const char *filename,ExceptionInfo *exception)
16234 assert(image_info != (const ImageInfo *) NULL);
16235 assert(image_info->signature == MagickSignature);
16236 assert(filename != (char *) NULL);
16238 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16239 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16240 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
16241 return(MagickFalse);