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 SetErrorHandler((ErrorHandler) NULL);
1705 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=AcquireCacheView(*image);
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 virtual_pixel[CompositePixelChannel];
3767 Update color information using replace algorithm.
3769 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
3770 (ssize_t) y_offset,virtual_pixel,exception);
3771 target.red=virtual_pixel[RedPixelChannel];
3772 target.green=virtual_pixel[GreenPixelChannel];
3773 target.blue=virtual_pixel[BluePixelChannel];
3774 target.alpha=virtual_pixel[AlphaPixelChannel];
3775 if ((*image)->storage_class == DirectClass)
3777 for (y=0; y < (int) (*image)->rows; y++)
3779 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3780 (*image)->columns,1,exception);
3781 if (q == (Quantum *) NULL)
3783 for (x=0; x < (int) (*image)->columns; x++)
3785 GetPixelInfoPixel(*image,q,&pixel);
3786 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3788 SetPixelRed(*image,ScaleShortToQuantum(
3790 SetPixelGreen(*image,ScaleShortToQuantum(
3792 SetPixelBlue(*image,ScaleShortToQuantum(
3795 q+=GetPixelChannels(*image);
3797 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3803 for (i=0; i < (ssize_t) (*image)->colors; i++)
3804 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3806 (*image)->colormap[i].red=ScaleShortToQuantum(
3808 (*image)->colormap[i].green=ScaleShortToQuantum(
3810 (*image)->colormap[i].blue=ScaleShortToQuantum(
3813 (void) SyncImage(*image,exception);
3817 case FloodfillMethod:
3818 case FillToBorderMethod:
3827 Update color information using floodfill algorithm.
3829 (void) GetOneVirtualPixelInfo(*image,
3830 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3831 y_offset,&target,exception);
3832 if (method == FillToBorderMethod)
3834 target.red=(MagickRealType)
3835 ScaleShortToQuantum(border_color.red);
3836 target.green=(MagickRealType)
3837 ScaleShortToQuantum(border_color.green);
3838 target.blue=(MagickRealType)
3839 ScaleShortToQuantum(border_color.blue);
3841 draw_info=CloneDrawInfo(resource_info->image_info,
3843 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3844 AllCompliance,&draw_info->fill,exception);
3845 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
3846 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
3847 MagickFalse : MagickTrue,exception);
3848 draw_info=DestroyDrawInfo(draw_info);
3854 Update color information using reset algorithm.
3856 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3857 return(MagickFalse);
3858 for (y=0; y < (int) (*image)->rows; y++)
3860 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3861 (*image)->columns,1,exception);
3862 if (q == (Quantum *) NULL)
3864 for (x=0; x < (int) (*image)->columns; x++)
3866 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3867 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3868 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3869 q+=GetPixelChannels(*image);
3871 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3877 image_view=DestroyCacheView(image_view);
3878 state&=(~UpdateConfigurationState);
3880 } while ((state & ExitState) == 0);
3881 (void) XSelectInput(display,windows->image.id,
3882 windows->image.attributes.event_mask);
3883 XSetCursorState(display,windows,MagickFalse);
3884 (void) XFreeCursor(display,cursor);
3889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3893 + X C o m p o s i t e I m a g e %
3897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3899 % XCompositeImage() requests an image name from the user, reads the image and
3900 % composites it with the X window image at a location the user chooses with
3903 % The format of the XCompositeImage method is:
3905 % MagickBooleanType XCompositeImage(Display *display,
3906 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3907 % ExceptionInfo *exception)
3909 % A description of each parameter follows:
3911 % o display: Specifies a connection to an X server; returned from
3914 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3916 % o windows: Specifies a pointer to a XWindows structure.
3918 % o image: the image; returned from ReadImage.
3920 % o exception: return any errors or warnings in this structure.
3923 static MagickBooleanType XCompositeImage(Display *display,
3924 XResourceInfo *resource_info,XWindows *windows,Image *image,
3925 ExceptionInfo *exception)
3928 displacement_geometry[MaxTextExtent] = "30x30",
3929 filename[MaxTextExtent] = "\0";
3942 static CompositeOperator
3943 compose = CopyCompositeOp;
3945 static const ModeType
3946 CompositeCommands[] =
3948 CompositeOperatorsCommand,
3949 CompositeDissolveCommand,
3950 CompositeDisplaceCommand,
3951 CompositeHelpCommand,
3952 CompositeDismissCommand
3956 text[MaxTextExtent];
3989 Request image file name from user.
3991 XFileBrowserWidget(display,windows,"Composite",filename);
3992 if (*filename == '\0')
3997 XSetCursorState(display,windows,MagickTrue);
3998 XCheckRefreshWindows(display,windows);
3999 (void) CopyMagickString(resource_info->image_info->filename,filename,
4001 composite_image=ReadImage(resource_info->image_info,exception);
4002 CatchException(exception);
4003 XSetCursorState(display,windows,MagickFalse);
4004 if (composite_image == (Image *) NULL)
4005 return(MagickFalse);
4009 (void) CloneString(&windows->command.name,"Composite");
4010 windows->command.data=1;
4011 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
4012 (void) XMapRaised(display,windows->command.id);
4013 XClientMessage(display,windows->image.id,windows->im_protocols,
4014 windows->im_update_widget,CurrentTime);
4016 Track pointer until button 1 is pressed.
4018 XQueryPosition(display,windows->image.id,&x,&y);
4019 (void) XSelectInput(display,windows->image.id,
4020 windows->image.attributes.event_mask | PointerMotionMask);
4021 composite_info.x=(ssize_t) windows->image.x+x;
4022 composite_info.y=(ssize_t) windows->image.y+y;
4023 composite_info.width=0;
4024 composite_info.height=0;
4025 cursor=XCreateFontCursor(display,XC_ul_angle);
4026 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4031 if (windows->info.mapped != MagickFalse)
4034 Display pointer position.
4036 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4037 (long) composite_info.x,(long) composite_info.y);
4038 XInfoWidget(display,windows,text);
4040 highlight_info=composite_info;
4041 highlight_info.x=composite_info.x-windows->image.x;
4042 highlight_info.y=composite_info.y-windows->image.y;
4043 XHighlightRectangle(display,windows->image.id,
4044 windows->image.highlight_context,&highlight_info);
4046 Wait for next event.
4048 XScreenEvent(display,windows,&event,exception);
4049 XHighlightRectangle(display,windows->image.id,
4050 windows->image.highlight_context,&highlight_info);
4051 if (event.xany.window == windows->command.id)
4054 Select a command from the Command widget.
4056 id=XCommandWidget(display,windows,CompositeMenu,&event);
4059 switch (CompositeCommands[id])
4061 case CompositeOperatorsCommand:
4064 command[MaxTextExtent],
4068 Select a command from the pop-up menu.
4070 operators=GetCommandOptions(MagickComposeOptions);
4071 if (operators == (char **) NULL)
4073 entry=XMenuWidget(display,windows,CompositeMenu[id],
4074 (const char **) operators,command);
4076 compose=(CompositeOperator) ParseCommandOption(
4077 MagickComposeOptions,MagickFalse,operators[entry]);
4078 operators=DestroyStringList(operators);
4081 case CompositeDissolveCommand:
4084 factor[MaxTextExtent] = "20.0";
4087 Dissolve the two images a given percent.
4089 (void) XSetFunction(display,windows->image.highlight_context,
4091 (void) XDialogWidget(display,windows,"Dissolve",
4092 "Enter the blend factor (0.0 - 99.9%):",factor);
4093 (void) XSetFunction(display,windows->image.highlight_context,
4095 if (*factor == '\0')
4097 blend=StringToDouble(factor,(char **) NULL);
4098 compose=DissolveCompositeOp;
4101 case CompositeDisplaceCommand:
4104 Get horizontal and vertical scale displacement geometry.
4106 (void) XSetFunction(display,windows->image.highlight_context,
4108 (void) XDialogWidget(display,windows,"Displace",
4109 "Enter the horizontal and vertical scale:",displacement_geometry);
4110 (void) XSetFunction(display,windows->image.highlight_context,
4112 if (*displacement_geometry == '\0')
4114 compose=DisplaceCompositeOp;
4117 case CompositeHelpCommand:
4119 (void) XSetFunction(display,windows->image.highlight_context,
4121 XTextViewWidget(display,resource_info,windows,MagickFalse,
4122 "Help Viewer - Image Composite",ImageCompositeHelp);
4123 (void) XSetFunction(display,windows->image.highlight_context,
4127 case CompositeDismissCommand:
4145 if (image->debug != MagickFalse)
4146 (void) LogMagickEvent(X11Event,GetMagickModule(),
4147 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4148 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4149 if (event.xbutton.button != Button1)
4151 if (event.xbutton.window != windows->image.id)
4156 composite_info.width=composite_image->columns;
4157 composite_info.height=composite_image->rows;
4158 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4159 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4160 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4165 if (image->debug != MagickFalse)
4166 (void) LogMagickEvent(X11Event,GetMagickModule(),
4167 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4168 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4169 if (event.xbutton.button != Button1)
4171 if (event.xbutton.window != windows->image.id)
4173 if ((composite_info.width != 0) && (composite_info.height != 0))
4176 User has selected the location of the composite image.
4178 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4179 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4189 command[MaxTextExtent];
4197 if (event.xkey.window != windows->image.id)
4200 Respond to a user key press.
4202 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4203 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4204 *(command+length)='\0';
4205 if (image->debug != MagickFalse)
4206 (void) LogMagickEvent(X11Event,GetMagickModule(),
4207 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4208 switch ((int) key_symbol)
4216 composite_image=DestroyImage(composite_image);
4224 (void) XSetFunction(display,windows->image.highlight_context,
4226 XTextViewWidget(display,resource_info,windows,MagickFalse,
4227 "Help Viewer - Image Composite",ImageCompositeHelp);
4228 (void) XSetFunction(display,windows->image.highlight_context,
4234 (void) XBell(display,0);
4243 Map and unmap Info widget as text cursor crosses its boundaries.
4247 if (windows->info.mapped != MagickFalse)
4249 if ((x < (int) (windows->info.x+windows->info.width)) &&
4250 (y < (int) (windows->info.y+windows->info.height)))
4251 (void) XWithdrawWindow(display,windows->info.id,
4252 windows->info.screen);
4255 if ((x > (int) (windows->info.x+windows->info.width)) ||
4256 (y > (int) (windows->info.y+windows->info.height)))
4257 (void) XMapWindow(display,windows->info.id);
4258 composite_info.x=(ssize_t) windows->image.x+x;
4259 composite_info.y=(ssize_t) windows->image.y+y;
4264 if (image->debug != MagickFalse)
4265 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4270 } while ((state & ExitState) == 0);
4271 (void) XSelectInput(display,windows->image.id,
4272 windows->image.attributes.event_mask);
4273 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4274 XSetCursorState(display,windows,MagickFalse);
4275 (void) XFreeCursor(display,cursor);
4276 if ((state & EscapeState) != 0)
4279 Image compositing is relative to image configuration.
4281 XSetCursorState(display,windows,MagickTrue);
4282 XCheckRefreshWindows(display,windows);
4283 width=(unsigned int) image->columns;
4284 height=(unsigned int) image->rows;
4287 if (windows->image.crop_geometry != (char *) NULL)
4288 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4289 scale_factor=(MagickRealType) width/windows->image.ximage->width;
4290 composite_info.x+=x;
4291 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4292 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4293 scale_factor=(MagickRealType) height/windows->image.ximage->height;
4294 composite_info.y+=y;
4295 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4296 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4297 if ((composite_info.width != composite_image->columns) ||
4298 (composite_info.height != composite_image->rows))
4304 Scale composite image.
4306 resize_image=ResizeImage(composite_image,composite_info.width,
4307 composite_info.height,composite_image->filter,composite_image->blur,
4309 composite_image=DestroyImage(composite_image);
4310 if (resize_image == (Image *) NULL)
4312 XSetCursorState(display,windows,MagickFalse);
4313 return(MagickFalse);
4315 composite_image=resize_image;
4317 if (compose == DisplaceCompositeOp)
4318 (void) SetImageArtifact(composite_image,"compose:args",
4319 displacement_geometry);
4338 Create mattes for blending.
4340 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4341 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
4342 ((ssize_t) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
4343 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4344 return(MagickFalse);
4345 image->matte=MagickTrue;
4346 image_view=AcquireCacheView(image);
4347 for (y=0; y < (int) image->rows; y++)
4349 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4351 if (q == (Quantum *) NULL)
4353 for (x=0; x < (int) image->columns; x++)
4355 SetPixelAlpha(image,opacity,q);
4356 q+=GetPixelChannels(image);
4358 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4361 image_view=DestroyCacheView(image_view);
4364 Composite image with X Image window.
4366 (void) CompositeImage(image,compose,composite_image,composite_info.x,
4367 composite_info.y,exception);
4368 composite_image=DestroyImage(composite_image);
4369 XSetCursorState(display,windows,MagickFalse);
4371 Update image configuration.
4373 XConfigureImageColormap(display,resource_info,windows,image,exception);
4374 (void) XConfigureImage(display,resource_info,windows,image,exception);
4379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4383 + X C o n f i g u r e I m a g e %
4387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4389 % XConfigureImage() creates a new X image. It also notifies the window
4390 % manager of the new image size and configures the transient widows.
4392 % The format of the XConfigureImage method is:
4394 % MagickBooleanType XConfigureImage(Display *display,
4395 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4396 % ExceptionInfo *exception)
4398 % A description of each parameter follows:
4400 % o display: Specifies a connection to an X server; returned from
4403 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4405 % o windows: Specifies a pointer to a XWindows structure.
4407 % o image: the image.
4409 % o exception: return any errors or warnings in this structure.
4411 % o exception: return any errors or warnings in this structure.
4414 static MagickBooleanType XConfigureImage(Display *display,
4415 XResourceInfo *resource_info,XWindows *windows,Image *image,
4416 ExceptionInfo *exception)
4419 geometry[MaxTextExtent];
4440 Dismiss if window dimensions are zero.
4442 width=(unsigned int) windows->image.window_changes.width;
4443 height=(unsigned int) windows->image.window_changes.height;
4444 if (image->debug != MagickFalse)
4445 (void) LogMagickEvent(X11Event,GetMagickModule(),
4446 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4447 windows->image.ximage->height,(double) width,(double) height);
4448 if ((width*height) == 0)
4453 Resize image to fit Image window dimensions.
4455 XSetCursorState(display,windows,MagickTrue);
4456 (void) XFlush(display);
4457 if (((int) width != windows->image.ximage->width) ||
4458 ((int) height != windows->image.ximage->height))
4459 image->taint=MagickTrue;
4460 windows->magnify.x=(int)
4461 width*windows->magnify.x/windows->image.ximage->width;
4462 windows->magnify.y=(int)
4463 height*windows->magnify.y/windows->image.ximage->height;
4464 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4465 windows->image.y=(int)
4466 (height*windows->image.y/windows->image.ximage->height);
4467 status=XMakeImage(display,resource_info,&windows->image,image,
4468 (unsigned int) width,(unsigned int) height,exception);
4469 if (status == MagickFalse)
4470 XNoticeWidget(display,windows,"Unable to configure X image:",
4471 windows->image.name);
4473 Notify window manager of the new configuration.
4475 if (resource_info->image_geometry != (char *) NULL)
4476 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4477 resource_info->image_geometry);
4479 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4480 XDisplayWidth(display,windows->image.screen),
4481 XDisplayHeight(display,windows->image.screen));
4482 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4483 window_changes.width=(int) width;
4484 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4485 window_changes.width=XDisplayWidth(display,windows->image.screen);
4486 window_changes.height=(int) height;
4487 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4488 window_changes.height=XDisplayHeight(display,windows->image.screen);
4489 mask=(size_t) (CWWidth | CWHeight);
4490 if (resource_info->backdrop)
4493 window_changes.x=(int)
4494 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4495 window_changes.y=(int)
4496 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4498 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4499 (unsigned int) mask,&window_changes);
4500 (void) XClearWindow(display,windows->image.id);
4501 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4503 Update Magnify window configuration.
4505 if (windows->magnify.mapped != MagickFalse)
4506 XMakeMagnifyImage(display,windows,exception);
4507 windows->pan.crop_geometry=windows->image.crop_geometry;
4508 XBestIconSize(display,&windows->pan,image);
4509 while (((windows->pan.width << 1) < MaxIconSize) &&
4510 ((windows->pan.height << 1) < MaxIconSize))
4512 windows->pan.width<<=1;
4513 windows->pan.height<<=1;
4515 if (windows->pan.geometry != (char *) NULL)
4516 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4517 &windows->pan.width,&windows->pan.height);
4518 window_changes.width=(int) windows->pan.width;
4519 window_changes.height=(int) windows->pan.height;
4520 size_hints=XAllocSizeHints();
4521 if (size_hints != (XSizeHints *) NULL)
4526 size_hints->flags=PSize | PMinSize | PMaxSize;
4527 size_hints->width=window_changes.width;
4528 size_hints->height=window_changes.height;
4529 size_hints->min_width=size_hints->width;
4530 size_hints->min_height=size_hints->height;
4531 size_hints->max_width=size_hints->width;
4532 size_hints->max_height=size_hints->height;
4533 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4534 (void) XFree((void *) size_hints);
4536 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4537 (unsigned int) (CWWidth | CWHeight),&window_changes);
4539 Update icon window configuration.
4541 windows->icon.crop_geometry=windows->image.crop_geometry;
4542 XBestIconSize(display,&windows->icon,image);
4543 window_changes.width=(int) windows->icon.width;
4544 window_changes.height=(int) windows->icon.height;
4545 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4546 (unsigned int) (CWWidth | CWHeight),&window_changes);
4547 XSetCursorState(display,windows,MagickFalse);
4548 return(status != 0 ? MagickTrue : MagickFalse);
4552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4556 + X C r o p I m a g e %
4560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4562 % XCropImage() allows the user to select a region of the image and crop, copy,
4563 % or cut it. For copy or cut, the image can subsequently be composited onto
4564 % the image with XPasteImage.
4566 % The format of the XCropImage method is:
4568 % MagickBooleanType XCropImage(Display *display,
4569 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4570 % const ClipboardMode mode,ExceptionInfo *exception)
4572 % A description of each parameter follows:
4574 % o display: Specifies a connection to an X server; returned from
4577 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4579 % o windows: Specifies a pointer to a XWindows structure.
4581 % o image: the image; returned from ReadImage.
4583 % o mode: This unsigned value specified whether the image should be
4584 % cropped, copied, or cut.
4586 % o exception: return any errors or warnings in this structure.
4589 static MagickBooleanType XCropImage(Display *display,
4590 XResourceInfo *resource_info,XWindows *windows,Image *image,
4591 const ClipboardMode mode,ExceptionInfo *exception)
4600 *RectifyModeMenu[] =
4608 static const ModeType
4618 RectifyDismissCommand
4625 command[MaxTextExtent],
4626 text[MaxTextExtent];
4669 (void) CloneString(&windows->command.name,"Copy");
4674 (void) CloneString(&windows->command.name,"Crop");
4679 (void) CloneString(&windows->command.name,"Cut");
4683 RectifyModeMenu[0]=windows->command.name;
4684 windows->command.data=0;
4685 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4686 (void) XMapRaised(display,windows->command.id);
4687 XClientMessage(display,windows->image.id,windows->im_protocols,
4688 windows->im_update_widget,CurrentTime);
4690 Track pointer until button 1 is pressed.
4692 XQueryPosition(display,windows->image.id,&x,&y);
4693 (void) XSelectInput(display,windows->image.id,
4694 windows->image.attributes.event_mask | PointerMotionMask);
4695 crop_info.x=(ssize_t) windows->image.x+x;
4696 crop_info.y=(ssize_t) windows->image.y+y;
4699 cursor=XCreateFontCursor(display,XC_fleur);
4703 if (windows->info.mapped != MagickFalse)
4706 Display pointer position.
4708 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4709 (long) crop_info.x,(long) crop_info.y);
4710 XInfoWidget(display,windows,text);
4713 Wait for next event.
4715 XScreenEvent(display,windows,&event,exception);
4716 if (event.xany.window == windows->command.id)
4719 Select a command from the Command widget.
4721 id=XCommandWidget(display,windows,CropModeMenu,&event);
4724 switch (CropCommands[id])
4726 case CropHelpCommand:
4732 XTextViewWidget(display,resource_info,windows,MagickFalse,
4733 "Help Viewer - Image Copy",ImageCopyHelp);
4738 XTextViewWidget(display,resource_info,windows,MagickFalse,
4739 "Help Viewer - Image Crop",ImageCropHelp);
4744 XTextViewWidget(display,resource_info,windows,MagickFalse,
4745 "Help Viewer - Image Cut",ImageCutHelp);
4751 case CropDismissCommand:
4769 if (event.xbutton.button != Button1)
4771 if (event.xbutton.window != windows->image.id)
4774 Note first corner of cropping rectangle-- exit loop.
4776 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4777 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4778 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4788 if (event.xkey.window != windows->image.id)
4791 Respond to a user key press.
4793 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4794 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4795 switch ((int) key_symbol)
4814 XTextViewWidget(display,resource_info,windows,MagickFalse,
4815 "Help Viewer - Image Copy",ImageCopyHelp);
4820 XTextViewWidget(display,resource_info,windows,MagickFalse,
4821 "Help Viewer - Image Crop",ImageCropHelp);
4826 XTextViewWidget(display,resource_info,windows,MagickFalse,
4827 "Help Viewer - Image Cut",ImageCutHelp);
4835 (void) XBell(display,0);
4843 if (event.xmotion.window != windows->image.id)
4846 Map and unmap Info widget as text cursor crosses its boundaries.
4850 if (windows->info.mapped != MagickFalse)
4852 if ((x < (int) (windows->info.x+windows->info.width)) &&
4853 (y < (int) (windows->info.y+windows->info.height)))
4854 (void) XWithdrawWindow(display,windows->info.id,
4855 windows->info.screen);
4858 if ((x > (int) (windows->info.x+windows->info.width)) ||
4859 (y > (int) (windows->info.y+windows->info.height)))
4860 (void) XMapWindow(display,windows->info.id);
4861 crop_info.x=(ssize_t) windows->image.x+x;
4862 crop_info.y=(ssize_t) windows->image.y+y;
4868 } while ((state & ExitState) == 0);
4869 (void) XSelectInput(display,windows->image.id,
4870 windows->image.attributes.event_mask);
4871 if ((state & EscapeState) != 0)
4874 User want to exit without cropping.
4876 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4877 (void) XFreeCursor(display,cursor);
4880 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4884 Size rectangle as pointer moves until the mouse button is released.
4886 x=(int) crop_info.x;
4887 y=(int) crop_info.y;
4893 highlight_info=crop_info;
4894 highlight_info.x=crop_info.x-windows->image.x;
4895 highlight_info.y=crop_info.y-windows->image.y;
4896 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4899 Display info and draw cropping rectangle.
4901 if (windows->info.mapped == MagickFalse)
4902 (void) XMapWindow(display,windows->info.id);
4903 (void) FormatLocaleString(text,MaxTextExtent,
4904 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4905 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4906 XInfoWidget(display,windows,text);
4907 XHighlightRectangle(display,windows->image.id,
4908 windows->image.highlight_context,&highlight_info);
4911 if (windows->info.mapped != MagickFalse)
4912 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4914 Wait for next event.
4916 XScreenEvent(display,windows,&event,exception);
4917 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4918 XHighlightRectangle(display,windows->image.id,
4919 windows->image.highlight_context,&highlight_info);
4924 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4925 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4931 User has committed to cropping rectangle.
4933 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4934 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4935 XSetCursorState(display,windows,MagickFalse);
4937 windows->command.data=0;
4938 (void) XCommandWidget(display,windows,RectifyModeMenu,
4946 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4947 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4952 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4953 ((state & ExitState) != 0))
4956 Check boundary conditions.
4958 if (crop_info.x < 0)
4961 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4962 crop_info.x=(ssize_t) windows->image.ximage->width;
4963 if ((int) crop_info.x < x)
4964 crop_info.width=(unsigned int) (x-crop_info.x);
4967 crop_info.width=(unsigned int) (crop_info.x-x);
4968 crop_info.x=(ssize_t) x;
4970 if (crop_info.y < 0)
4973 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4974 crop_info.y=(ssize_t) windows->image.ximage->height;
4975 if ((int) crop_info.y < y)
4976 crop_info.height=(unsigned int) (y-crop_info.y);
4979 crop_info.height=(unsigned int) (crop_info.y-y);
4980 crop_info.y=(ssize_t) y;
4983 } while ((state & ExitState) == 0);
4985 Wait for user to grab a corner of the rectangle or press return.
4988 (void) XMapWindow(display,windows->info.id);
4991 if (windows->info.mapped != MagickFalse)
4994 Display pointer position.
4996 (void) FormatLocaleString(text,MaxTextExtent,
4997 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4998 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4999 XInfoWidget(display,windows,text);
5001 highlight_info=crop_info;
5002 highlight_info.x=crop_info.x-windows->image.x;
5003 highlight_info.y=crop_info.y-windows->image.y;
5004 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
5010 XHighlightRectangle(display,windows->image.id,
5011 windows->image.highlight_context,&highlight_info);
5012 XScreenEvent(display,windows,&event,exception);
5013 if (event.xany.window == windows->command.id)
5016 Select a command from the Command widget.
5018 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5019 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5020 (void) XSetFunction(display,windows->image.highlight_context,
5022 XHighlightRectangle(display,windows->image.id,
5023 windows->image.highlight_context,&highlight_info);
5025 switch (RectifyCommands[id])
5027 case RectifyCopyCommand:
5032 case RectifyHelpCommand:
5034 (void) XSetFunction(display,windows->image.highlight_context,
5040 XTextViewWidget(display,resource_info,windows,MagickFalse,
5041 "Help Viewer - Image Copy",ImageCopyHelp);
5046 XTextViewWidget(display,resource_info,windows,MagickFalse,
5047 "Help Viewer - Image Crop",ImageCropHelp);
5052 XTextViewWidget(display,resource_info,windows,MagickFalse,
5053 "Help Viewer - Image Cut",ImageCutHelp);
5057 (void) XSetFunction(display,windows->image.highlight_context,
5061 case RectifyDismissCommand:
5075 XHighlightRectangle(display,windows->image.id,
5076 windows->image.highlight_context,&highlight_info);
5081 if (event.xbutton.button != Button1)
5083 if (event.xbutton.window != windows->image.id)
5085 x=windows->image.x+event.xbutton.x;
5086 y=windows->image.y+event.xbutton.y;
5087 if ((x < (int) (crop_info.x+RoiDelta)) &&
5088 (x > (int) (crop_info.x-RoiDelta)) &&
5089 (y < (int) (crop_info.y+RoiDelta)) &&
5090 (y > (int) (crop_info.y-RoiDelta)))
5092 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5093 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5094 state|=UpdateConfigurationState;
5097 if ((x < (int) (crop_info.x+RoiDelta)) &&
5098 (x > (int) (crop_info.x-RoiDelta)) &&
5099 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5100 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5102 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5103 state|=UpdateConfigurationState;
5106 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5107 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5108 (y < (int) (crop_info.y+RoiDelta)) &&
5109 (y > (int) (crop_info.y-RoiDelta)))
5111 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5112 state|=UpdateConfigurationState;
5115 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5116 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5117 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5118 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5120 state|=UpdateConfigurationState;
5126 if (event.xbutton.window == windows->pan.id)
5127 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5128 (highlight_info.y != crop_info.y-windows->image.y))
5129 XHighlightRectangle(display,windows->image.id,
5130 windows->image.highlight_context,&highlight_info);
5131 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5132 event.xbutton.time);
5137 if (event.xexpose.window == windows->image.id)
5138 if (event.xexpose.count == 0)
5140 event.xexpose.x=(int) highlight_info.x;
5141 event.xexpose.y=(int) highlight_info.y;
5142 event.xexpose.width=(int) highlight_info.width;
5143 event.xexpose.height=(int) highlight_info.height;
5144 XRefreshWindow(display,&windows->image,&event);
5146 if (event.xexpose.window == windows->info.id)
5147 if (event.xexpose.count == 0)
5148 XInfoWidget(display,windows,text);
5153 if (event.xkey.window != windows->image.id)
5156 Respond to a user key press.
5158 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5159 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5160 switch ((int) key_symbol)
5173 crop_info.x=(ssize_t) (windows->image.width/2L-
5174 crop_info.width/2L);
5175 crop_info.y=(ssize_t) (windows->image.height/2L-
5176 crop_info.height/2L);
5208 (void) XSetFunction(display,windows->image.highlight_context,
5214 XTextViewWidget(display,resource_info,windows,MagickFalse,
5215 "Help Viewer - Image Copy",ImageCopyHelp);
5220 XTextViewWidget(display,resource_info,windows,MagickFalse,
5221 "Help Viewer - Image Cropg",ImageCropHelp);
5226 XTextViewWidget(display,resource_info,windows,MagickFalse,
5227 "Help Viewer - Image Cutg",ImageCutHelp);
5231 (void) XSetFunction(display,windows->image.highlight_context,
5237 (void) XBell(display,0);
5241 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5249 if (event.xmotion.window != windows->image.id)
5252 Map and unmap Info widget as text cursor crosses its boundaries.
5256 if (windows->info.mapped != MagickFalse)
5258 if ((x < (int) (windows->info.x+windows->info.width)) &&
5259 (y < (int) (windows->info.y+windows->info.height)))
5260 (void) XWithdrawWindow(display,windows->info.id,
5261 windows->info.screen);
5264 if ((x > (int) (windows->info.x+windows->info.width)) ||
5265 (y > (int) (windows->info.y+windows->info.height)))
5266 (void) XMapWindow(display,windows->info.id);
5267 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5268 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5271 case SelectionRequest:
5276 XSelectionRequestEvent
5280 Set primary selection.
5282 (void) FormatLocaleString(text,MaxTextExtent,
5283 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5284 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5285 request=(&(event.xselectionrequest));
5286 (void) XChangeProperty(request->display,request->requestor,
5287 request->property,request->target,8,PropModeReplace,
5288 (unsigned char *) text,(int) strlen(text));
5289 notify.type=SelectionNotify;
5290 notify.display=request->display;
5291 notify.requestor=request->requestor;
5292 notify.selection=request->selection;
5293 notify.target=request->target;
5294 notify.time=request->time;
5295 if (request->property == None)
5296 notify.property=request->target;
5298 notify.property=request->property;
5299 (void) XSendEvent(request->display,request->requestor,False,0,
5300 (XEvent *) ¬ify);
5305 if ((state & UpdateConfigurationState) != 0)
5307 (void) XPutBackEvent(display,&event);
5308 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5311 } while ((state & ExitState) == 0);
5312 } while ((state & ExitState) == 0);
5313 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5314 XSetCursorState(display,windows,MagickFalse);
5315 if ((state & EscapeState) != 0)
5317 if (mode == CropMode)
5318 if (((int) crop_info.width != windows->image.ximage->width) ||
5319 ((int) crop_info.height != windows->image.ximage->height))
5322 Reconfigure Image window as defined by cropping rectangle.
5324 XSetCropGeometry(display,windows,&crop_info,image);
5325 windows->image.window_changes.width=(int) crop_info.width;
5326 windows->image.window_changes.height=(int) crop_info.height;
5327 (void) XConfigureImage(display,resource_info,windows,image,exception);
5331 Copy image before applying image transforms.
5333 XSetCursorState(display,windows,MagickTrue);
5334 XCheckRefreshWindows(display,windows);
5335 width=(unsigned int) image->columns;
5336 height=(unsigned int) image->rows;
5339 if (windows->image.crop_geometry != (char *) NULL)
5340 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5341 scale_factor=(MagickRealType) width/windows->image.ximage->width;
5343 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5344 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5345 scale_factor=(MagickRealType) height/windows->image.ximage->height;
5347 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5348 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5349 crop_image=CropImage(image,&crop_info,exception);
5350 XSetCursorState(display,windows,MagickFalse);
5351 if (crop_image == (Image *) NULL)
5352 return(MagickFalse);
5353 if (resource_info->copy_image != (Image *) NULL)
5354 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5355 resource_info->copy_image=crop_image;
5356 if (mode == CopyMode)
5358 (void) XConfigureImage(display,resource_info,windows,image,exception);
5364 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
5365 return(MagickFalse);
5366 image->matte=MagickTrue;
5367 image_view=AcquireCacheView(image);
5368 for (y=0; y < (int) crop_info.height; y++)
5370 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5371 crop_info.width,1,exception);
5372 if (q == (Quantum *) NULL)
5374 for (x=0; x < (int) crop_info.width; x++)
5376 SetPixelAlpha(image,TransparentAlpha,q);
5377 q+=GetPixelChannels(image);
5379 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
5382 image_view=DestroyCacheView(image_view);
5384 Update image configuration.
5386 XConfigureImageColormap(display,resource_info,windows,image,exception);
5387 (void) XConfigureImage(display,resource_info,windows,image,exception);
5392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5396 + X D r a w I m a g e %
5400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5402 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5405 % The format of the XDrawEditImage method is:
5407 % MagickBooleanType XDrawEditImage(Display *display,
5408 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5409 % ExceptionInfo *exception)
5411 % A description of each parameter follows:
5413 % o display: Specifies a connection to an X server; returned from
5416 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5418 % o windows: Specifies a pointer to a XWindows structure.
5420 % o image: the image.
5422 % o exception: return any errors or warnings in this structure.
5425 static MagickBooleanType XDrawEditImage(Display *display,
5426 XResourceInfo *resource_info,XWindows *windows,Image **image,
5427 ExceptionInfo *exception)
5443 element = PointElement;
5445 static const ModeType
5458 stipple = (Pixmap) NULL;
5465 command[MaxTextExtent],
5466 text[MaxTextExtent];
5515 Allocate polygon info.
5517 max_coordinates=2048;
5518 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5519 sizeof(*coordinate_info));
5520 if (coordinate_info == (XPoint *) NULL)
5522 (void) ThrowMagickException(exception,GetMagickModule(),
5523 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5524 return(MagickFalse);
5529 (void) CloneString(&windows->command.name,"Draw");
5530 windows->command.data=4;
5531 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5532 (void) XMapRaised(display,windows->command.id);
5533 XClientMessage(display,windows->image.id,windows->im_protocols,
5534 windows->im_update_widget,CurrentTime);
5536 Wait for first button press.
5538 root_window=XRootWindow(display,XDefaultScreen(display));
5539 draw_info.stencil=OpaqueStencil;
5541 cursor=XCreateFontCursor(display,XC_tcross);
5544 XQueryPosition(display,windows->image.id,&x,&y);
5545 (void) XSelectInput(display,windows->image.id,
5546 windows->image.attributes.event_mask | PointerMotionMask);
5547 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5551 if (windows->info.mapped != MagickFalse)
5554 Display pointer position.
5556 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5557 x+windows->image.x,y+windows->image.y);
5558 XInfoWidget(display,windows,text);
5561 Wait for next event.
5563 XScreenEvent(display,windows,&event,exception);
5564 if (event.xany.window == windows->command.id)
5567 Select a command from the Command widget.
5569 id=XCommandWidget(display,windows,DrawMenu,&event);
5572 switch (DrawCommands[id])
5574 case DrawElementCommand:
5593 Select a command from the pop-up menu.
5595 element=(ElementType) (XMenuWidget(display,windows,
5596 DrawMenu[id],Elements,command)+1);
5599 case DrawColorCommand:
5602 *ColorMenu[MaxNumberPens+1];
5614 Initialize menu selections.
5616 for (i=0; i < (int) (MaxNumberPens-2); i++)
5617 ColorMenu[i]=resource_info->pen_colors[i];
5618 ColorMenu[MaxNumberPens-2]="transparent";
5619 ColorMenu[MaxNumberPens-1]="Browser...";
5620 ColorMenu[MaxNumberPens]=(char *) NULL;
5622 Select a pen color from the pop-up menu.
5624 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5625 (const char **) ColorMenu,command);
5628 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5630 if (transparent != MagickFalse)
5632 draw_info.stencil=TransparentStencil;
5635 if (pen_number == (MaxNumberPens-1))
5638 color_name[MaxTextExtent] = "gray";
5641 Select a pen color from a dialog.
5643 resource_info->pen_colors[pen_number]=color_name;
5644 XColorBrowserWidget(display,windows,"Select",color_name);
5645 if (*color_name == '\0')
5651 (void) XParseColor(display,windows->map_info->colormap,
5652 resource_info->pen_colors[pen_number],&color);
5653 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5654 (unsigned int) MaxColors,&color);
5655 windows->pixel_info->pen_colors[pen_number]=color;
5656 pen_id=(unsigned int) pen_number;
5657 draw_info.stencil=OpaqueStencil;
5660 case DrawStippleCommand:
5672 filename[MaxTextExtent] = "\0";
5689 Select a command from the pop-up menu.
5691 StipplesMenu[7]="Open...";
5692 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5696 if (stipple != (Pixmap) NULL)
5697 (void) XFreePixmap(display,stipple);
5698 stipple=(Pixmap) NULL;
5705 stipple=XCreateBitmapFromData(display,root_window,
5706 (char *) BricksBitmap,BricksWidth,BricksHeight);
5711 stipple=XCreateBitmapFromData(display,root_window,
5712 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5717 stipple=XCreateBitmapFromData(display,root_window,
5718 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5723 stipple=XCreateBitmapFromData(display,root_window,
5724 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5729 stipple=XCreateBitmapFromData(display,root_window,
5730 (char *) WavyBitmap,WavyWidth,WavyHeight);
5735 stipple=XCreateBitmapFromData(display,root_window,
5736 (char *) HighlightBitmap,HighlightWidth,
5743 stipple=XCreateBitmapFromData(display,root_window,
5744 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5750 XFileBrowserWidget(display,windows,"Stipple",filename);
5751 if (*filename == '\0')
5756 XSetCursorState(display,windows,MagickTrue);
5757 XCheckRefreshWindows(display,windows);
5758 image_info=AcquireImageInfo();
5759 (void) CopyMagickString(image_info->filename,filename,
5761 stipple_image=ReadImage(image_info,exception);
5762 CatchException(exception);
5763 XSetCursorState(display,windows,MagickFalse);
5764 if (stipple_image == (Image *) NULL)
5766 (void) AcquireUniqueFileResource(filename);
5767 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5769 (void) WriteImage(image_info,stipple_image,exception);
5770 stipple_image=DestroyImage(stipple_image);
5771 image_info=DestroyImageInfo(image_info);
5772 status=XReadBitmapFile(display,root_window,filename,&width,
5773 &height,&stipple,&x,&y);
5774 (void) RelinquishUniqueFileResource(filename);
5775 if ((status != BitmapSuccess) != 0)
5776 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5780 case DrawWidthCommand:
5783 width[MaxTextExtent] = "0";
5798 Select a command from the pop-up menu.
5800 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5806 line_width=(unsigned int) StringToUnsignedLong(
5810 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5814 line_width=(unsigned int) StringToUnsignedLong(width);
5817 case DrawUndoCommand:
5819 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5823 case DrawHelpCommand:
5825 XTextViewWidget(display,resource_info,windows,MagickFalse,
5826 "Help Viewer - Image Rotation",ImageDrawHelp);
5827 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5830 case DrawDismissCommand:
5842 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5849 if (event.xbutton.button != Button1)
5851 if (event.xbutton.window != windows->image.id)
5870 if (event.xkey.window != windows->image.id)
5873 Respond to a user key press.
5875 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5876 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5877 switch ((int) key_symbol)
5892 XTextViewWidget(display,resource_info,windows,MagickFalse,
5893 "Help Viewer - Image Rotation",ImageDrawHelp);
5898 (void) XBell(display,0);
5907 Map and unmap Info widget as text cursor crosses its boundaries.
5911 if (windows->info.mapped != MagickFalse)
5913 if ((x < (int) (windows->info.x+windows->info.width)) &&
5914 (y < (int) (windows->info.y+windows->info.height)))
5915 (void) XWithdrawWindow(display,windows->info.id,
5916 windows->info.screen);
5919 if ((x > (int) (windows->info.x+windows->info.width)) ||
5920 (y > (int) (windows->info.y+windows->info.height)))
5921 (void) XMapWindow(display,windows->info.id);
5925 } while ((state & ExitState) == 0);
5926 (void) XSelectInput(display,windows->image.id,
5927 windows->image.attributes.event_mask);
5928 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5929 if ((state & EscapeState) != 0)
5932 Draw element as pointer moves until the button is released.
5940 rectangle_info.x=(ssize_t) x;
5941 rectangle_info.y=(ssize_t) y;
5942 rectangle_info.width=0;
5943 rectangle_info.height=0;
5944 number_coordinates=1;
5945 coordinate_info->x=x;
5946 coordinate_info->y=y;
5947 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5956 if (number_coordinates > 1)
5958 (void) XDrawLines(display,windows->image.id,
5959 windows->image.highlight_context,coordinate_info,
5960 number_coordinates,CoordModeOrigin);
5961 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5962 coordinate_info[number_coordinates-1].x,
5963 coordinate_info[number_coordinates-1].y);
5964 XInfoWidget(display,windows,text);
5973 Display angle of the line.
5975 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5976 line_info.y1),(double) (line_info.x2-line_info.x1)));
5977 (void) FormatLocaleString(text,MaxTextExtent," %g",
5979 XInfoWidget(display,windows,text);
5980 XHighlightLine(display,windows->image.id,
5981 windows->image.highlight_context,&line_info);
5984 if (windows->info.mapped != MagickFalse)
5985 (void) XWithdrawWindow(display,windows->info.id,
5986 windows->info.screen);
5989 case RectangleElement:
5990 case FillRectangleElement:
5992 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5995 Display info and draw drawing rectangle.
5997 (void) FormatLocaleString(text,MaxTextExtent,
5998 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5999 (double) rectangle_info.height,(double) rectangle_info.x,
6000 (double) rectangle_info.y);
6001 XInfoWidget(display,windows,text);
6002 XHighlightRectangle(display,windows->image.id,
6003 windows->image.highlight_context,&rectangle_info);
6006 if (windows->info.mapped != MagickFalse)
6007 (void) XWithdrawWindow(display,windows->info.id,
6008 windows->info.screen);
6012 case FillCircleElement:
6013 case EllipseElement:
6014 case FillEllipseElement:
6016 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6019 Display info and draw drawing rectangle.
6021 (void) FormatLocaleString(text,MaxTextExtent,
6022 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6023 (double) rectangle_info.height,(double) rectangle_info.x,
6024 (double) rectangle_info.y);
6025 XInfoWidget(display,windows,text);
6026 XHighlightEllipse(display,windows->image.id,
6027 windows->image.highlight_context,&rectangle_info);
6030 if (windows->info.mapped != MagickFalse)
6031 (void) XWithdrawWindow(display,windows->info.id,
6032 windows->info.screen);
6035 case PolygonElement:
6036 case FillPolygonElement:
6038 if (number_coordinates > 1)
6039 (void) XDrawLines(display,windows->image.id,
6040 windows->image.highlight_context,coordinate_info,
6041 number_coordinates,CoordModeOrigin);
6045 Display angle of the line.
6047 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6048 line_info.y1),(double) (line_info.x2-line_info.x1)));
6049 (void) FormatLocaleString(text,MaxTextExtent," %g",
6051 XInfoWidget(display,windows,text);
6052 XHighlightLine(display,windows->image.id,
6053 windows->image.highlight_context,&line_info);
6056 if (windows->info.mapped != MagickFalse)
6057 (void) XWithdrawWindow(display,windows->info.id,
6058 windows->info.screen);
6063 Wait for next event.
6065 XScreenEvent(display,windows,&event,exception);
6071 if (number_coordinates > 1)
6072 (void) XDrawLines(display,windows->image.id,
6073 windows->image.highlight_context,coordinate_info,
6074 number_coordinates,CoordModeOrigin);
6080 XHighlightLine(display,windows->image.id,
6081 windows->image.highlight_context,&line_info);
6084 case RectangleElement:
6085 case FillRectangleElement:
6087 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6088 XHighlightRectangle(display,windows->image.id,
6089 windows->image.highlight_context,&rectangle_info);
6093 case FillCircleElement:
6094 case EllipseElement:
6095 case FillEllipseElement:
6097 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6098 XHighlightEllipse(display,windows->image.id,
6099 windows->image.highlight_context,&rectangle_info);
6102 case PolygonElement:
6103 case FillPolygonElement:
6105 if (number_coordinates > 1)
6106 (void) XDrawLines(display,windows->image.id,
6107 windows->image.highlight_context,coordinate_info,
6108 number_coordinates,CoordModeOrigin);
6110 XHighlightLine(display,windows->image.id,
6111 windows->image.highlight_context,&line_info);
6122 User has committed to element.
6124 line_info.x2=event.xbutton.x;
6125 line_info.y2=event.xbutton.y;
6126 rectangle_info.x=(ssize_t) event.xbutton.x;
6127 rectangle_info.y=(ssize_t) event.xbutton.y;
6128 coordinate_info[number_coordinates].x=event.xbutton.x;
6129 coordinate_info[number_coordinates].y=event.xbutton.y;
6130 if (((element != PolygonElement) &&
6131 (element != FillPolygonElement)) || (distance <= 9))
6136 number_coordinates++;
6137 if (number_coordinates < (int) max_coordinates)
6139 line_info.x1=event.xbutton.x;
6140 line_info.y1=event.xbutton.y;
6143 max_coordinates<<=1;
6144 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6145 max_coordinates,sizeof(*coordinate_info));
6146 if (coordinate_info == (XPoint *) NULL)
6147 (void) ThrowMagickException(exception,GetMagickModule(),
6148 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6155 if (event.xmotion.window != windows->image.id)
6157 if (element != PointElement)
6159 line_info.x2=event.xmotion.x;
6160 line_info.y2=event.xmotion.y;
6161 rectangle_info.x=(ssize_t) event.xmotion.x;
6162 rectangle_info.y=(ssize_t) event.xmotion.y;
6165 coordinate_info[number_coordinates].x=event.xbutton.x;
6166 coordinate_info[number_coordinates].y=event.xbutton.y;
6167 number_coordinates++;
6168 if (number_coordinates < (int) max_coordinates)
6170 max_coordinates<<=1;
6171 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6172 max_coordinates,sizeof(*coordinate_info));
6173 if (coordinate_info == (XPoint *) NULL)
6174 (void) ThrowMagickException(exception,GetMagickModule(),
6175 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6182 Check boundary conditions.
6184 if (line_info.x2 < 0)
6187 if (line_info.x2 > (int) windows->image.width)
6188 line_info.x2=(short) windows->image.width;
6189 if (line_info.y2 < 0)
6192 if (line_info.y2 > (int) windows->image.height)
6193 line_info.y2=(short) windows->image.height;
6194 distance=(unsigned int)
6195 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6196 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6197 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6198 ((state & ExitState) != 0))
6200 if (rectangle_info.x < 0)
6203 if (rectangle_info.x > (ssize_t) windows->image.width)
6204 rectangle_info.x=(ssize_t) windows->image.width;
6205 if ((int) rectangle_info.x < x)
6206 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6209 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6210 rectangle_info.x=(ssize_t) x;
6212 if (rectangle_info.y < 0)
6215 if (rectangle_info.y > (ssize_t) windows->image.height)
6216 rectangle_info.y=(ssize_t) windows->image.height;
6217 if ((int) rectangle_info.y < y)
6218 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6221 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6222 rectangle_info.y=(ssize_t) y;
6225 } while ((state & ExitState) == 0);
6226 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6227 if ((element == PointElement) || (element == PolygonElement) ||
6228 (element == FillPolygonElement))
6231 Determine polygon bounding box.
6233 rectangle_info.x=(ssize_t) coordinate_info->x;
6234 rectangle_info.y=(ssize_t) coordinate_info->y;
6235 x=coordinate_info->x;
6236 y=coordinate_info->y;
6237 for (i=1; i < number_coordinates; i++)
6239 if (coordinate_info[i].x > x)
6240 x=coordinate_info[i].x;
6241 if (coordinate_info[i].y > y)
6242 y=coordinate_info[i].y;
6243 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6244 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6245 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6246 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6248 rectangle_info.width=(size_t) (x-rectangle_info.x);
6249 rectangle_info.height=(size_t) (y-rectangle_info.y);
6250 for (i=0; i < number_coordinates; i++)
6252 coordinate_info[i].x-=rectangle_info.x;
6253 coordinate_info[i].y-=rectangle_info.y;
6260 if ((element == RectangleElement) ||
6261 (element == CircleElement) || (element == EllipseElement))
6263 rectangle_info.width--;
6264 rectangle_info.height--;
6267 Drawing is relative to image configuration.
6269 draw_info.x=(int) rectangle_info.x;
6270 draw_info.y=(int) rectangle_info.y;
6271 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6273 width=(unsigned int) (*image)->columns;
6274 height=(unsigned int) (*image)->rows;
6277 if (windows->image.crop_geometry != (char *) NULL)
6278 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6279 draw_info.x+=windows->image.x-(line_width/2);
6280 if (draw_info.x < 0)
6282 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6283 draw_info.y+=windows->image.y-(line_width/2);
6284 if (draw_info.y < 0)
6286 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6287 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6288 if (draw_info.width > (unsigned int) (*image)->columns)
6289 draw_info.width=(unsigned int) (*image)->columns;
6290 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6291 if (draw_info.height > (unsigned int) (*image)->rows)
6292 draw_info.height=(unsigned int) (*image)->rows;
6293 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6294 width*draw_info.width/windows->image.ximage->width,
6295 height*draw_info.height/windows->image.ximage->height,
6296 draw_info.x+x,draw_info.y+y);
6298 Initialize drawing attributes.
6300 draw_info.degrees=0.0;
6301 draw_info.element=element;
6302 draw_info.stipple=stipple;
6303 draw_info.line_width=line_width;
6304 draw_info.line_info=line_info;
6305 if (line_info.x1 > (int) (line_width/2))
6306 draw_info.line_info.x1=(short) line_width/2;
6307 if (line_info.y1 > (int) (line_width/2))
6308 draw_info.line_info.y1=(short) line_width/2;
6309 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6310 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6311 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6313 draw_info.line_info.x2=(-draw_info.line_info.x2);
6314 draw_info.line_info.y2=(-draw_info.line_info.y2);
6316 if (draw_info.line_info.x2 < 0)
6318 draw_info.line_info.x2=(-draw_info.line_info.x2);
6319 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6321 if (draw_info.line_info.y2 < 0)
6323 draw_info.line_info.y2=(-draw_info.line_info.y2);
6324 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6326 draw_info.rectangle_info=rectangle_info;
6327 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6328 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6329 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6330 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6331 draw_info.number_coordinates=(unsigned int) number_coordinates;
6332 draw_info.coordinate_info=coordinate_info;
6333 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6335 Draw element on image.
6337 XSetCursorState(display,windows,MagickTrue);
6338 XCheckRefreshWindows(display,windows);
6339 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6340 XSetCursorState(display,windows,MagickFalse);
6342 Update image colormap and return to image drawing.
6344 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6345 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6347 XSetCursorState(display,windows,MagickFalse);
6348 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6349 return(status != 0 ? MagickTrue : MagickFalse);
6353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6357 + X D r a w P a n R e c t a n g l e %
6361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6363 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6364 % displays a zoom image and the rectangle shows which portion of the image is
6365 % displayed in the Image window.
6367 % The format of the XDrawPanRectangle method is:
6369 % XDrawPanRectangle(Display *display,XWindows *windows)
6371 % A description of each parameter follows:
6373 % o display: Specifies a connection to an X server; returned from
6376 % o windows: Specifies a pointer to a XWindows structure.
6379 static void XDrawPanRectangle(Display *display,XWindows *windows)
6388 Determine dimensions of the panning rectangle.
6390 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
6391 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6392 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6393 scale_factor=(MagickRealType)
6394 windows->pan.height/windows->image.ximage->height;
6395 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6396 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6398 Display the panning rectangle.
6400 (void) XClearWindow(display,windows->pan.id);
6401 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6410 + X I m a g e C a c h e %
6414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6416 % XImageCache() handles the creation, manipulation, and destruction of the
6417 % image cache (undo and redo buffers).
6419 % The format of the XImageCache method is:
6421 % void XImageCache(Display *display,XResourceInfo *resource_info,
6422 % XWindows *windows,const CommandType command,Image **image,
6423 % ExceptionInfo *exception)
6425 % A description of each parameter follows:
6427 % o display: Specifies a connection to an X server; returned from
6430 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6432 % o windows: Specifies a pointer to a XWindows structure.
6434 % o command: Specifies a command to perform.
6436 % o image: the image; XImageCache may transform the image and return a new
6439 % o exception: return any errors or warnings in this structure.
6442 static void XImageCache(Display *display,XResourceInfo *resource_info,
6443 XWindows *windows,const CommandType command,Image **image,
6444 ExceptionInfo *exception)
6450 *redo_image = (Image *) NULL,
6451 *undo_image = (Image *) NULL;
6455 case FreeBuffersCommand:
6458 Free memory from the undo and redo cache.
6460 while (undo_image != (Image *) NULL)
6462 cache_image=undo_image;
6463 undo_image=GetPreviousImageInList(undo_image);
6464 cache_image->list=DestroyImage(cache_image->list);
6465 cache_image=DestroyImage(cache_image);
6467 undo_image=NewImageList();
6468 if (redo_image != (Image *) NULL)
6469 redo_image=DestroyImage(redo_image);
6470 redo_image=NewImageList();
6476 image_geometry[MaxTextExtent];
6479 Undo the last image transformation.
6481 if (undo_image == (Image *) NULL)
6483 (void) XBell(display,0);
6486 cache_image=undo_image;
6487 undo_image=GetPreviousImageInList(undo_image);
6488 windows->image.window_changes.width=(int) cache_image->columns;
6489 windows->image.window_changes.height=(int) cache_image->rows;
6490 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6491 windows->image.ximage->width,windows->image.ximage->height);
6492 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6494 if (windows->image.crop_geometry != (char *) NULL)
6495 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6496 windows->image.crop_geometry);
6497 windows->image.crop_geometry=cache_image->geometry;
6498 if (redo_image != (Image *) NULL)
6499 redo_image=DestroyImage(redo_image);
6500 redo_image=(*image);
6501 *image=cache_image->list;
6502 cache_image=DestroyImage(cache_image);
6503 if (windows->image.orphan != MagickFalse)
6505 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6506 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6512 case HalfSizeCommand:
6513 case OriginalSizeCommand:
6514 case DoubleSizeCommand:
6521 case RotateRightCommand:
6522 case RotateLeftCommand:
6527 case ContrastStretchCommand:
6528 case SigmoidalContrastCommand:
6529 case NormalizeCommand:
6530 case EqualizeCommand:
6532 case SaturationCommand:
6533 case BrightnessCommand:
6537 case GrayscaleCommand:
6539 case QuantizeCommand:
6540 case DespeckleCommand:
6542 case ReduceNoiseCommand:
6543 case AddNoiseCommand:
6544 case SharpenCommand:
6546 case ThresholdCommand:
6547 case EdgeDetectCommand:
6551 case SegmentCommand:
6552 case SolarizeCommand:
6553 case SepiaToneCommand:
6555 case ImplodeCommand:
6556 case VignetteCommand:
6558 case OilPaintCommand:
6559 case CharcoalDrawCommand:
6560 case AnnotateCommand:
6561 case AddBorderCommand:
6562 case AddFrameCommand:
6563 case CompositeCommand:
6564 case CommentCommand:
6566 case RegionofInterestCommand:
6567 case SaveToUndoBufferCommand:
6576 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6577 if (undo_image != (Image *) NULL)
6580 Ensure the undo cache has enough memory available.
6582 previous_image=undo_image;
6583 while (previous_image != (Image *) NULL)
6585 bytes+=previous_image->list->columns*previous_image->list->rows*
6587 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6589 previous_image=GetPreviousImageInList(previous_image);
6592 bytes-=previous_image->list->columns*previous_image->list->rows*
6594 if (previous_image == undo_image)
6595 undo_image=NewImageList();
6597 previous_image->next->previous=NewImageList();
6600 while (previous_image != (Image *) NULL)
6603 Delete any excess memory from undo cache.
6605 cache_image=previous_image;
6606 previous_image=GetPreviousImageInList(previous_image);
6607 cache_image->list=DestroyImage(cache_image->list);
6608 cache_image=DestroyImage(cache_image);
6611 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6614 Save image before transformations are applied.
6616 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6617 if (cache_image == (Image *) NULL)
6619 XSetCursorState(display,windows,MagickTrue);
6620 XCheckRefreshWindows(display,windows);
6621 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6622 XSetCursorState(display,windows,MagickFalse);
6623 if (cache_image->list == (Image *) NULL)
6625 cache_image=DestroyImage(cache_image);
6628 cache_image->columns=(size_t) windows->image.ximage->width;
6629 cache_image->rows=(size_t) windows->image.ximage->height;
6630 cache_image->geometry=windows->image.crop_geometry;
6631 if (windows->image.crop_geometry != (char *) NULL)
6633 cache_image->geometry=AcquireString((char *) NULL);
6634 (void) CopyMagickString(cache_image->geometry,
6635 windows->image.crop_geometry,MaxTextExtent);
6637 if (undo_image == (Image *) NULL)
6639 undo_image=cache_image;
6642 undo_image->next=cache_image;
6643 undo_image->next->previous=undo_image;
6644 undo_image=undo_image->next;
6650 if (command == RedoCommand)
6653 Redo the last image transformation.
6655 if (redo_image == (Image *) NULL)
6657 (void) XBell(display,0);
6660 windows->image.window_changes.width=(int) redo_image->columns;
6661 windows->image.window_changes.height=(int) redo_image->rows;
6662 if (windows->image.crop_geometry != (char *) NULL)
6663 windows->image.crop_geometry=(char *)
6664 RelinquishMagickMemory(windows->image.crop_geometry);
6665 windows->image.crop_geometry=redo_image->geometry;
6666 *image=DestroyImage(*image);
6668 redo_image=NewImageList();
6669 if (windows->image.orphan != MagickFalse)
6671 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6672 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6675 if (command != InfoCommand)
6680 XSetCursorState(display,windows,MagickTrue);
6681 XCheckRefreshWindows(display,windows);
6682 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6683 XSetCursorState(display,windows,MagickFalse);
6687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6691 + X I m a g e W i n d o w C o m m a n d %
6695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6697 % XImageWindowCommand() makes a transform to the image or Image window as
6698 % specified by a user menu button or keyboard command.
6700 % The format of the XImageWindowCommand method is:
6702 % CommandType XImageWindowCommand(Display *display,
6703 % XResourceInfo *resource_info,XWindows *windows,
6704 % const MagickStatusType state,KeySym key_symbol,Image **image,
6705 % ExceptionInfo *exception)
6707 % A description of each parameter follows:
6709 % o nexus: Method XImageWindowCommand returns an image when the
6710 % user chooses 'Open Image' from the command menu. Otherwise a null
6711 % image is returned.
6713 % o display: Specifies a connection to an X server; returned from
6716 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6718 % o windows: Specifies a pointer to a XWindows structure.
6720 % o state: key mask.
6722 % o key_symbol: Specifies a command to perform.
6724 % o image: the image; XImageWIndowCommand may transform the image and
6725 % return a new image pointer.
6727 % o exception: return any errors or warnings in this structure.
6730 static CommandType XImageWindowCommand(Display *display,
6731 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6732 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6735 delta[MaxTextExtent] = "";
6738 Digits[] = "01234567890";
6743 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6745 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6748 resource_info->quantum=1;
6750 last_symbol=key_symbol;
6751 delta[strlen(delta)+1]='\0';
6752 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6753 resource_info->quantum=StringToLong(delta);
6754 return(NullCommand);
6756 last_symbol=key_symbol;
6757 if (resource_info->immutable)
6760 Virtual image window has a restricted command set.
6765 return(InfoCommand);
6768 return(PrintCommand);
6770 return(NextCommand);
6773 return(QuitCommand);
6777 return(NullCommand);
6779 switch ((int) key_symbol)
6783 if ((state & ControlMask) == 0)
6785 return(OpenCommand);
6788 return(NextCommand);
6790 return(FormerCommand);
6793 if ((state & Mod1Mask) != 0)
6794 return(SwirlCommand);
6795 if ((state & ControlMask) == 0)
6796 return(ShearCommand);
6797 return(SaveCommand);
6802 if ((state & Mod1Mask) != 0)
6803 return(OilPaintCommand);
6804 if ((state & Mod4Mask) != 0)
6805 return(ColorCommand);
6806 if ((state & ControlMask) == 0)
6807 return(NullCommand);
6808 return(PrintCommand);
6812 if ((state & Mod4Mask) != 0)
6813 return(DrawCommand);
6814 if ((state & ControlMask) == 0)
6815 return(NullCommand);
6816 return(DeleteCommand);
6820 if ((state & ControlMask) == 0)
6821 return(NullCommand);
6822 return(SelectCommand);
6826 if ((state & ControlMask) == 0)
6827 return(NullCommand);
6832 return(QuitCommand);
6836 if ((state & ControlMask) == 0)
6837 return(NullCommand);
6838 return(UndoCommand);
6843 if ((state & ControlMask) == 0)
6844 return(RollCommand);
6845 return(RedoCommand);
6849 if ((state & ControlMask) == 0)
6850 return(NullCommand);
6855 if ((state & Mod1Mask) != 0)
6856 return(CharcoalDrawCommand);
6857 if ((state & ControlMask) == 0)
6858 return(CropCommand);
6859 return(CopyCommand);
6864 if ((state & Mod4Mask) != 0)
6865 return(CompositeCommand);
6866 if ((state & ControlMask) == 0)
6867 return(FlipCommand);
6868 return(PasteCommand);
6871 return(HalfSizeCommand);
6873 return(OriginalSizeCommand);
6875 return(DoubleSizeCommand);
6877 return(ResizeCommand);
6879 return(RefreshCommand);
6880 case XK_bracketleft:
6881 return(ChopCommand);
6883 return(FlopCommand);
6885 return(RotateRightCommand);
6887 return(RotateLeftCommand);
6889 return(RotateCommand);
6891 return(TrimCommand);
6895 return(SaturationCommand);
6897 return(BrightnessCommand);
6899 return(GammaCommand);
6901 return(SpiffCommand);
6903 return(DullCommand);
6905 return(NormalizeCommand);
6907 return(EqualizeCommand);
6909 return(NegateCommand);
6911 return(GrayscaleCommand);
6913 return(QuantizeCommand);
6915 return(DespeckleCommand);
6917 return(EmbossCommand);
6919 return(ReduceNoiseCommand);
6921 return(AddNoiseCommand);
6923 return(SharpenCommand);
6925 return(BlurCommand);
6927 return(ThresholdCommand);
6929 return(EdgeDetectCommand);
6931 return(SpreadCommand);
6933 return(ShadeCommand);
6935 return(RaiseCommand);
6937 return(SegmentCommand);
6940 if ((state & Mod1Mask) == 0)
6941 return(NullCommand);
6942 return(ImplodeCommand);
6946 if ((state & Mod1Mask) == 0)
6947 return(NullCommand);
6948 return(WaveCommand);
6952 if ((state & Mod4Mask) == 0)
6953 return(NullCommand);
6954 return(MatteCommand);
6958 if ((state & Mod4Mask) == 0)
6959 return(NullCommand);
6960 return(AddBorderCommand);
6964 if ((state & Mod4Mask) == 0)
6965 return(NullCommand);
6966 return(AddFrameCommand);
6970 if ((state & Mod4Mask) == 0)
6971 return(NullCommand);
6972 return(CommentCommand);
6976 if ((state & Mod1Mask) != 0)
6977 return(ApplyCommand);
6978 if ((state & Mod4Mask) != 0)
6979 return(AnnotateCommand);
6980 if ((state & ControlMask) == 0)
6981 return(NullCommand);
6982 return(RegionofInterestCommand);
6985 return(InfoCommand);
6987 return(ZoomCommand);
6990 if ((state & ShiftMask) == 0)
6991 return(NullCommand);
6992 return(ShowPreviewCommand);
6995 return(LaunchCommand);
6997 return(HelpCommand);
6999 return(BrowseDocumentationCommand);
7002 (void) XMapRaised(display,windows->command.id);
7003 return(NullCommand);
7010 XTranslateImage(display,windows,*image,key_symbol);
7011 return(NullCommand);
7022 if ((state & Mod1Mask) != 0)
7028 Trim one pixel from edge of image.
7032 crop_info.width=(size_t) windows->image.ximage->width;
7033 crop_info.height=(size_t) windows->image.ximage->height;
7034 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7036 if (resource_info->quantum >= (int) crop_info.height)
7037 resource_info->quantum=(int) crop_info.height-1;
7038 crop_info.height-=resource_info->quantum;
7040 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7042 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7043 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7044 crop_info.y+=resource_info->quantum;
7045 crop_info.height-=resource_info->quantum;
7047 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7049 if (resource_info->quantum >= (int) crop_info.width)
7050 resource_info->quantum=(int) crop_info.width-1;
7051 crop_info.width-=resource_info->quantum;
7053 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7055 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7056 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7057 crop_info.x+=resource_info->quantum;
7058 crop_info.width-=resource_info->quantum;
7060 if ((int) (windows->image.x+windows->image.width) >
7061 (int) crop_info.width)
7062 windows->image.x=(int) (crop_info.width-windows->image.width);
7063 if ((int) (windows->image.y+windows->image.height) >
7064 (int) crop_info.height)
7065 windows->image.y=(int) (crop_info.height-windows->image.height);
7066 XSetCropGeometry(display,windows,&crop_info,*image);
7067 windows->image.window_changes.width=(int) crop_info.width;
7068 windows->image.window_changes.height=(int) crop_info.height;
7069 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7070 (void) XConfigureImage(display,resource_info,windows,*image,
7072 return(NullCommand);
7074 XTranslateImage(display,windows,*image,key_symbol);
7075 return(NullCommand);
7078 return(NullCommand);
7080 return(NullCommand);
7084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7088 + X M a g i c k C o m m a n d %
7092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7094 % XMagickCommand() makes a transform to the image or Image window as
7095 % specified by a user menu button or keyboard command.
7097 % The format of the XMagickCommand method is:
7099 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7100 % XWindows *windows,const CommandType command,Image **image,
7101 % ExceptionInfo *exception)
7103 % A description of each parameter follows:
7105 % o display: Specifies a connection to an X server; returned from
7108 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7110 % o windows: Specifies a pointer to a XWindows structure.
7112 % o command: Specifies a command to perform.
7114 % o image: the image; XMagickCommand may transform the image and return a
7115 % new image pointer.
7117 % o exception: return any errors or warnings in this structure.
7120 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7121 XWindows *windows,const CommandType command,Image **image,
7122 ExceptionInfo *exception)
7125 filename[MaxTextExtent],
7126 geometry[MaxTextExtent],
7127 modulate_factors[MaxTextExtent];
7156 color[MaxTextExtent] = "gray";
7163 Process user command.
7165 XCheckRefreshWindows(display,windows);
7166 XImageCache(display,resource_info,windows,command,image,exception);
7167 nexus=NewImageList();
7168 windows->image.window_changes.width=windows->image.ximage->width;
7169 windows->image.window_changes.height=windows->image.ximage->height;
7170 image_info=CloneImageInfo(resource_info->image_info);
7171 SetGeometryInfo(&geometry_info);
7172 GetQuantizeInfo(&quantize_info);
7180 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7188 for (i=0; i < resource_info->quantum; i++)
7189 XClientMessage(display,windows->image.id,windows->im_protocols,
7190 windows->im_next_image,CurrentTime);
7196 Display former image.
7198 for (i=0; i < resource_info->quantum; i++)
7199 XClientMessage(display,windows->image.id,windows->im_protocols,
7200 windows->im_former_image,CurrentTime);
7211 status=chdir(resource_info->home_directory);
7213 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7214 "UnableToOpenFile","%s",resource_info->home_directory);
7215 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7223 status=XSaveImage(display,resource_info,windows,*image,exception);
7224 if (status == MagickFalse)
7227 message[MaxTextExtent];
7229 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7230 exception->reason != (char *) NULL ? exception->reason : "",
7231 exception->description != (char *) NULL ? exception->description :
7233 XNoticeWidget(display,windows,"Unable to save file:",message);
7243 status=XPrintImage(display,resource_info,windows,*image,exception);
7244 if (status == MagickFalse)
7247 message[MaxTextExtent];
7249 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7250 exception->reason != (char *) NULL ? exception->reason : "",
7251 exception->description != (char *) NULL ? exception->description :
7253 XNoticeWidget(display,windows,"Unable to print file:",message);
7261 filename[MaxTextExtent] = "\0";
7266 XFileBrowserWidget(display,windows,"Delete",filename);
7267 if (*filename == '\0')
7269 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
7270 if (status != MagickFalse)
7271 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7280 color[MaxTextExtent] = "gray",
7281 geometry[MaxTextExtent] = "640x480";
7284 *format = "gradient";
7287 Query user for canvas geometry.
7289 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7291 if (*geometry == '\0')
7295 XColorBrowserWidget(display,windows,"Select",color);
7301 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7302 "%s:%s",format,color);
7303 (void) CloneString(&image_info->size,geometry);
7304 nexus=ReadImage(image_info,exception);
7305 CatchException(exception);
7306 XClientMessage(display,windows->image.id,windows->im_protocols,
7307 windows->im_next_image,CurrentTime);
7310 case VisualDirectoryCommand:
7313 Visual Image directory.
7315 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7323 if (resource_info->confirm_exit == MagickFalse)
7324 XClientMessage(display,windows->image.id,windows->im_protocols,
7325 windows->im_exit,CurrentTime);
7332 Confirm program exit.
7334 status=XConfirmWidget(display,windows,"Do you really want to exit",
7335 resource_info->client_name);
7337 XClientMessage(display,windows->image.id,windows->im_protocols,
7338 windows->im_exit,CurrentTime);
7347 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7355 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7364 status=XPasteImage(display,resource_info,windows,*image,exception);
7365 if (status == MagickFalse)
7367 XNoticeWidget(display,windows,"Unable to paste X image",
7368 (*image)->filename);
7373 case HalfSizeCommand:
7378 windows->image.window_changes.width=windows->image.ximage->width/2;
7379 windows->image.window_changes.height=windows->image.ximage->height/2;
7380 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7383 case OriginalSizeCommand:
7386 Original image size.
7388 windows->image.window_changes.width=(int) (*image)->columns;
7389 windows->image.window_changes.height=(int) (*image)->rows;
7390 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7393 case DoubleSizeCommand:
7396 Double the image size.
7398 windows->image.window_changes.width=windows->image.ximage->width << 1;
7399 windows->image.window_changes.height=windows->image.ximage->height << 1;
7400 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7419 width=(size_t) windows->image.ximage->width;
7420 height=(size_t) windows->image.ximage->height;
7423 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7424 (double) width,(double) height);
7425 status=XDialogWidget(display,windows,"Resize",
7426 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7427 if (*geometry == '\0')
7430 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7431 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7432 windows->image.window_changes.width=(int) width;
7433 windows->image.window_changes.height=(int) height;
7434 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7440 image_geometry[MaxTextExtent];
7442 if ((windows->image.crop_geometry == (char *) NULL) &&
7443 ((int) (*image)->columns == windows->image.ximage->width) &&
7444 ((int) (*image)->rows == windows->image.ximage->height))
7447 Apply size transforms to image.
7449 XSetCursorState(display,windows,MagickTrue);
7450 XCheckRefreshWindows(display,windows);
7452 Crop and/or scale displayed image.
7454 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7455 windows->image.ximage->width,windows->image.ximage->height);
7456 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7458 if (windows->image.crop_geometry != (char *) NULL)
7459 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7460 windows->image.crop_geometry);
7463 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7464 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7467 case RefreshCommand:
7469 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7472 case RestoreCommand:
7475 Restore Image window to its original size.
7477 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7478 (windows->image.height == (unsigned int) (*image)->rows) &&
7479 (windows->image.crop_geometry == (char *) NULL))
7481 (void) XBell(display,0);
7484 windows->image.window_changes.width=(int) (*image)->columns;
7485 windows->image.window_changes.height=(int) (*image)->rows;
7486 if (windows->image.crop_geometry != (char *) NULL)
7488 windows->image.crop_geometry=(char *)
7489 RelinquishMagickMemory(windows->image.crop_geometry);
7490 windows->image.crop_geometry=(char *) NULL;
7494 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7495 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7503 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7512 status=XChopImage(display,resource_info,windows,image,exception);
7513 if (status == MagickFalse)
7515 XNoticeWidget(display,windows,"Unable to cut X image",
7516 (*image)->filename);
7527 Flop image scanlines.
7529 XSetCursorState(display,windows,MagickTrue);
7530 XCheckRefreshWindows(display,windows);
7531 flop_image=FlopImage(*image,exception);
7532 if (flop_image != (Image *) NULL)
7534 *image=DestroyImage(*image);
7537 CatchException(exception);
7538 XSetCursorState(display,windows,MagickFalse);
7539 if (windows->image.crop_geometry != (char *) NULL)
7544 width=(unsigned int) (*image)->columns;
7545 height=(unsigned int) (*image)->rows;
7546 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7548 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7549 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7551 if (windows->image.orphan != MagickFalse)
7553 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7562 Flip image scanlines.
7564 XSetCursorState(display,windows,MagickTrue);
7565 XCheckRefreshWindows(display,windows);
7566 flip_image=FlipImage(*image,exception);
7567 if (flip_image != (Image *) NULL)
7569 *image=DestroyImage(*image);
7572 CatchException(exception);
7573 XSetCursorState(display,windows,MagickFalse);
7574 if (windows->image.crop_geometry != (char *) NULL)
7579 width=(unsigned int) (*image)->columns;
7580 height=(unsigned int) (*image)->rows;
7581 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7583 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7584 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7586 if (windows->image.orphan != MagickFalse)
7588 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7591 case RotateRightCommand:
7594 Rotate image 90 degrees clockwise.
7596 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7597 if (status == MagickFalse)
7599 XNoticeWidget(display,windows,"Unable to rotate X image",
7600 (*image)->filename);
7605 case RotateLeftCommand:
7608 Rotate image 90 degrees counter-clockwise.
7610 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7611 if (status == MagickFalse)
7613 XNoticeWidget(display,windows,"Unable to rotate X image",
7614 (*image)->filename);
7624 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7625 if (status == MagickFalse)
7627 XNoticeWidget(display,windows,"Unable to rotate X image",
7628 (*image)->filename);
7639 geometry[MaxTextExtent] = "45.0x45.0";
7642 Query user for shear color and geometry.
7644 XColorBrowserWidget(display,windows,"Select",color);
7647 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7649 if (*geometry == '\0')
7654 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7656 XSetCursorState(display,windows,MagickTrue);
7657 XCheckRefreshWindows(display,windows);
7658 (void) QueryColorCompliance(color,AllCompliance,
7659 &(*image)->background_color,exception);
7660 flags=ParseGeometry(geometry,&geometry_info);
7661 if ((flags & SigmaValue) == 0)
7662 geometry_info.sigma=geometry_info.rho;
7663 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7665 if (shear_image != (Image *) NULL)
7667 *image=DestroyImage(*image);
7670 CatchException(exception);
7671 XSetCursorState(display,windows,MagickFalse);
7672 if (windows->image.orphan != MagickFalse)
7674 windows->image.window_changes.width=(int) (*image)->columns;
7675 windows->image.window_changes.height=(int) (*image)->rows;
7676 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7677 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7686 geometry[MaxTextExtent] = "+2+2";
7689 Query user for the roll geometry.
7691 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7693 if (*geometry == '\0')
7698 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7700 XSetCursorState(display,windows,MagickTrue);
7701 XCheckRefreshWindows(display,windows);
7702 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7704 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7706 if (roll_image != (Image *) NULL)
7708 *image=DestroyImage(*image);
7711 CatchException(exception);
7712 XSetCursorState(display,windows,MagickFalse);
7713 if (windows->image.orphan != MagickFalse)
7715 windows->image.window_changes.width=(int) (*image)->columns;
7716 windows->image.window_changes.height=(int) (*image)->rows;
7717 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7718 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7724 fuzz[MaxTextExtent];
7727 Query user for the fuzz factor.
7729 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7730 (*image)->fuzz/(QuantumRange+1.0));
7731 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7734 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+1.0);
7738 status=XTrimImage(display,resource_info,windows,*image,exception);
7739 if (status == MagickFalse)
7741 XNoticeWidget(display,windows,"Unable to trim X image",
7742 (*image)->filename);
7750 hue_percent[MaxTextExtent] = "110";
7753 Query user for percent hue change.
7755 (void) XDialogWidget(display,windows,"Apply",
7756 "Enter percent change in image hue (0-200):",hue_percent);
7757 if (*hue_percent == '\0')
7762 XSetCursorState(display,windows,MagickTrue);
7763 XCheckRefreshWindows(display,windows);
7764 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7765 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7767 (void) ModulateImage(*image,modulate_factors,exception);
7768 XSetCursorState(display,windows,MagickFalse);
7769 if (windows->image.orphan != MagickFalse)
7771 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7772 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7775 case SaturationCommand:
7778 saturation_percent[MaxTextExtent] = "110";
7781 Query user for percent saturation change.
7783 (void) XDialogWidget(display,windows,"Apply",
7784 "Enter percent change in color saturation (0-200):",saturation_percent);
7785 if (*saturation_percent == '\0')
7788 Vary color saturation.
7790 XSetCursorState(display,windows,MagickTrue);
7791 XCheckRefreshWindows(display,windows);
7792 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7793 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7795 (void) ModulateImage(*image,modulate_factors,exception);
7796 XSetCursorState(display,windows,MagickFalse);
7797 if (windows->image.orphan != MagickFalse)
7799 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7800 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7803 case BrightnessCommand:
7806 brightness_percent[MaxTextExtent] = "110";
7809 Query user for percent brightness change.
7811 (void) XDialogWidget(display,windows,"Apply",
7812 "Enter percent change in color brightness (0-200):",brightness_percent);
7813 if (*brightness_percent == '\0')
7816 Vary the color brightness.
7818 XSetCursorState(display,windows,MagickTrue);
7819 XCheckRefreshWindows(display,windows);
7820 (void) CopyMagickString(modulate_factors,brightness_percent,
7822 (void) ModulateImage(*image,modulate_factors,exception);
7823 XSetCursorState(display,windows,MagickFalse);
7824 if (windows->image.orphan != MagickFalse)
7826 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7827 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7833 factor[MaxTextExtent] = "1.6";
7836 Query user for gamma value.
7838 (void) XDialogWidget(display,windows,"Gamma",
7839 "Enter gamma value (e.g. 1.2):",factor);
7840 if (*factor == '\0')
7843 Gamma correct image.
7845 XSetCursorState(display,windows,MagickTrue);
7846 XCheckRefreshWindows(display,windows);
7847 (void) GammaImage(*image,atof(factor),exception);
7848 XSetCursorState(display,windows,MagickFalse);
7849 if (windows->image.orphan != MagickFalse)
7851 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7852 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7858 Sharpen the image contrast.
7860 XSetCursorState(display,windows,MagickTrue);
7861 XCheckRefreshWindows(display,windows);
7862 (void) ContrastImage(*image,MagickTrue,exception);
7863 XSetCursorState(display,windows,MagickFalse);
7864 if (windows->image.orphan != MagickFalse)
7866 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7867 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7873 Dull the image contrast.
7875 XSetCursorState(display,windows,MagickTrue);
7876 XCheckRefreshWindows(display,windows);
7877 (void) ContrastImage(*image,MagickFalse,exception);
7878 XSetCursorState(display,windows,MagickFalse);
7879 if (windows->image.orphan != MagickFalse)
7881 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7882 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7885 case ContrastStretchCommand:
7892 levels[MaxTextExtent] = "1%";
7895 Query user for gamma value.
7897 (void) XDialogWidget(display,windows,"Contrast Stretch",
7898 "Enter black and white points:",levels);
7899 if (*levels == '\0')
7902 Contrast stretch image.
7904 XSetCursorState(display,windows,MagickTrue);
7905 XCheckRefreshWindows(display,windows);
7906 flags=ParseGeometry(levels,&geometry_info);
7907 black_point=geometry_info.rho;
7908 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7909 if ((flags & PercentValue) != 0)
7911 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7912 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7914 white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point;
7915 (void) ContrastStretchImage(*image,black_point,white_point,
7917 XSetCursorState(display,windows,MagickFalse);
7918 if (windows->image.orphan != MagickFalse)
7920 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7921 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7924 case SigmoidalContrastCommand:
7933 levels[MaxTextExtent] = "3x50%";
7936 Query user for gamma value.
7938 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7939 "Enter contrast and midpoint:",levels);
7940 if (*levels == '\0')
7943 Contrast stretch image.
7945 XSetCursorState(display,windows,MagickTrue);
7946 XCheckRefreshWindows(display,windows);
7947 flags=ParseGeometry(levels,&geometry_info);
7948 if ((flags & SigmaValue) == 0)
7949 geometry_info.sigma=1.0*QuantumRange/2.0;
7950 if ((flags & PercentValue) != 0)
7951 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7952 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7953 geometry_info.sigma,exception);
7954 XSetCursorState(display,windows,MagickFalse);
7955 if (windows->image.orphan != MagickFalse)
7957 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7958 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7961 case NormalizeCommand:
7964 Perform histogram normalization on the image.
7966 XSetCursorState(display,windows,MagickTrue);
7967 XCheckRefreshWindows(display,windows);
7968 (void) NormalizeImage(*image,exception);
7969 XSetCursorState(display,windows,MagickFalse);
7970 if (windows->image.orphan != MagickFalse)
7972 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7973 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7976 case EqualizeCommand:
7979 Perform histogram equalization on the image.
7981 XSetCursorState(display,windows,MagickTrue);
7982 XCheckRefreshWindows(display,windows);
7983 (void) EqualizeImage(*image,exception);
7984 XSetCursorState(display,windows,MagickFalse);
7985 if (windows->image.orphan != MagickFalse)
7987 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7988 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7994 Negate colors in image.
7996 XSetCursorState(display,windows,MagickTrue);
7997 XCheckRefreshWindows(display,windows);
7998 (void) NegateImage(*image,MagickFalse,exception);
7999 XSetCursorState(display,windows,MagickFalse);
8000 if (windows->image.orphan != MagickFalse)
8002 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8003 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8006 case GrayscaleCommand:
8009 Convert image to grayscale.
8011 XSetCursorState(display,windows,MagickTrue);
8012 XCheckRefreshWindows(display,windows);
8013 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
8014 GrayscaleType : GrayscaleMatteType,exception);
8015 XSetCursorState(display,windows,MagickFalse);
8016 if (windows->image.orphan != MagickFalse)
8018 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8019 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8028 filename[MaxTextExtent] = "\0";
8031 Request image file name from user.
8033 XFileBrowserWidget(display,windows,"Map",filename);
8034 if (*filename == '\0')
8039 XSetCursorState(display,windows,MagickTrue);
8040 XCheckRefreshWindows(display,windows);
8041 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8042 affinity_image=ReadImage(image_info,exception);
8043 if (affinity_image != (Image *) NULL)
8045 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8046 affinity_image=DestroyImage(affinity_image);
8048 CatchException(exception);
8049 XSetCursorState(display,windows,MagickFalse);
8050 if (windows->image.orphan != MagickFalse)
8052 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8053 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8056 case QuantizeCommand:
8062 colors[MaxTextExtent] = "256";
8065 Query user for maximum number of colors.
8067 status=XDialogWidget(display,windows,"Quantize",
8068 "Maximum number of colors:",colors);
8069 if (*colors == '\0')
8072 Color reduce the image.
8074 XSetCursorState(display,windows,MagickTrue);
8075 XCheckRefreshWindows(display,windows);
8076 quantize_info.number_colors=StringToUnsignedLong(colors);
8077 quantize_info.dither=status != 0 ? MagickTrue : MagickFalse;
8078 (void) QuantizeImage(&quantize_info,*image,exception);
8079 XSetCursorState(display,windows,MagickFalse);
8080 if (windows->image.orphan != MagickFalse)
8082 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8083 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8086 case DespeckleCommand:
8094 XSetCursorState(display,windows,MagickTrue);
8095 XCheckRefreshWindows(display,windows);
8096 despeckle_image=DespeckleImage(*image,exception);
8097 if (despeckle_image != (Image *) NULL)
8099 *image=DestroyImage(*image);
8100 *image=despeckle_image;
8102 CatchException(exception);
8103 XSetCursorState(display,windows,MagickFalse);
8104 if (windows->image.orphan != MagickFalse)
8106 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8107 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8116 radius[MaxTextExtent] = "0.0x1.0";
8119 Query user for emboss radius.
8121 (void) XDialogWidget(display,windows,"Emboss",
8122 "Enter the emboss radius and standard deviation:",radius);
8123 if (*radius == '\0')
8126 Reduce noise in the image.
8128 XSetCursorState(display,windows,MagickTrue);
8129 XCheckRefreshWindows(display,windows);
8130 flags=ParseGeometry(radius,&geometry_info);
8131 if ((flags & SigmaValue) == 0)
8132 geometry_info.sigma=1.0;
8133 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8135 if (emboss_image != (Image *) NULL)
8137 *image=DestroyImage(*image);
8138 *image=emboss_image;
8140 CatchException(exception);
8141 XSetCursorState(display,windows,MagickFalse);
8142 if (windows->image.orphan != MagickFalse)
8144 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8145 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8148 case ReduceNoiseCommand:
8154 radius[MaxTextExtent] = "0";
8157 Query user for noise radius.
8159 (void) XDialogWidget(display,windows,"Reduce Noise",
8160 "Enter the noise radius:",radius);
8161 if (*radius == '\0')
8164 Reduce noise in the image.
8166 XSetCursorState(display,windows,MagickTrue);
8167 XCheckRefreshWindows(display,windows);
8168 flags=ParseGeometry(radius,&geometry_info);
8169 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8170 geometry_info.rho,(size_t) geometry_info.rho,exception);
8171 if (noise_image != (Image *) NULL)
8173 *image=DestroyImage(*image);
8176 CatchException(exception);
8177 XSetCursorState(display,windows,MagickFalse);
8178 if (windows->image.orphan != MagickFalse)
8180 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8181 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8184 case AddNoiseCommand:
8193 noise_type[MaxTextExtent] = "Gaussian";
8196 Add noise to the image.
8198 noises=GetCommandOptions(MagickNoiseOptions);
8199 if (noises == (char **) NULL)
8201 XListBrowserWidget(display,windows,&windows->widget,
8202 (const char **) noises,"Add Noise",
8203 "Select a type of noise to add to your image:",noise_type);
8204 noises=DestroyStringList(noises);
8205 if (*noise_type == '\0')
8207 XSetCursorState(display,windows,MagickTrue);
8208 XCheckRefreshWindows(display,windows);
8209 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8210 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8211 if (noise_image != (Image *) NULL)
8213 *image=DestroyImage(*image);
8216 CatchException(exception);
8217 XSetCursorState(display,windows,MagickFalse);
8218 if (windows->image.orphan != MagickFalse)
8220 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8221 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8224 case SharpenCommand:
8230 radius[MaxTextExtent] = "0.0x1.0";
8233 Query user for sharpen radius.
8235 (void) XDialogWidget(display,windows,"Sharpen",
8236 "Enter the sharpen radius and standard deviation:",radius);
8237 if (*radius == '\0')
8240 Sharpen image scanlines.
8242 XSetCursorState(display,windows,MagickTrue);
8243 XCheckRefreshWindows(display,windows);
8244 flags=ParseGeometry(radius,&geometry_info);
8245 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8246 geometry_info.xi,exception);
8247 if (sharp_image != (Image *) NULL)
8249 *image=DestroyImage(*image);
8252 CatchException(exception);
8253 XSetCursorState(display,windows,MagickFalse);
8254 if (windows->image.orphan != MagickFalse)
8256 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8257 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8266 radius[MaxTextExtent] = "0.0x1.0";
8269 Query user for blur radius.
8271 (void) XDialogWidget(display,windows,"Blur",
8272 "Enter the blur radius and standard deviation:",radius);
8273 if (*radius == '\0')
8278 XSetCursorState(display,windows,MagickTrue);
8279 XCheckRefreshWindows(display,windows);
8280 flags=ParseGeometry(radius,&geometry_info);
8281 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8282 geometry_info.xi,exception);
8283 if (blur_image != (Image *) NULL)
8285 *image=DestroyImage(*image);
8288 CatchException(exception);
8289 XSetCursorState(display,windows,MagickFalse);
8290 if (windows->image.orphan != MagickFalse)
8292 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8293 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8296 case ThresholdCommand:
8302 factor[MaxTextExtent] = "128";
8305 Query user for threshold value.
8307 (void) XDialogWidget(display,windows,"Threshold",
8308 "Enter threshold value:",factor);
8309 if (*factor == '\0')
8312 Gamma correct image.
8314 XSetCursorState(display,windows,MagickTrue);
8315 XCheckRefreshWindows(display,windows);
8316 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8317 (void) BilevelImage(*image,threshold,exception);
8318 XSetCursorState(display,windows,MagickFalse);
8319 if (windows->image.orphan != MagickFalse)
8321 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8322 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8325 case EdgeDetectCommand:
8331 radius[MaxTextExtent] = "0";
8334 Query user for edge factor.
8336 (void) XDialogWidget(display,windows,"Detect Edges",
8337 "Enter the edge detect radius:",radius);
8338 if (*radius == '\0')
8341 Detect edge in image.
8343 XSetCursorState(display,windows,MagickTrue);
8344 XCheckRefreshWindows(display,windows);
8345 flags=ParseGeometry(radius,&geometry_info);
8346 edge_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8348 if (edge_image != (Image *) NULL)
8350 *image=DestroyImage(*image);
8353 CatchException(exception);
8354 XSetCursorState(display,windows,MagickFalse);
8355 if (windows->image.orphan != MagickFalse)
8357 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8358 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8367 amount[MaxTextExtent] = "2";
8370 Query user for spread amount.
8372 (void) XDialogWidget(display,windows,"Spread",
8373 "Enter the displacement amount:",amount);
8374 if (*amount == '\0')
8377 Displace image pixels by a random amount.
8379 XSetCursorState(display,windows,MagickTrue);
8380 XCheckRefreshWindows(display,windows);
8381 flags=ParseGeometry(amount,&geometry_info);
8382 spread_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8384 if (spread_image != (Image *) NULL)
8386 *image=DestroyImage(*image);
8387 *image=spread_image;
8389 CatchException(exception);
8390 XSetCursorState(display,windows,MagickFalse);
8391 if (windows->image.orphan != MagickFalse)
8393 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8394 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8406 geometry[MaxTextExtent] = "30x30";
8409 Query user for the shade geometry.
8411 status=XDialogWidget(display,windows,"Shade",
8412 "Enter the azimuth and elevation of the light source:",geometry);
8413 if (*geometry == '\0')
8418 XSetCursorState(display,windows,MagickTrue);
8419 XCheckRefreshWindows(display,windows);
8420 flags=ParseGeometry(geometry,&geometry_info);
8421 if ((flags & SigmaValue) == 0)
8422 geometry_info.sigma=1.0;
8423 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
8424 geometry_info.rho,geometry_info.sigma,exception);
8425 if (shade_image != (Image *) NULL)
8427 *image=DestroyImage(*image);
8430 CatchException(exception);
8431 XSetCursorState(display,windows,MagickFalse);
8432 if (windows->image.orphan != MagickFalse)
8434 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8435 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8441 bevel_width[MaxTextExtent] = "10";
8444 Query user for bevel width.
8446 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8447 if (*bevel_width == '\0')
8452 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8454 XSetCursorState(display,windows,MagickTrue);
8455 XCheckRefreshWindows(display,windows);
8456 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8458 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8459 XSetCursorState(display,windows,MagickFalse);
8460 if (windows->image.orphan != MagickFalse)
8462 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8463 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8466 case SegmentCommand:
8469 threshold[MaxTextExtent] = "1.0x1.5";
8472 Query user for smoothing threshold.
8474 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8476 if (*threshold == '\0')
8481 XSetCursorState(display,windows,MagickTrue);
8482 XCheckRefreshWindows(display,windows);
8483 flags=ParseGeometry(threshold,&geometry_info);
8484 if ((flags & SigmaValue) == 0)
8485 geometry_info.sigma=1.0;
8486 (void) SegmentImage(*image,RGBColorspace,MagickFalse,geometry_info.rho,
8487 geometry_info.sigma,exception);
8488 XSetCursorState(display,windows,MagickFalse);
8489 if (windows->image.orphan != MagickFalse)
8491 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8492 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8495 case SepiaToneCommand:
8504 factor[MaxTextExtent] = "80%";
8507 Query user for sepia-tone factor.
8509 (void) XDialogWidget(display,windows,"Sepia Tone",
8510 "Enter the sepia tone factor (0 - 99.9%):",factor);
8511 if (*factor == '\0')
8514 Sepia tone image pixels.
8516 XSetCursorState(display,windows,MagickTrue);
8517 XCheckRefreshWindows(display,windows);
8518 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8519 sepia_image=SepiaToneImage(*image,threshold,exception);
8520 if (sepia_image != (Image *) NULL)
8522 *image=DestroyImage(*image);
8525 CatchException(exception);
8526 XSetCursorState(display,windows,MagickFalse);
8527 if (windows->image.orphan != MagickFalse)
8529 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8530 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8533 case SolarizeCommand:
8539 factor[MaxTextExtent] = "60%";
8542 Query user for solarize factor.
8544 (void) XDialogWidget(display,windows,"Solarize",
8545 "Enter the solarize factor (0 - 99.9%):",factor);
8546 if (*factor == '\0')
8549 Solarize image pixels.
8551 XSetCursorState(display,windows,MagickTrue);
8552 XCheckRefreshWindows(display,windows);
8553 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8554 (void) SolarizeImage(*image,threshold,exception);
8555 XSetCursorState(display,windows,MagickFalse);
8556 if (windows->image.orphan != MagickFalse)
8558 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8559 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8568 degrees[MaxTextExtent] = "60";
8571 Query user for swirl angle.
8573 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8575 if (*degrees == '\0')
8578 Swirl image pixels about the center.
8580 XSetCursorState(display,windows,MagickTrue);
8581 XCheckRefreshWindows(display,windows);
8582 flags=ParseGeometry(degrees,&geometry_info);
8583 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8585 if (swirl_image != (Image *) NULL)
8587 *image=DestroyImage(*image);
8590 CatchException(exception);
8591 XSetCursorState(display,windows,MagickFalse);
8592 if (windows->image.orphan != MagickFalse)
8594 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8595 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8598 case ImplodeCommand:
8604 factor[MaxTextExtent] = "0.3";
8607 Query user for implode factor.
8609 (void) XDialogWidget(display,windows,"Implode",
8610 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8611 if (*factor == '\0')
8614 Implode image pixels about the center.
8616 XSetCursorState(display,windows,MagickTrue);
8617 XCheckRefreshWindows(display,windows);
8618 flags=ParseGeometry(factor,&geometry_info);
8619 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8621 if (implode_image != (Image *) NULL)
8623 *image=DestroyImage(*image);
8624 *image=implode_image;
8626 CatchException(exception);
8627 XSetCursorState(display,windows,MagickFalse);
8628 if (windows->image.orphan != MagickFalse)
8630 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8631 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8634 case VignetteCommand:
8640 geometry[MaxTextExtent] = "0x20";
8643 Query user for the vignette geometry.
8645 (void) XDialogWidget(display,windows,"Vignette",
8646 "Enter the radius, sigma, and x and y offsets:",geometry);
8647 if (*geometry == '\0')
8650 Soften the edges of the image in vignette style
8652 XSetCursorState(display,windows,MagickTrue);
8653 XCheckRefreshWindows(display,windows);
8654 flags=ParseGeometry(geometry,&geometry_info);
8655 if ((flags & SigmaValue) == 0)
8656 geometry_info.sigma=1.0;
8657 if ((flags & XiValue) == 0)
8658 geometry_info.xi=0.1*(*image)->columns;
8659 if ((flags & PsiValue) == 0)
8660 geometry_info.psi=0.1*(*image)->rows;
8661 vignette_image=VignetteImage(*image,geometry_info.rho,geometry_info.sigma,
8662 0.0,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
8663 ceil(geometry_info.psi-0.5),exception);
8664 if (vignette_image != (Image *) NULL)
8666 *image=DestroyImage(*image);
8667 *image=vignette_image;
8669 CatchException(exception);
8670 XSetCursorState(display,windows,MagickFalse);
8671 if (windows->image.orphan != MagickFalse)
8673 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8674 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8683 geometry[MaxTextExtent] = "25x150";
8686 Query user for the wave geometry.
8688 (void) XDialogWidget(display,windows,"Wave",
8689 "Enter the amplitude and length of the wave:",geometry);
8690 if (*geometry == '\0')
8693 Alter an image along a sine wave.
8695 XSetCursorState(display,windows,MagickTrue);
8696 XCheckRefreshWindows(display,windows);
8697 flags=ParseGeometry(geometry,&geometry_info);
8698 if ((flags & SigmaValue) == 0)
8699 geometry_info.sigma=1.0;
8700 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8701 (*image)->interpolate,exception);
8702 if (wave_image != (Image *) NULL)
8704 *image=DestroyImage(*image);
8707 CatchException(exception);
8708 XSetCursorState(display,windows,MagickFalse);
8709 if (windows->image.orphan != MagickFalse)
8711 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8712 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8715 case OilPaintCommand:
8721 radius[MaxTextExtent] = "0";
8724 Query user for circular neighborhood radius.
8726 (void) XDialogWidget(display,windows,"Oil Paint",
8727 "Enter the mask radius:",radius);
8728 if (*radius == '\0')
8731 OilPaint image scanlines.
8733 XSetCursorState(display,windows,MagickTrue);
8734 XCheckRefreshWindows(display,windows);
8735 flags=ParseGeometry(radius,&geometry_info);
8736 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8738 if (paint_image != (Image *) NULL)
8740 *image=DestroyImage(*image);
8743 CatchException(exception);
8744 XSetCursorState(display,windows,MagickFalse);
8745 if (windows->image.orphan != MagickFalse)
8747 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8748 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8751 case CharcoalDrawCommand:
8757 radius[MaxTextExtent] = "0x1";
8760 Query user for charcoal radius.
8762 (void) XDialogWidget(display,windows,"Charcoal Draw",
8763 "Enter the charcoal radius and sigma:",radius);
8764 if (*radius == '\0')
8769 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8771 XSetCursorState(display,windows,MagickTrue);
8772 XCheckRefreshWindows(display,windows);
8773 flags=ParseGeometry(radius,&geometry_info);
8774 if ((flags & SigmaValue) == 0)
8775 geometry_info.sigma=geometry_info.rho;
8776 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8777 geometry_info.xi,exception);
8778 if (charcoal_image != (Image *) NULL)
8780 *image=DestroyImage(*image);
8781 *image=charcoal_image;
8783 CatchException(exception);
8784 XSetCursorState(display,windows,MagickFalse);
8785 if (windows->image.orphan != MagickFalse)
8787 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8788 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8791 case AnnotateCommand:
8794 Annotate the image with text.
8796 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8797 if (status == MagickFalse)
8799 XNoticeWidget(display,windows,"Unable to annotate X image",
8800 (*image)->filename);
8810 status=XDrawEditImage(display,resource_info,windows,image,exception);
8811 if (status == MagickFalse)
8813 XNoticeWidget(display,windows,"Unable to draw on the X image",
8814 (*image)->filename);
8824 status=XColorEditImage(display,resource_info,windows,image,exception);
8825 if (status == MagickFalse)
8827 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8828 (*image)->filename);
8838 status=XMatteEditImage(display,resource_info,windows,image,exception);
8839 if (status == MagickFalse)
8841 XNoticeWidget(display,windows,"Unable to matte edit X image",
8842 (*image)->filename);
8847 case CompositeCommand:
8852 status=XCompositeImage(display,resource_info,windows,*image,
8854 if (status == MagickFalse)
8856 XNoticeWidget(display,windows,"Unable to composite X image",
8857 (*image)->filename);
8862 case AddBorderCommand:
8868 geometry[MaxTextExtent] = "6x6";
8871 Query user for border color and geometry.
8873 XColorBrowserWidget(display,windows,"Select",color);
8876 (void) XDialogWidget(display,windows,"Add Border",
8877 "Enter border geometry:",geometry);
8878 if (*geometry == '\0')
8881 Add a border to the image.
8883 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8885 XSetCursorState(display,windows,MagickTrue);
8886 XCheckRefreshWindows(display,windows);
8887 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8889 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8891 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8893 if (border_image != (Image *) NULL)
8895 *image=DestroyImage(*image);
8896 *image=border_image;
8898 CatchException(exception);
8899 XSetCursorState(display,windows,MagickFalse);
8900 if (windows->image.orphan != MagickFalse)
8902 windows->image.window_changes.width=(int) (*image)->columns;
8903 windows->image.window_changes.height=(int) (*image)->rows;
8904 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8905 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8908 case AddFrameCommand:
8917 geometry[MaxTextExtent] = "6x6";
8920 Query user for frame color and geometry.
8922 XColorBrowserWidget(display,windows,"Select",color);
8925 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8927 if (*geometry == '\0')
8930 Surround image with an ornamental border.
8932 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8934 XSetCursorState(display,windows,MagickTrue);
8935 XCheckRefreshWindows(display,windows);
8936 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8938 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8940 frame_info.width=page_geometry.width;
8941 frame_info.height=page_geometry.height;
8942 frame_info.outer_bevel=page_geometry.x;
8943 frame_info.inner_bevel=page_geometry.y;
8944 frame_info.x=(ssize_t) frame_info.width;
8945 frame_info.y=(ssize_t) frame_info.height;
8946 frame_info.width=(*image)->columns+2*frame_info.width;
8947 frame_info.height=(*image)->rows+2*frame_info.height;
8948 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8949 if (frame_image != (Image *) NULL)
8951 *image=DestroyImage(*image);
8954 CatchException(exception);
8955 XSetCursorState(display,windows,MagickFalse);
8956 if (windows->image.orphan != MagickFalse)
8958 windows->image.window_changes.width=(int) (*image)->columns;
8959 windows->image.window_changes.height=(int) (*image)->rows;
8960 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8961 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8964 case CommentCommand:
8978 unique_file=AcquireUniqueFileResource(image_info->filename);
8979 if (unique_file == -1)
8980 XNoticeWidget(display,windows,"Unable to edit image comment",
8981 image_info->filename);
8982 value=GetImageProperty(*image,"comment",exception);
8983 if (value == (char *) NULL)
8984 unique_file=close(unique_file)-1;
8990 file=fdopen(unique_file,"w");
8991 if (file == (FILE *) NULL)
8993 XNoticeWidget(display,windows,"Unable to edit image comment",
8994 image_info->filename);
8997 for (p=value; *p != '\0'; p++)
8998 (void) fputc((int) *p,file);
8999 (void) fputc('\n',file);
9000 (void) fclose(file);
9002 XSetCursorState(display,windows,MagickTrue);
9003 XCheckRefreshWindows(display,windows);
9004 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
9006 if (status == MagickFalse)
9007 XNoticeWidget(display,windows,"Unable to edit image comment",
9014 comment=FileToString(image_info->filename,~0UL,exception);
9015 if (comment != (char *) NULL)
9017 (void) SetImageProperty(*image,"comment",comment,exception);
9018 (*image)->taint=MagickTrue;
9021 (void) RelinquishUniqueFileResource(image_info->filename);
9022 XSetCursorState(display,windows,MagickFalse);
9030 XSetCursorState(display,windows,MagickTrue);
9031 XCheckRefreshWindows(display,windows);
9032 (void) AcquireUniqueFilename(filename);
9033 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9035 status=WriteImage(image_info,*image,exception);
9036 if (status == MagickFalse)
9037 XNoticeWidget(display,windows,"Unable to launch image editor",
9041 nexus=ReadImage(resource_info->image_info,exception);
9042 CatchException(exception);
9043 XClientMessage(display,windows->image.id,windows->im_protocols,
9044 windows->im_next_image,CurrentTime);
9046 (void) RelinquishUniqueFileResource(filename);
9047 XSetCursorState(display,windows,MagickFalse);
9050 case RegionofInterestCommand:
9053 Apply an image processing technique to a region of interest.
9055 (void) XROIImage(display,resource_info,windows,image,exception);
9065 if (windows->magnify.mapped != MagickFalse)
9066 (void) XRaiseWindow(display,windows->magnify.id);
9072 XSetCursorState(display,windows,MagickTrue);
9073 (void) XMapRaised(display,windows->magnify.id);
9074 XSetCursorState(display,windows,MagickFalse);
9078 case ShowPreviewCommand:
9087 preview_type[MaxTextExtent] = "Gamma";
9090 Select preview type from menu.
9092 previews=GetCommandOptions(MagickPreviewOptions);
9093 if (previews == (char **) NULL)
9095 XListBrowserWidget(display,windows,&windows->widget,
9096 (const char **) previews,"Preview",
9097 "Select an enhancement, effect, or F/X:",preview_type);
9098 previews=DestroyStringList(previews);
9099 if (*preview_type == '\0')
9104 XSetCursorState(display,windows,MagickTrue);
9105 XCheckRefreshWindows(display,windows);
9106 image_info->preview_type=(PreviewType)
9107 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9108 image_info->group=(ssize_t) windows->image.id;
9109 (void) DeleteImageProperty(*image,"label");
9110 (void) SetImageProperty(*image,"label","Preview",exception);
9111 (void) AcquireUniqueFilename(filename);
9112 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9114 status=WriteImage(image_info,*image,exception);
9115 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9116 preview_image=ReadImage(image_info,exception);
9117 (void) RelinquishUniqueFileResource(filename);
9118 if (preview_image == (Image *) NULL)
9120 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9122 status=WriteImage(image_info,preview_image,exception);
9123 preview_image=DestroyImage(preview_image);
9124 if (status == MagickFalse)
9125 XNoticeWidget(display,windows,"Unable to show image preview",
9126 (*image)->filename);
9127 XDelay(display,1500);
9128 XSetCursorState(display,windows,MagickFalse);
9131 case ShowHistogramCommand:
9137 Show image histogram.
9139 XSetCursorState(display,windows,MagickTrue);
9140 XCheckRefreshWindows(display,windows);
9141 image_info->group=(ssize_t) windows->image.id;
9142 (void) DeleteImageProperty(*image,"label");
9143 (void) SetImageProperty(*image,"label","Histogram",exception);
9144 (void) AcquireUniqueFilename(filename);
9145 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9147 status=WriteImage(image_info,*image,exception);
9148 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9149 histogram_image=ReadImage(image_info,exception);
9150 (void) RelinquishUniqueFileResource(filename);
9151 if (histogram_image == (Image *) NULL)
9153 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9154 "show:%s",filename);
9155 status=WriteImage(image_info,histogram_image,exception);
9156 histogram_image=DestroyImage(histogram_image);
9157 if (status == MagickFalse)
9158 XNoticeWidget(display,windows,"Unable to show histogram",
9159 (*image)->filename);
9160 XDelay(display,1500);
9161 XSetCursorState(display,windows,MagickFalse);
9164 case ShowMatteCommand:
9169 if ((*image)->matte == MagickFalse)
9171 XNoticeWidget(display,windows,
9172 "Image does not have any matte information",(*image)->filename);
9178 XSetCursorState(display,windows,MagickTrue);
9179 XCheckRefreshWindows(display,windows);
9180 image_info->group=(ssize_t) windows->image.id;
9181 (void) DeleteImageProperty(*image,"label");
9182 (void) SetImageProperty(*image,"label","Matte",exception);
9183 (void) AcquireUniqueFilename(filename);
9184 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9186 status=WriteImage(image_info,*image,exception);
9187 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9188 matte_image=ReadImage(image_info,exception);
9189 (void) RelinquishUniqueFileResource(filename);
9190 if (matte_image == (Image *) NULL)
9192 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9194 status=WriteImage(image_info,matte_image,exception);
9195 matte_image=DestroyImage(matte_image);
9196 if (status == MagickFalse)
9197 XNoticeWidget(display,windows,"Unable to show matte",
9198 (*image)->filename);
9199 XDelay(display,1500);
9200 XSetCursorState(display,windows,MagickFalse);
9203 case BackgroundCommand:
9208 status=XBackgroundImage(display,resource_info,windows,image,exception);
9209 if (status == MagickFalse)
9211 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9212 if (nexus != (Image *) NULL)
9213 XClientMessage(display,windows->image.id,windows->im_protocols,
9214 windows->im_next_image,CurrentTime);
9217 case SlideShowCommand:
9220 delay[MaxTextExtent] = "5";
9223 Display next image after pausing.
9225 (void) XDialogWidget(display,windows,"Slide Show",
9226 "Pause how many 1/100ths of a second between images:",delay);
9229 resource_info->delay=StringToUnsignedLong(delay);
9230 XClientMessage(display,windows->image.id,windows->im_protocols,
9231 windows->im_next_image,CurrentTime);
9234 case PreferencesCommand:
9237 Set user preferences.
9239 status=XPreferencesWidget(display,resource_info,windows);
9240 if (status == MagickFalse)
9242 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9243 if (nexus != (Image *) NULL)
9244 XClientMessage(display,windows->image.id,windows->im_protocols,
9245 windows->im_next_image,CurrentTime);
9251 User requested help.
9253 XTextViewWidget(display,resource_info,windows,MagickFalse,
9254 "Help Viewer - Display",DisplayHelp);
9257 case BrowseDocumentationCommand:
9267 Browse the ImageMagick documentation.
9269 root_window=XRootWindow(display,XDefaultScreen(display));
9270 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9271 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9272 if (mozilla_window != (Window) NULL)
9275 command[MaxTextExtent],
9279 Display documentation using Netscape remote control.
9281 url=GetMagickHomeURL();
9282 (void) FormatLocaleString(command,MaxTextExtent,
9283 "openurl(%s,new-tab)",url);
9284 url=DestroyString(url);
9285 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9286 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9287 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9288 XSetCursorState(display,windows,MagickFalse);
9291 XSetCursorState(display,windows,MagickTrue);
9292 XCheckRefreshWindows(display,windows);
9293 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9295 if (status == MagickFalse)
9296 XNoticeWidget(display,windows,"Unable to browse documentation",
9298 XDelay(display,1500);
9299 XSetCursorState(display,windows,MagickFalse);
9302 case VersionCommand:
9304 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9305 GetMagickCopyright());
9308 case SaveToUndoBufferCommand:
9312 (void) XBell(display,0);
9316 image_info=DestroyImageInfo(image_info);
9321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9325 + X M a g n i f y I m a g e %
9329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9331 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9332 % The magnified portion is displayed in a separate window.
9334 % The format of the XMagnifyImage method is:
9336 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9337 % ExceptionInfo *exception)
9339 % A description of each parameter follows:
9341 % o display: Specifies a connection to an X server; returned from
9344 % o windows: Specifies a pointer to a XWindows structure.
9346 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9347 % the entire image is refreshed.
9349 % o exception: return any errors or warnings in this structure.
9352 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9353 ExceptionInfo *exception)
9356 text[MaxTextExtent];
9366 Update magnified image until the mouse button is released.
9368 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9372 windows->magnify.x=(int) windows->image.x+x;
9373 windows->magnify.y=(int) windows->image.y+y;
9377 Map and unmap Info widget as text cursor crosses its boundaries.
9379 if (windows->info.mapped != MagickFalse)
9381 if ((x < (int) (windows->info.x+windows->info.width)) &&
9382 (y < (int) (windows->info.y+windows->info.height)))
9383 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9386 if ((x > (int) (windows->info.x+windows->info.width)) ||
9387 (y > (int) (windows->info.y+windows->info.height)))
9388 (void) XMapWindow(display,windows->info.id);
9389 if (windows->info.mapped != MagickFalse)
9392 Display pointer position.
9394 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9395 windows->magnify.x,windows->magnify.y);
9396 XInfoWidget(display,windows,text);
9399 Wait for next event.
9401 XScreenEvent(display,windows,event,exception);
9402 switch (event->type)
9409 User has finished magnifying image.
9428 Check boundary conditions.
9433 if (x >= (int) windows->image.width)
9434 x=(int) windows->image.width-1;
9438 if (y >= (int) windows->image.height)
9439 y=(int) windows->image.height-1;
9440 } while ((state & ExitState) == 0);
9442 Display magnified image.
9444 XSetCursorState(display,windows,MagickFalse);
9448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9452 + X M a g n i f y W i n d o w C o m m a n d %
9456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9458 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9459 % pixel as specified by the key symbol.
9461 % The format of the XMagnifyWindowCommand method is:
9463 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9464 % const MagickStatusType state,const KeySym key_symbol,
9465 % ExceptionInfo *exception)
9467 % A description of each parameter follows:
9469 % o display: Specifies a connection to an X server; returned from
9472 % o windows: Specifies a pointer to a XWindows structure.
9474 % o state: key mask.
9476 % o key_symbol: Specifies a KeySym which indicates which side of the image
9479 % o exception: return any errors or warnings in this structure.
9482 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9483 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9489 User specified a magnify factor or position.
9492 if ((state & Mod1Mask) != 0)
9494 switch ((int) key_symbol)
9498 (void) XWithdrawWindow(display,windows->magnify.id,
9499 windows->magnify.screen);
9505 windows->magnify.x=(int) windows->image.width/2;
9506 windows->magnify.y=(int) windows->image.height/2;
9512 if (windows->magnify.x > 0)
9513 windows->magnify.x-=quantum;
9519 if (windows->magnify.y > 0)
9520 windows->magnify.y-=quantum;
9526 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9527 windows->magnify.x+=quantum;
9533 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9534 windows->magnify.y+=quantum;
9548 windows->magnify.data=(key_symbol-XK_0);
9562 windows->magnify.data=(key_symbol-XK_KP_0);
9568 XMakeMagnifyImage(display,windows,exception);
9572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9576 + X M a k e P a n I m a g e %
9580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9582 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9585 % The format of the XMakePanImage method is:
9587 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9588 % XWindows *windows,Image *image,ExceptionInfo *exception)
9590 % A description of each parameter follows:
9592 % o display: Specifies a connection to an X server; returned from
9595 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9597 % o windows: Specifies a pointer to a XWindows structure.
9599 % o image: the image.
9601 % o exception: return any errors or warnings in this structure.
9604 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9605 XWindows *windows,Image *image,ExceptionInfo *exception)
9611 Create and display image for panning icon.
9613 XSetCursorState(display,windows,MagickTrue);
9614 XCheckRefreshWindows(display,windows);
9615 windows->pan.x=(int) windows->image.x;
9616 windows->pan.y=(int) windows->image.y;
9617 status=XMakeImage(display,resource_info,&windows->pan,image,
9618 windows->pan.width,windows->pan.height,exception);
9619 if (status == MagickFalse)
9620 ThrowXWindowFatalException(ResourceLimitError,
9621 "MemoryAllocationFailed",image->filename);
9622 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9623 windows->pan.pixmap);
9624 (void) XClearWindow(display,windows->pan.id);
9625 XDrawPanRectangle(display,windows);
9626 XSetCursorState(display,windows,MagickFalse);
9630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9634 + X M a t t a E d i t I m a g e %
9638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9640 % XMatteEditImage() allows the user to interactively change the Matte channel
9641 % of an image. If the image is PseudoClass it is promoted to DirectClass
9642 % before the matte information is stored.
9644 % The format of the XMatteEditImage method is:
9646 % MagickBooleanType XMatteEditImage(Display *display,
9647 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9648 % ExceptionInfo *exception)
9650 % A description of each parameter follows:
9652 % o display: Specifies a connection to an X server; returned from
9655 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9657 % o windows: Specifies a pointer to a XWindows structure.
9659 % o image: the image; returned from ReadImage.
9661 % o exception: return any errors or warnings in this structure.
9664 static MagickBooleanType XMatteEditImage(Display *display,
9665 XResourceInfo *resource_info,XWindows *windows,Image **image,
9666 ExceptionInfo *exception)
9669 matte[MaxTextExtent] = "0";
9684 static const ModeType
9685 MatteEditCommands[] =
9688 MatteEditBorderCommand,
9689 MatteEditFuzzCommand,
9690 MatteEditValueCommand,
9691 MatteEditUndoCommand,
9692 MatteEditHelpCommand,
9693 MatteEditDismissCommand
9697 method = PointMethod;
9700 border_color = { 0, 0, 0, 0, 0, 0 };
9703 command[MaxTextExtent],
9704 text[MaxTextExtent];
9736 (void) CloneString(&windows->command.name,"Matte Edit");
9737 windows->command.data=4;
9738 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9739 (void) XMapRaised(display,windows->command.id);
9740 XClientMessage(display,windows->image.id,windows->im_protocols,
9741 windows->im_update_widget,CurrentTime);
9745 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9746 resource_info->background_color,resource_info->foreground_color);
9747 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9749 Track pointer until button 1 is pressed.
9751 XQueryPosition(display,windows->image.id,&x,&y);
9752 (void) XSelectInput(display,windows->image.id,
9753 windows->image.attributes.event_mask | PointerMotionMask);
9757 if (windows->info.mapped != MagickFalse)
9760 Display pointer position.
9762 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9763 x+windows->image.x,y+windows->image.y);
9764 XInfoWidget(display,windows,text);
9767 Wait for next event.
9769 XScreenEvent(display,windows,&event,exception);
9770 if (event.xany.window == windows->command.id)
9773 Select a command from the Command widget.
9775 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9778 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9781 switch (MatteEditCommands[id])
9783 case MatteEditMethod:
9789 Select a method from the pop-up menu.
9791 methods=GetCommandOptions(MagickMethodOptions);
9792 if (methods == (char **) NULL)
9794 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9795 (const char **) methods,command);
9797 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9798 MagickFalse,methods[entry]);
9799 methods=DestroyStringList(methods);
9802 case MatteEditBorderCommand:
9805 *ColorMenu[MaxNumberPens];
9811 Initialize menu selections.
9813 for (i=0; i < (int) (MaxNumberPens-2); i++)
9814 ColorMenu[i]=resource_info->pen_colors[i];
9815 ColorMenu[MaxNumberPens-2]="Browser...";
9816 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9818 Select a pen color from the pop-up menu.
9820 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9821 (const char **) ColorMenu,command);
9824 if (pen_number == (MaxNumberPens-2))
9827 color_name[MaxTextExtent] = "gray";
9830 Select a pen color from a dialog.
9832 resource_info->pen_colors[pen_number]=color_name;
9833 XColorBrowserWidget(display,windows,"Select",color_name);
9834 if (*color_name == '\0')
9840 (void) XParseColor(display,windows->map_info->colormap,
9841 resource_info->pen_colors[pen_number],&border_color);
9844 case MatteEditFuzzCommand:
9847 fuzz[MaxTextExtent];
9862 Select a command from the pop-up menu.
9864 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9870 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9874 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9875 (void) XDialogWidget(display,windows,"Ok",
9876 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9879 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9880 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9884 case MatteEditValueCommand:
9887 message[MaxTextExtent];
9899 Select a command from the pop-up menu.
9901 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9907 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9909 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9910 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9911 (Quantum) TransparentAlpha);
9914 (void) FormatLocaleString(message,MaxTextExtent,
9915 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9917 (void) XDialogWidget(display,windows,"Matte",message,matte);
9922 case MatteEditUndoCommand:
9924 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9928 case MatteEditHelpCommand:
9930 XTextViewWidget(display,resource_info,windows,MagickFalse,
9931 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9934 case MatteEditDismissCommand:
9946 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9953 if (event.xbutton.button != Button1)
9955 if ((event.xbutton.window != windows->image.id) &&
9956 (event.xbutton.window != windows->magnify.id))
9963 (void) XMagickCommand(display,resource_info,windows,
9964 SaveToUndoBufferCommand,image,exception);
9965 state|=UpdateConfigurationState;
9970 if (event.xbutton.button != Button1)
9972 if ((event.xbutton.window != windows->image.id) &&
9973 (event.xbutton.window != windows->magnify.id))
9976 Update colormap information.
9980 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9981 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9982 XInfoWidget(display,windows,text);
9983 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9984 state&=(~UpdateConfigurationState);
9992 command[MaxTextExtent];
9997 if (event.xkey.window == windows->magnify.id)
10002 window=windows->magnify.id;
10003 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
10005 if (event.xkey.window != windows->image.id)
10008 Respond to a user key press.
10010 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10011 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10012 switch ((int) key_symbol)
10026 XTextViewWidget(display,resource_info,windows,MagickFalse,
10027 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10032 (void) XBell(display,0);
10041 Map and unmap Info widget as cursor crosses its boundaries.
10045 if (windows->info.mapped != MagickFalse)
10047 if ((x < (int) (windows->info.x+windows->info.width)) &&
10048 (y < (int) (windows->info.y+windows->info.height)))
10049 (void) XWithdrawWindow(display,windows->info.id,
10050 windows->info.screen);
10053 if ((x > (int) (windows->info.x+windows->info.width)) ||
10054 (y > (int) (windows->info.y+windows->info.height)))
10055 (void) XMapWindow(display,windows->info.id);
10061 if (event.xany.window == windows->magnify.id)
10063 x=windows->magnify.x-windows->image.x;
10064 y=windows->magnify.y-windows->image.y;
10068 if ((state & UpdateConfigurationState) != 0)
10078 Matte edit is relative to image configuration.
10080 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10082 XPutPixel(windows->image.ximage,x_offset,y_offset,
10083 windows->pixel_info->background_color.pixel);
10084 width=(unsigned int) (*image)->columns;
10085 height=(unsigned int) (*image)->rows;
10088 if (windows->image.crop_geometry != (char *) NULL)
10089 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10091 x_offset=(int) (width*(windows->image.x+x_offset)/
10092 windows->image.ximage->width+x);
10093 y_offset=(int) (height*(windows->image.y+y_offset)/
10094 windows->image.ximage->height+y);
10095 if ((x_offset < 0) || (y_offset < 0))
10097 if ((x_offset >= (int) (*image)->columns) ||
10098 (y_offset >= (int) (*image)->rows))
10100 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10101 return(MagickFalse);
10102 (*image)->matte=MagickTrue;
10103 image_view=AcquireCacheView(*image);
10110 Update matte information using point algorithm.
10112 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10113 (ssize_t) y_offset,1,1,exception);
10114 if (q == (Quantum *) NULL)
10116 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10117 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10120 case ReplaceMethod:
10127 virtual_pixel[CompositePixelChannel];
10130 Update matte information using replace algorithm.
10132 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
10133 (ssize_t) y_offset,virtual_pixel,exception);
10134 target.red=virtual_pixel[RedPixelChannel];
10135 target.green=virtual_pixel[GreenPixelChannel];
10136 target.blue=virtual_pixel[BluePixelChannel];
10137 target.alpha=virtual_pixel[AlphaPixelChannel];
10138 for (y=0; y < (int) (*image)->rows; y++)
10140 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10141 (*image)->columns,1,exception);
10142 if (q == (Quantum *) NULL)
10144 for (x=0; x < (int) (*image)->columns; x++)
10146 GetPixelInfoPixel(*image,q,&pixel);
10147 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10148 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10149 q+=GetPixelChannels(*image);
10151 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10156 case FloodfillMethod:
10157 case FillToBorderMethod:
10169 Update matte information using floodfill algorithm.
10171 (void) GetOneVirtualPixelInfo(*image,
10172 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10173 y_offset,&target,exception);
10174 if (method == FillToBorderMethod)
10176 target.red=(MagickRealType) ScaleShortToQuantum(
10178 target.green=(MagickRealType) ScaleShortToQuantum(
10179 border_color.green);
10180 target.blue=(MagickRealType) ScaleShortToQuantum(
10181 border_color.blue);
10183 draw_info=CloneDrawInfo(resource_info->image_info,
10184 (DrawInfo *) NULL);
10185 draw_info->fill.alpha=ClampToQuantum(StringToDouble(matte,
10187 channel_mask=SetPixelChannelMask(*image,AlphaChannel);
10188 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10189 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
10190 MagickFalse : MagickTrue,exception);
10191 (void) SetPixelChannelMapMask(*image,channel_mask);
10192 draw_info=DestroyDrawInfo(draw_info);
10198 Update matte information using reset algorithm.
10200 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10201 return(MagickFalse);
10202 for (y=0; y < (int) (*image)->rows; y++)
10204 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10205 (*image)->columns,1,exception);
10206 if (q == (Quantum *) NULL)
10208 for (x=0; x < (int) (*image)->columns; x++)
10210 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10211 q+=GetPixelChannels(*image);
10213 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10216 if (StringToLong(matte) == (long) OpaqueAlpha)
10217 (*image)->matte=MagickFalse;
10221 image_view=DestroyCacheView(image_view);
10222 state&=(~UpdateConfigurationState);
10224 } while ((state & ExitState) == 0);
10225 (void) XSelectInput(display,windows->image.id,
10226 windows->image.attributes.event_mask);
10227 XSetCursorState(display,windows,MagickFalse);
10228 (void) XFreeCursor(display,cursor);
10229 return(MagickTrue);
10233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10237 + X O p e n I m a g e %
10241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10243 % XOpenImage() loads an image from a file.
10245 % The format of the XOpenImage method is:
10247 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10248 % XWindows *windows,const unsigned int command)
10250 % A description of each parameter follows:
10252 % o display: Specifies a connection to an X server; returned from
10255 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10257 % o windows: Specifies a pointer to a XWindows structure.
10259 % o command: A value other than zero indicates that the file is selected
10260 % from the command line argument list.
10263 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10264 XWindows *windows,const MagickBooleanType command)
10279 filename[MaxTextExtent] = "\0";
10282 Request file name from user.
10284 if (command == MagickFalse)
10285 XFileBrowserWidget(display,windows,"Open",filename);
10301 Select next image from the command line.
10303 status=XGetCommand(display,windows->image.id,&files,&count);
10306 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10307 return((Image *) NULL);
10309 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10310 if (filelist == (char **) NULL)
10312 ThrowXWindowFatalException(ResourceLimitError,
10313 "MemoryAllocationFailed","...");
10314 (void) XFreeStringList(files);
10315 return((Image *) NULL);
10318 for (i=1; i < count; i++)
10319 if (*files[i] != '-')
10320 filelist[j++]=files[i];
10321 filelist[j]=(char *) NULL;
10322 XListBrowserWidget(display,windows,&windows->widget,
10323 (const char **) filelist,"Load","Select Image to Load:",filename);
10324 filelist=(char **) RelinquishMagickMemory(filelist);
10325 (void) XFreeStringList(files);
10327 if (*filename == '\0')
10328 return((Image *) NULL);
10329 image_info=CloneImageInfo(resource_info->image_info);
10330 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10332 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10333 exception=AcquireExceptionInfo();
10334 (void) SetImageInfo(image_info,0,exception);
10335 if (LocaleCompare(image_info->magick,"X") == 0)
10338 seconds[MaxTextExtent];
10341 User may want to delay the X server screen grab.
10343 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10344 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10346 if (*seconds == '\0')
10347 return((Image *) NULL);
10348 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10350 magick_info=GetMagickInfo(image_info->magick,exception);
10351 if ((magick_info != (const MagickInfo *) NULL) &&
10352 (magick_info->raw != MagickFalse))
10355 geometry[MaxTextExtent];
10358 Request image size from the user.
10360 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10361 if (image_info->size != (char *) NULL)
10362 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10363 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10365 (void) CloneString(&image_info->size,geometry);
10370 XSetCursorState(display,windows,MagickTrue);
10371 XCheckRefreshWindows(display,windows);
10372 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10373 nexus=ReadImage(image_info,exception);
10374 CatchException(exception);
10375 XSetCursorState(display,windows,MagickFalse);
10376 if (nexus != (Image *) NULL)
10377 XClientMessage(display,windows->image.id,windows->im_protocols,
10378 windows->im_next_image,CurrentTime);
10386 Unknown image format.
10388 text=FileToString(filename,~0,exception);
10389 if (text == (char *) NULL)
10390 return((Image *) NULL);
10391 textlist=StringToList(text);
10392 if (textlist != (char **) NULL)
10395 title[MaxTextExtent];
10400 (void) FormatLocaleString(title,MaxTextExtent,
10401 "Unknown format: %s",filename);
10402 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10403 (const char **) textlist);
10404 for (i=0; textlist[i] != (char *) NULL; i++)
10405 textlist[i]=DestroyString(textlist[i]);
10406 textlist=(char **) RelinquishMagickMemory(textlist);
10408 text=DestroyString(text);
10410 exception=DestroyExceptionInfo(exception);
10411 image_info=DestroyImageInfo(image_info);
10416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10420 + X P a n I m a g e %
10424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10426 % XPanImage() pans the image until the mouse button is released.
10428 % The format of the XPanImage method is:
10430 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10431 % ExceptionInfo *exception)
10433 % A description of each parameter follows:
10435 % o display: Specifies a connection to an X server; returned from
10438 % o windows: Specifies a pointer to a XWindows structure.
10440 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10441 % the entire image is refreshed.
10443 % o exception: return any errors or warnings in this structure.
10446 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10447 ExceptionInfo *exception)
10450 text[MaxTextExtent];
10468 if ((windows->image.ximage->width > (int) windows->image.width) &&
10469 (windows->image.ximage->height > (int) windows->image.height))
10470 cursor=XCreateFontCursor(display,XC_fleur);
10472 if (windows->image.ximage->width > (int) windows->image.width)
10473 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10475 if (windows->image.ximage->height > (int) windows->image.height)
10476 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10478 cursor=XCreateFontCursor(display,XC_arrow);
10479 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10481 Pan image as pointer moves until the mouse button is released.
10483 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10484 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10485 pan_info.width=windows->pan.width*windows->image.width/
10486 windows->image.ximage->width;
10487 pan_info.height=windows->pan.height*windows->image.height/
10488 windows->image.ximage->height;
10491 state=UpdateConfigurationState;
10494 switch (event->type)
10499 User choose an initial pan location.
10501 pan_info.x=(ssize_t) event->xbutton.x;
10502 pan_info.y=(ssize_t) event->xbutton.y;
10503 state|=UpdateConfigurationState;
10506 case ButtonRelease:
10509 User has finished panning the image.
10511 pan_info.x=(ssize_t) event->xbutton.x;
10512 pan_info.y=(ssize_t) event->xbutton.y;
10513 state|=UpdateConfigurationState | ExitState;
10518 pan_info.x=(ssize_t) event->xmotion.x;
10519 pan_info.y=(ssize_t) event->xmotion.y;
10520 state|=UpdateConfigurationState;
10525 if ((state & UpdateConfigurationState) != 0)
10528 Check boundary conditions.
10530 if (pan_info.x < (ssize_t) (pan_info.width/2))
10533 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10534 if (pan_info.x < 0)
10537 if ((int) (pan_info.x+windows->image.width) >
10538 windows->image.ximage->width)
10539 pan_info.x=(ssize_t)
10540 (windows->image.ximage->width-windows->image.width);
10541 if (pan_info.y < (ssize_t) (pan_info.height/2))
10544 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10545 if (pan_info.y < 0)
10548 if ((int) (pan_info.y+windows->image.height) >
10549 windows->image.ximage->height)
10550 pan_info.y=(ssize_t)
10551 (windows->image.ximage->height-windows->image.height);
10552 if ((windows->image.x != (int) pan_info.x) ||
10553 (windows->image.y != (int) pan_info.y))
10556 Display image pan offset.
10558 windows->image.x=(int) pan_info.x;
10559 windows->image.y=(int) pan_info.y;
10560 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10561 windows->image.width,windows->image.height,windows->image.x,
10563 XInfoWidget(display,windows,text);
10565 Refresh Image window.
10567 XDrawPanRectangle(display,windows);
10568 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10570 state&=(~UpdateConfigurationState);
10573 Wait for next event.
10575 if ((state & ExitState) == 0)
10576 XScreenEvent(display,windows,event,exception);
10577 } while ((state & ExitState) == 0);
10581 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10582 (void) XFreeCursor(display,cursor);
10583 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10591 + X P a s t e I m a g e %
10595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10597 % XPasteImage() pastes an image previously saved with XCropImage in the X
10598 % window image at a location the user chooses with the pointer.
10600 % The format of the XPasteImage method is:
10602 % MagickBooleanType XPasteImage(Display *display,
10603 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10604 % ExceptionInfo *exception)
10606 % A description of each parameter follows:
10608 % o display: Specifies a connection to an X server; returned from
10611 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10613 % o windows: Specifies a pointer to a XWindows structure.
10615 % o image: the image; returned from ReadImage.
10617 % o exception: return any errors or warnings in this structure.
10620 static MagickBooleanType XPasteImage(Display *display,
10621 XResourceInfo *resource_info,XWindows *windows,Image *image,
10622 ExceptionInfo *exception)
10633 static const ModeType
10636 PasteOperatorsCommand,
10638 PasteDismissCommand
10641 static CompositeOperator
10642 compose = CopyCompositeOp;
10645 text[MaxTextExtent];
10679 if (resource_info->copy_image == (Image *) NULL)
10680 return(MagickFalse);
10681 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10683 Map Command widget.
10685 (void) CloneString(&windows->command.name,"Paste");
10686 windows->command.data=1;
10687 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10688 (void) XMapRaised(display,windows->command.id);
10689 XClientMessage(display,windows->image.id,windows->im_protocols,
10690 windows->im_update_widget,CurrentTime);
10692 Track pointer until button 1 is pressed.
10694 XSetCursorState(display,windows,MagickFalse);
10695 XQueryPosition(display,windows->image.id,&x,&y);
10696 (void) XSelectInput(display,windows->image.id,
10697 windows->image.attributes.event_mask | PointerMotionMask);
10698 paste_info.x=(ssize_t) windows->image.x+x;
10699 paste_info.y=(ssize_t) windows->image.y+y;
10700 paste_info.width=0;
10701 paste_info.height=0;
10702 cursor=XCreateFontCursor(display,XC_ul_angle);
10703 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10704 state=DefaultState;
10707 if (windows->info.mapped != MagickFalse)
10710 Display pointer position.
10712 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10713 (long) paste_info.x,(long) paste_info.y);
10714 XInfoWidget(display,windows,text);
10716 highlight_info=paste_info;
10717 highlight_info.x=paste_info.x-windows->image.x;
10718 highlight_info.y=paste_info.y-windows->image.y;
10719 XHighlightRectangle(display,windows->image.id,
10720 windows->image.highlight_context,&highlight_info);
10722 Wait for next event.
10724 XScreenEvent(display,windows,&event,exception);
10725 XHighlightRectangle(display,windows->image.id,
10726 windows->image.highlight_context,&highlight_info);
10727 if (event.xany.window == windows->command.id)
10730 Select a command from the Command widget.
10732 id=XCommandWidget(display,windows,PasteMenu,&event);
10735 switch (PasteCommands[id])
10737 case PasteOperatorsCommand:
10740 command[MaxTextExtent],
10744 Select a command from the pop-up menu.
10746 operators=GetCommandOptions(MagickComposeOptions);
10747 if (operators == (char **) NULL)
10749 entry=XMenuWidget(display,windows,PasteMenu[id],
10750 (const char **) operators,command);
10752 compose=(CompositeOperator) ParseCommandOption(
10753 MagickComposeOptions,MagickFalse,operators[entry]);
10754 operators=DestroyStringList(operators);
10757 case PasteHelpCommand:
10759 XTextViewWidget(display,resource_info,windows,MagickFalse,
10760 "Help Viewer - Image Composite",ImagePasteHelp);
10763 case PasteDismissCommand:
10768 state|=EscapeState;
10777 switch (event.type)
10781 if (image->debug != MagickFalse)
10782 (void) LogMagickEvent(X11Event,GetMagickModule(),
10783 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10784 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10785 if (event.xbutton.button != Button1)
10787 if (event.xbutton.window != windows->image.id)
10790 Paste rectangle is relative to image configuration.
10792 width=(unsigned int) image->columns;
10793 height=(unsigned int) image->rows;
10796 if (windows->image.crop_geometry != (char *) NULL)
10797 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10799 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10800 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10801 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10802 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10803 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10804 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10805 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10808 case ButtonRelease:
10810 if (image->debug != MagickFalse)
10811 (void) LogMagickEvent(X11Event,GetMagickModule(),
10812 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10813 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10814 if (event.xbutton.button != Button1)
10816 if (event.xbutton.window != windows->image.id)
10818 if ((paste_info.width != 0) && (paste_info.height != 0))
10821 User has selected the location of the paste image.
10823 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10824 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10834 command[MaxTextExtent];
10842 if (event.xkey.window != windows->image.id)
10845 Respond to a user key press.
10847 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10848 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10849 *(command+length)='\0';
10850 if (image->debug != MagickFalse)
10851 (void) LogMagickEvent(X11Event,GetMagickModule(),
10852 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10853 switch ((int) key_symbol)
10861 paste_image=DestroyImage(paste_image);
10862 state|=EscapeState;
10869 (void) XSetFunction(display,windows->image.highlight_context,
10871 XTextViewWidget(display,resource_info,windows,MagickFalse,
10872 "Help Viewer - Image Composite",ImagePasteHelp);
10873 (void) XSetFunction(display,windows->image.highlight_context,
10879 (void) XBell(display,0);
10888 Map and unmap Info widget as text cursor crosses its boundaries.
10892 if (windows->info.mapped != MagickFalse)
10894 if ((x < (int) (windows->info.x+windows->info.width)) &&
10895 (y < (int) (windows->info.y+windows->info.height)))
10896 (void) XWithdrawWindow(display,windows->info.id,
10897 windows->info.screen);
10900 if ((x > (int) (windows->info.x+windows->info.width)) ||
10901 (y > (int) (windows->info.y+windows->info.height)))
10902 (void) XMapWindow(display,windows->info.id);
10903 paste_info.x=(ssize_t) windows->image.x+x;
10904 paste_info.y=(ssize_t) windows->image.y+y;
10909 if (image->debug != MagickFalse)
10910 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10915 } while ((state & ExitState) == 0);
10916 (void) XSelectInput(display,windows->image.id,
10917 windows->image.attributes.event_mask);
10918 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10919 XSetCursorState(display,windows,MagickFalse);
10920 (void) XFreeCursor(display,cursor);
10921 if ((state & EscapeState) != 0)
10922 return(MagickTrue);
10924 Image pasting is relative to image configuration.
10926 XSetCursorState(display,windows,MagickTrue);
10927 XCheckRefreshWindows(display,windows);
10928 width=(unsigned int) image->columns;
10929 height=(unsigned int) image->rows;
10932 if (windows->image.crop_geometry != (char *) NULL)
10933 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10934 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10936 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10937 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10938 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10940 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10941 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10943 Paste image with X Image window.
10945 (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y,
10947 paste_image=DestroyImage(paste_image);
10948 XSetCursorState(display,windows,MagickFalse);
10950 Update image colormap.
10952 XConfigureImageColormap(display,resource_info,windows,image,exception);
10953 (void) XConfigureImage(display,resource_info,windows,image,exception);
10954 return(MagickTrue);
10958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10962 + X P r i n t I m a g e %
10966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10968 % XPrintImage() prints an image to a Postscript printer.
10970 % The format of the XPrintImage method is:
10972 % MagickBooleanType XPrintImage(Display *display,
10973 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10974 % ExceptionInfo *exception)
10976 % A description of each parameter follows:
10978 % o display: Specifies a connection to an X server; returned from
10981 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10983 % o windows: Specifies a pointer to a XWindows structure.
10985 % o image: the image.
10987 % o exception: return any errors or warnings in this structure.
10990 static MagickBooleanType XPrintImage(Display *display,
10991 XResourceInfo *resource_info,XWindows *windows,Image *image,
10992 ExceptionInfo *exception)
10995 filename[MaxTextExtent],
10996 geometry[MaxTextExtent];
11008 Request Postscript page geometry from user.
11010 image_info=CloneImageInfo(resource_info->image_info);
11011 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
11012 if (image_info->page != (char *) NULL)
11013 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11014 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11015 "Select Postscript Page Geometry:",geometry);
11016 if (*geometry == '\0')
11017 return(MagickTrue);
11018 image_info->page=GetPageGeometry(geometry);
11020 Apply image transforms.
11022 XSetCursorState(display,windows,MagickTrue);
11023 XCheckRefreshWindows(display,windows);
11024 print_image=CloneImage(image,0,0,MagickTrue,exception);
11025 if (print_image == (Image *) NULL)
11026 return(MagickFalse);
11027 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11028 windows->image.ximage->width,windows->image.ximage->height);
11029 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11034 (void) AcquireUniqueFilename(filename);
11035 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11037 status=WriteImage(image_info,print_image,exception);
11038 (void) RelinquishUniqueFileResource(filename);
11039 print_image=DestroyImage(print_image);
11040 image_info=DestroyImageInfo(image_info);
11041 XSetCursorState(display,windows,MagickFalse);
11042 return(status != 0 ? MagickTrue : MagickFalse);
11046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11050 + X R O I I m a g e %
11054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11056 % XROIImage() applies an image processing technique to a region of interest.
11058 % The format of the XROIImage method is:
11060 % MagickBooleanType XROIImage(Display *display,
11061 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11062 % ExceptionInfo *exception)
11064 % A description of each parameter follows:
11066 % o display: Specifies a connection to an X server; returned from
11069 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11071 % o windows: Specifies a pointer to a XWindows structure.
11073 % o image: the image; returned from ReadImage.
11075 % o exception: return any errors or warnings in this structure.
11078 static MagickBooleanType XROIImage(Display *display,
11079 XResourceInfo *resource_info,XWindows *windows,Image **image,
11080 ExceptionInfo *exception)
11082 #define ApplyMenus 7
11132 "Contrast Stretch...",
11133 "Sigmoidal Contrast...",
11167 "Charcoal Draw...",
11170 *MiscellanyMenu[] =
11181 **Menus[ApplyMenus] =
11192 static const CommandType
11215 TransformCommands[] =
11219 RotateRightCommand,
11222 EnhanceCommands[] =
11230 ContrastStretchCommand,
11231 SigmoidalContrastCommand,
11239 EffectsCommands[] =
11243 ReduceNoiseCommand,
11262 CharcoalDrawCommand
11264 MiscellanyCommands[] =
11268 ShowPreviewCommand,
11269 ShowHistogramCommand,
11278 static const CommandType
11279 *Commands[ApplyMenus] =
11291 command[MaxTextExtent],
11292 text[MaxTextExtent];
11312 MagickProgressMonitor
11331 Map Command widget.
11333 (void) CloneString(&windows->command.name,"ROI");
11334 windows->command.data=0;
11335 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11336 (void) XMapRaised(display,windows->command.id);
11337 XClientMessage(display,windows->image.id,windows->im_protocols,
11338 windows->im_update_widget,CurrentTime);
11340 Track pointer until button 1 is pressed.
11342 XQueryPosition(display,windows->image.id,&x,&y);
11343 (void) XSelectInput(display,windows->image.id,
11344 windows->image.attributes.event_mask | PointerMotionMask);
11345 roi_info.x=(ssize_t) windows->image.x+x;
11346 roi_info.y=(ssize_t) windows->image.y+y;
11349 cursor=XCreateFontCursor(display,XC_fleur);
11350 state=DefaultState;
11353 if (windows->info.mapped != MagickFalse)
11356 Display pointer position.
11358 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11359 (long) roi_info.x,(long) roi_info.y);
11360 XInfoWidget(display,windows,text);
11363 Wait for next event.
11365 XScreenEvent(display,windows,&event,exception);
11366 if (event.xany.window == windows->command.id)
11369 Select a command from the Command widget.
11371 id=XCommandWidget(display,windows,ROIMenu,&event);
11374 switch (ROICommands[id])
11376 case ROIHelpCommand:
11378 XTextViewWidget(display,resource_info,windows,MagickFalse,
11379 "Help Viewer - Region of Interest",ImageROIHelp);
11382 case ROIDismissCommand:
11387 state|=EscapeState;
11396 switch (event.type)
11400 if (event.xbutton.button != Button1)
11402 if (event.xbutton.window != windows->image.id)
11405 Note first corner of region of interest rectangle-- exit loop.
11407 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11408 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11409 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11413 case ButtonRelease:
11422 if (event.xkey.window != windows->image.id)
11425 Respond to a user key press.
11427 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11428 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11429 switch ((int) key_symbol)
11437 state|=EscapeState;
11444 XTextViewWidget(display,resource_info,windows,MagickFalse,
11445 "Help Viewer - Region of Interest",ImageROIHelp);
11450 (void) XBell(display,0);
11459 Map and unmap Info widget as text cursor crosses its boundaries.
11463 if (windows->info.mapped != MagickFalse)
11465 if ((x < (int) (windows->info.x+windows->info.width)) &&
11466 (y < (int) (windows->info.y+windows->info.height)))
11467 (void) XWithdrawWindow(display,windows->info.id,
11468 windows->info.screen);
11471 if ((x > (int) (windows->info.x+windows->info.width)) ||
11472 (y > (int) (windows->info.y+windows->info.height)))
11473 (void) XMapWindow(display,windows->info.id);
11474 roi_info.x=(ssize_t) windows->image.x+x;
11475 roi_info.y=(ssize_t) windows->image.y+y;
11481 } while ((state & ExitState) == 0);
11482 (void) XSelectInput(display,windows->image.id,
11483 windows->image.attributes.event_mask);
11484 if ((state & EscapeState) != 0)
11487 User want to exit without region of interest.
11489 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11490 (void) XFreeCursor(display,cursor);
11491 return(MagickTrue);
11493 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11497 Size rectangle as pointer moves until the mouse button is released.
11499 x=(int) roi_info.x;
11500 y=(int) roi_info.y;
11503 state=DefaultState;
11506 highlight_info=roi_info;
11507 highlight_info.x=roi_info.x-windows->image.x;
11508 highlight_info.y=roi_info.y-windows->image.y;
11509 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11512 Display info and draw region of interest rectangle.
11514 if (windows->info.mapped == MagickFalse)
11515 (void) XMapWindow(display,windows->info.id);
11516 (void) FormatLocaleString(text,MaxTextExtent,
11517 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11518 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11519 XInfoWidget(display,windows,text);
11520 XHighlightRectangle(display,windows->image.id,
11521 windows->image.highlight_context,&highlight_info);
11524 if (windows->info.mapped != MagickFalse)
11525 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11527 Wait for next event.
11529 XScreenEvent(display,windows,&event,exception);
11530 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11531 XHighlightRectangle(display,windows->image.id,
11532 windows->image.highlight_context,&highlight_info);
11533 switch (event.type)
11537 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11538 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11541 case ButtonRelease:
11544 User has committed to region of interest rectangle.
11546 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11547 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11548 XSetCursorState(display,windows,MagickFalse);
11550 if (LocaleCompare(windows->command.name,"Apply") == 0)
11552 (void) CloneString(&windows->command.name,"Apply");
11553 windows->command.data=ApplyMenus;
11554 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11561 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11562 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11567 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11568 ((state & ExitState) != 0))
11571 Check boundary conditions.
11573 if (roi_info.x < 0)
11576 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11577 roi_info.x=(ssize_t) windows->image.ximage->width;
11578 if ((int) roi_info.x < x)
11579 roi_info.width=(unsigned int) (x-roi_info.x);
11582 roi_info.width=(unsigned int) (roi_info.x-x);
11583 roi_info.x=(ssize_t) x;
11585 if (roi_info.y < 0)
11588 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11589 roi_info.y=(ssize_t) windows->image.ximage->height;
11590 if ((int) roi_info.y < y)
11591 roi_info.height=(unsigned int) (y-roi_info.y);
11594 roi_info.height=(unsigned int) (roi_info.y-y);
11595 roi_info.y=(ssize_t) y;
11598 } while ((state & ExitState) == 0);
11600 Wait for user to grab a corner of the rectangle or press return.
11602 state=DefaultState;
11603 command_type=NullCommand;
11604 (void) XMapWindow(display,windows->info.id);
11607 if (windows->info.mapped != MagickFalse)
11610 Display pointer position.
11612 (void) FormatLocaleString(text,MaxTextExtent,
11613 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11614 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11615 XInfoWidget(display,windows,text);
11617 highlight_info=roi_info;
11618 highlight_info.x=roi_info.x-windows->image.x;
11619 highlight_info.y=roi_info.y-windows->image.y;
11620 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11622 state|=EscapeState;
11626 if ((state & UpdateRegionState) != 0)
11628 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11629 switch (command_type)
11634 (void) XMagickCommand(display,resource_info,windows,command_type,
11641 Region of interest is relative to image configuration.
11643 progress_monitor=SetImageProgressMonitor(*image,
11644 (MagickProgressMonitor) NULL,(*image)->client_data);
11645 crop_info=roi_info;
11646 width=(unsigned int) (*image)->columns;
11647 height=(unsigned int) (*image)->rows;
11650 if (windows->image.crop_geometry != (char *) NULL)
11651 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11653 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11655 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11656 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11657 scale_factor=(MagickRealType)
11658 height/windows->image.ximage->height;
11660 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11661 crop_info.height=(unsigned int)
11662 (scale_factor*crop_info.height+0.5);
11663 roi_image=CropImage(*image,&crop_info,exception);
11664 (void) SetImageProgressMonitor(*image,progress_monitor,
11665 (*image)->client_data);
11666 if (roi_image == (Image *) NULL)
11669 Apply image processing technique to the region of interest.
11671 windows->image.orphan=MagickTrue;
11672 (void) XMagickCommand(display,resource_info,windows,command_type,
11673 &roi_image,exception);
11674 progress_monitor=SetImageProgressMonitor(*image,
11675 (MagickProgressMonitor) NULL,(*image)->client_data);
11676 (void) XMagickCommand(display,resource_info,windows,
11677 SaveToUndoBufferCommand,image,exception);
11678 windows->image.orphan=MagickFalse;
11679 (void) CompositeImage(*image,CopyCompositeOp,roi_image,
11680 crop_info.x,crop_info.y,exception);
11681 roi_image=DestroyImage(roi_image);
11682 (void) SetImageProgressMonitor(*image,progress_monitor,
11683 (*image)->client_data);
11687 if (command_type != InfoCommand)
11689 XConfigureImageColormap(display,resource_info,windows,*image,
11691 (void) XConfigureImage(display,resource_info,windows,*image,
11694 XCheckRefreshWindows(display,windows);
11695 XInfoWidget(display,windows,text);
11696 (void) XSetFunction(display,windows->image.highlight_context,
11698 state&=(~UpdateRegionState);
11700 XHighlightRectangle(display,windows->image.id,
11701 windows->image.highlight_context,&highlight_info);
11702 XScreenEvent(display,windows,&event,exception);
11703 if (event.xany.window == windows->command.id)
11706 Select a command from the Command widget.
11708 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11709 command_type=NullCommand;
11710 id=XCommandWidget(display,windows,ApplyMenu,&event);
11713 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11714 command_type=ApplyCommands[id];
11715 if (id < ApplyMenus)
11718 Select a command from a pop-up menu.
11720 entry=XMenuWidget(display,windows,ApplyMenu[id],
11721 (const char **) Menus[id],command);
11724 (void) CopyMagickString(command,Menus[id][entry],
11726 command_type=Commands[id][entry];
11730 (void) XSetFunction(display,windows->image.highlight_context,
11732 XHighlightRectangle(display,windows->image.id,
11733 windows->image.highlight_context,&highlight_info);
11734 if (command_type == HelpCommand)
11736 (void) XSetFunction(display,windows->image.highlight_context,
11738 XTextViewWidget(display,resource_info,windows,MagickFalse,
11739 "Help Viewer - Region of Interest",ImageROIHelp);
11740 (void) XSetFunction(display,windows->image.highlight_context,
11744 if (command_type == QuitCommand)
11749 state|=EscapeState;
11753 if (command_type != NullCommand)
11754 state|=UpdateRegionState;
11757 XHighlightRectangle(display,windows->image.id,
11758 windows->image.highlight_context,&highlight_info);
11759 switch (event.type)
11763 x=windows->image.x;
11764 y=windows->image.y;
11765 if (event.xbutton.button != Button1)
11767 if (event.xbutton.window != windows->image.id)
11769 x=windows->image.x+event.xbutton.x;
11770 y=windows->image.y+event.xbutton.y;
11771 if ((x < (int) (roi_info.x+RoiDelta)) &&
11772 (x > (int) (roi_info.x-RoiDelta)) &&
11773 (y < (int) (roi_info.y+RoiDelta)) &&
11774 (y > (int) (roi_info.y-RoiDelta)))
11776 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11777 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11778 state|=UpdateConfigurationState;
11781 if ((x < (int) (roi_info.x+RoiDelta)) &&
11782 (x > (int) (roi_info.x-RoiDelta)) &&
11783 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11784 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11786 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11787 state|=UpdateConfigurationState;
11790 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11791 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11792 (y < (int) (roi_info.y+RoiDelta)) &&
11793 (y > (int) (roi_info.y-RoiDelta)))
11795 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11796 state|=UpdateConfigurationState;
11799 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11800 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11801 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11802 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11804 state|=UpdateConfigurationState;
11808 case ButtonRelease:
11810 if (event.xbutton.window == windows->pan.id)
11811 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11812 (highlight_info.y != crop_info.y-windows->image.y))
11813 XHighlightRectangle(display,windows->image.id,
11814 windows->image.highlight_context,&highlight_info);
11815 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11816 event.xbutton.time);
11821 if (event.xexpose.window == windows->image.id)
11822 if (event.xexpose.count == 0)
11824 event.xexpose.x=(int) highlight_info.x;
11825 event.xexpose.y=(int) highlight_info.y;
11826 event.xexpose.width=(int) highlight_info.width;
11827 event.xexpose.height=(int) highlight_info.height;
11828 XRefreshWindow(display,&windows->image,&event);
11830 if (event.xexpose.window == windows->info.id)
11831 if (event.xexpose.count == 0)
11832 XInfoWidget(display,windows,text);
11840 if (event.xkey.window != windows->image.id)
11843 Respond to a user key press.
11845 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11846 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11847 switch ((int) key_symbol)
11854 state|=EscapeState;
11863 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11864 roi_info.y=(ssize_t) (windows->image.height/2L-
11865 roi_info.height/2L);
11897 (void) XSetFunction(display,windows->image.highlight_context,
11899 XTextViewWidget(display,resource_info,windows,MagickFalse,
11900 "Help Viewer - Region of Interest",ImageROIHelp);
11901 (void) XSetFunction(display,windows->image.highlight_context,
11907 command_type=XImageWindowCommand(display,resource_info,windows,
11908 event.xkey.state,key_symbol,image,exception);
11909 if (command_type != NullCommand)
11910 state|=UpdateRegionState;
11914 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11922 if (event.xbutton.window != windows->image.id)
11925 Map and unmap Info widget as text cursor crosses its boundaries.
11929 if (windows->info.mapped != MagickFalse)
11931 if ((x < (int) (windows->info.x+windows->info.width)) &&
11932 (y < (int) (windows->info.y+windows->info.height)))
11933 (void) XWithdrawWindow(display,windows->info.id,
11934 windows->info.screen);
11937 if ((x > (int) (windows->info.x+windows->info.width)) ||
11938 (y > (int) (windows->info.y+windows->info.height)))
11939 (void) XMapWindow(display,windows->info.id);
11940 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11941 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11944 case SelectionRequest:
11949 XSelectionRequestEvent
11953 Set primary selection.
11955 (void) FormatLocaleString(text,MaxTextExtent,
11956 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11957 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11958 request=(&(event.xselectionrequest));
11959 (void) XChangeProperty(request->display,request->requestor,
11960 request->property,request->target,8,PropModeReplace,
11961 (unsigned char *) text,(int) strlen(text));
11962 notify.type=SelectionNotify;
11963 notify.display=request->display;
11964 notify.requestor=request->requestor;
11965 notify.selection=request->selection;
11966 notify.target=request->target;
11967 notify.time=request->time;
11968 if (request->property == None)
11969 notify.property=request->target;
11971 notify.property=request->property;
11972 (void) XSendEvent(request->display,request->requestor,False,0,
11973 (XEvent *) ¬ify);
11978 if ((state & UpdateConfigurationState) != 0)
11980 (void) XPutBackEvent(display,&event);
11981 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11984 } while ((state & ExitState) == 0);
11985 } while ((state & ExitState) == 0);
11986 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11987 XSetCursorState(display,windows,MagickFalse);
11988 if ((state & EscapeState) != 0)
11989 return(MagickTrue);
11990 return(MagickTrue);
11994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11998 + X R o t a t e I m a g e %
12002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12004 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
12005 % rotation angle is computed from the slope of a line drawn by the user.
12007 % The format of the XRotateImage method is:
12009 % MagickBooleanType XRotateImage(Display *display,
12010 % XResourceInfo *resource_info,XWindows *windows,double degrees,
12011 % Image **image,ExceptionInfo *exception)
12013 % A description of each parameter follows:
12015 % o display: Specifies a connection to an X server; returned from
12018 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12020 % o windows: Specifies a pointer to a XWindows structure.
12022 % o degrees: Specifies the number of degrees to rotate the image.
12024 % o image: the image.
12026 % o exception: return any errors or warnings in this structure.
12029 static MagickBooleanType XRotateImage(Display *display,
12030 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12031 ExceptionInfo *exception)
12044 direction = HorizontalRotateCommand;
12046 static const ModeType
12047 DirectionCommands[] =
12049 HorizontalRotateCommand,
12050 VerticalRotateCommand
12054 RotateColorCommand,
12055 RotateDirectionCommand,
12057 RotateDismissCommand
12060 static unsigned int
12064 command[MaxTextExtent],
12065 text[MaxTextExtent];
12076 normalized_degrees;
12086 if (degrees == 0.0)
12101 Map Command widget.
12103 (void) CloneString(&windows->command.name,"Rotate");
12104 windows->command.data=2;
12105 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12106 (void) XMapRaised(display,windows->command.id);
12107 XClientMessage(display,windows->image.id,windows->im_protocols,
12108 windows->im_update_widget,CurrentTime);
12110 Wait for first button press.
12112 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12113 XQueryPosition(display,windows->image.id,&x,&y);
12118 state=DefaultState;
12121 XHighlightLine(display,windows->image.id,
12122 windows->image.highlight_context,&rotate_info);
12124 Wait for next event.
12126 XScreenEvent(display,windows,&event,exception);
12127 XHighlightLine(display,windows->image.id,
12128 windows->image.highlight_context,&rotate_info);
12129 if (event.xany.window == windows->command.id)
12132 Select a command from the Command widget.
12134 id=XCommandWidget(display,windows,RotateMenu,&event);
12137 (void) XSetFunction(display,windows->image.highlight_context,
12139 switch (RotateCommands[id])
12141 case RotateColorCommand:
12144 *ColorMenu[MaxNumberPens];
12153 Initialize menu selections.
12155 for (i=0; i < (int) (MaxNumberPens-2); i++)
12156 ColorMenu[i]=resource_info->pen_colors[i];
12157 ColorMenu[MaxNumberPens-2]="Browser...";
12158 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12160 Select a pen color from the pop-up menu.
12162 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12163 (const char **) ColorMenu,command);
12164 if (pen_number < 0)
12166 if (pen_number == (MaxNumberPens-2))
12169 color_name[MaxTextExtent] = "gray";
12172 Select a pen color from a dialog.
12174 resource_info->pen_colors[pen_number]=color_name;
12175 XColorBrowserWidget(display,windows,"Select",color_name);
12176 if (*color_name == '\0')
12182 (void) XParseColor(display,windows->map_info->colormap,
12183 resource_info->pen_colors[pen_number],&color);
12184 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12185 (unsigned int) MaxColors,&color);
12186 windows->pixel_info->pen_colors[pen_number]=color;
12187 pen_id=(unsigned int) pen_number;
12190 case RotateDirectionCommand:
12201 Select a command from the pop-up menu.
12203 id=XMenuWidget(display,windows,RotateMenu[id],
12204 Directions,command);
12206 direction=DirectionCommands[id];
12209 case RotateHelpCommand:
12211 XTextViewWidget(display,resource_info,windows,MagickFalse,
12212 "Help Viewer - Image Rotation",ImageRotateHelp);
12215 case RotateDismissCommand:
12220 state|=EscapeState;
12227 (void) XSetFunction(display,windows->image.highlight_context,
12231 switch (event.type)
12235 if (event.xbutton.button != Button1)
12237 if (event.xbutton.window != windows->image.id)
12242 (void) XSetFunction(display,windows->image.highlight_context,
12244 rotate_info.x1=event.xbutton.x;
12245 rotate_info.y1=event.xbutton.y;
12249 case ButtonRelease:
12256 command[MaxTextExtent];
12261 if (event.xkey.window != windows->image.id)
12264 Respond to a user key press.
12266 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12267 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12268 switch ((int) key_symbol)
12276 state|=EscapeState;
12283 (void) XSetFunction(display,windows->image.highlight_context,
12285 XTextViewWidget(display,resource_info,windows,MagickFalse,
12286 "Help Viewer - Image Rotation",ImageRotateHelp);
12287 (void) XSetFunction(display,windows->image.highlight_context,
12293 (void) XBell(display,0);
12301 rotate_info.x1=event.xmotion.x;
12302 rotate_info.y1=event.xmotion.y;
12305 rotate_info.x2=rotate_info.x1;
12306 rotate_info.y2=rotate_info.y1;
12307 if (direction == HorizontalRotateCommand)
12308 rotate_info.x2+=32;
12310 rotate_info.y2-=32;
12311 } while ((state & ExitState) == 0);
12312 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12313 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12314 if ((state & EscapeState) != 0)
12315 return(MagickTrue);
12317 Draw line as pointer moves until the mouse button is released.
12320 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12321 state=DefaultState;
12327 Display info and draw rotation line.
12329 if (windows->info.mapped == MagickFalse)
12330 (void) XMapWindow(display,windows->info.id);
12331 (void) FormatLocaleString(text,MaxTextExtent," %g",
12332 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12333 XInfoWidget(display,windows,text);
12334 XHighlightLine(display,windows->image.id,
12335 windows->image.highlight_context,&rotate_info);
12338 if (windows->info.mapped != MagickFalse)
12339 (void) XWithdrawWindow(display,windows->info.id,
12340 windows->info.screen);
12342 Wait for next event.
12344 XScreenEvent(display,windows,&event,exception);
12346 XHighlightLine(display,windows->image.id,
12347 windows->image.highlight_context,&rotate_info);
12348 switch (event.type)
12352 case ButtonRelease:
12355 User has committed to rotation line.
12357 rotate_info.x2=event.xbutton.x;
12358 rotate_info.y2=event.xbutton.y;
12366 rotate_info.x2=event.xmotion.x;
12367 rotate_info.y2=event.xmotion.y;
12373 Check boundary conditions.
12375 if (rotate_info.x2 < 0)
12378 if (rotate_info.x2 > (int) windows->image.width)
12379 rotate_info.x2=(short) windows->image.width;
12380 if (rotate_info.y2 < 0)
12383 if (rotate_info.y2 > (int) windows->image.height)
12384 rotate_info.y2=(short) windows->image.height;
12386 Compute rotation angle from the slope of the line.
12389 distance=(unsigned int)
12390 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12391 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12393 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12394 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12395 } while ((state & ExitState) == 0);
12396 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12397 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12399 return(MagickTrue);
12401 if (direction == VerticalRotateCommand)
12403 if (degrees == 0.0)
12404 return(MagickTrue);
12408 normalized_degrees=degrees;
12409 while (normalized_degrees < -45.0)
12410 normalized_degrees+=360.0;
12411 for (rotations=0; normalized_degrees > 45.0; rotations++)
12412 normalized_degrees-=90.0;
12413 if (normalized_degrees != 0.0)
12414 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12416 XSetCursorState(display,windows,MagickTrue);
12417 XCheckRefreshWindows(display,windows);
12418 (*image)->background_color.red=ScaleShortToQuantum(
12419 windows->pixel_info->pen_colors[pen_id].red);
12420 (*image)->background_color.green=ScaleShortToQuantum(
12421 windows->pixel_info->pen_colors[pen_id].green);
12422 (*image)->background_color.blue=ScaleShortToQuantum(
12423 windows->pixel_info->pen_colors[pen_id].blue);
12424 rotate_image=RotateImage(*image,degrees,exception);
12425 XSetCursorState(display,windows,MagickFalse);
12426 if (rotate_image == (Image *) NULL)
12427 return(MagickFalse);
12428 *image=DestroyImage(*image);
12429 *image=rotate_image;
12430 if (windows->image.crop_geometry != (char *) NULL)
12433 Rotate crop geometry.
12435 width=(unsigned int) (*image)->columns;
12436 height=(unsigned int) (*image)->rows;
12437 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12438 switch (rotations % 4)
12448 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12449 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12456 Rotate 180 degrees.
12458 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12459 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12465 Rotate 270 degrees.
12467 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12468 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12473 if (windows->image.orphan != MagickFalse)
12474 return(MagickTrue);
12475 if (normalized_degrees != 0.0)
12478 Update image colormap.
12480 windows->image.window_changes.width=(int) (*image)->columns;
12481 windows->image.window_changes.height=(int) (*image)->rows;
12482 if (windows->image.crop_geometry != (char *) NULL)
12485 Obtain dimensions of image from crop geometry.
12487 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12489 windows->image.window_changes.width=(int) width;
12490 windows->image.window_changes.height=(int) height;
12492 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12495 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12497 windows->image.window_changes.width=windows->image.ximage->height;
12498 windows->image.window_changes.height=windows->image.ximage->width;
12501 Update image configuration.
12503 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12504 return(MagickTrue);
12508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12512 + X S a v e I m a g e %
12516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12518 % XSaveImage() saves an image to a file.
12520 % The format of the XSaveImage method is:
12522 % MagickBooleanType XSaveImage(Display *display,
12523 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12524 % ExceptionInfo *exception)
12526 % A description of each parameter follows:
12528 % o display: Specifies a connection to an X server; returned from
12531 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12533 % o windows: Specifies a pointer to a XWindows structure.
12535 % o image: the image.
12537 % o exception: return any errors or warnings in this structure.
12540 static MagickBooleanType XSaveImage(Display *display,
12541 XResourceInfo *resource_info,XWindows *windows,Image *image,
12542 ExceptionInfo *exception)
12545 filename[MaxTextExtent],
12546 geometry[MaxTextExtent];
12558 Request file name from user.
12560 if (resource_info->write_filename != (char *) NULL)
12561 (void) CopyMagickString(filename,resource_info->write_filename,
12566 path[MaxTextExtent];
12571 GetPathComponent(image->filename,HeadPath,path);
12572 GetPathComponent(image->filename,TailPath,filename);
12575 status=chdir(path);
12577 (void) ThrowMagickException(exception,GetMagickModule(),
12578 FileOpenError,"UnableToOpenFile","%s",path);
12581 XFileBrowserWidget(display,windows,"Save",filename);
12582 if (*filename == '\0')
12583 return(MagickTrue);
12584 if (IsPathAccessible(filename) != MagickFalse)
12590 File exists-- seek user's permission before overwriting.
12592 status=XConfirmWidget(display,windows,"Overwrite",filename);
12594 return(MagickTrue);
12596 image_info=CloneImageInfo(resource_info->image_info);
12597 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12598 (void) SetImageInfo(image_info,1,exception);
12599 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12600 (LocaleCompare(image_info->magick,"JPG") == 0))
12603 quality[MaxTextExtent];
12609 Request JPEG quality from user.
12611 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12613 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12615 if (*quality == '\0')
12616 return(MagickTrue);
12617 image->quality=StringToUnsignedLong(quality);
12618 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12620 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12621 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12622 (LocaleCompare(image_info->magick,"PS") == 0) ||
12623 (LocaleCompare(image_info->magick,"PS2") == 0))
12626 geometry[MaxTextExtent];
12629 Request page geometry from user.
12631 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12632 if (LocaleCompare(image_info->magick,"PDF") == 0)
12633 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12634 if (image_info->page != (char *) NULL)
12635 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12636 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12637 "Select page geometry:",geometry);
12638 if (*geometry != '\0')
12639 image_info->page=GetPageGeometry(geometry);
12642 Apply image transforms.
12644 XSetCursorState(display,windows,MagickTrue);
12645 XCheckRefreshWindows(display,windows);
12646 save_image=CloneImage(image,0,0,MagickTrue,exception);
12647 if (save_image == (Image *) NULL)
12648 return(MagickFalse);
12649 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12650 windows->image.ximage->width,windows->image.ximage->height);
12651 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12656 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12657 status=WriteImage(image_info,save_image,exception);
12658 if (status != MagickFalse)
12659 image->taint=MagickFalse;
12660 save_image=DestroyImage(save_image);
12661 image_info=DestroyImageInfo(image_info);
12662 XSetCursorState(display,windows,MagickFalse);
12663 return(status != 0 ? MagickTrue : MagickFalse);
12667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12671 + X S c r e e n E v e n t %
12675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12677 % XScreenEvent() handles global events associated with the Pan and Magnify
12680 % The format of the XScreenEvent function is:
12682 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12683 % ExceptionInfo *exception)
12685 % A description of each parameter follows:
12687 % o display: Specifies a pointer to the Display structure; returned from
12690 % o windows: Specifies a pointer to a XWindows structure.
12692 % o event: Specifies a pointer to a X11 XEvent structure.
12694 % o exception: return any errors or warnings in this structure.
12698 #if defined(__cplusplus) || defined(c_plusplus)
12702 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12707 windows=(XWindows *) data;
12708 if ((event->type == ClientMessage) &&
12709 (event->xclient.window == windows->image.id))
12710 return(MagickFalse);
12711 return(MagickTrue);
12714 #if defined(__cplusplus) || defined(c_plusplus)
12718 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12719 ExceptionInfo *exception)
12725 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12726 if (event->xany.window == windows->command.id)
12728 switch (event->type)
12731 case ButtonRelease:
12733 if ((event->xbutton.button == Button3) &&
12734 (event->xbutton.state & Mod1Mask))
12737 Convert Alt-Button3 to Button2.
12739 event->xbutton.button=Button2;
12740 event->xbutton.state&=(~Mod1Mask);
12742 if (event->xbutton.window == windows->backdrop.id)
12744 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12745 event->xbutton.time);
12748 if (event->xbutton.window == windows->pan.id)
12750 XPanImage(display,windows,event,exception);
12753 if (event->xbutton.window == windows->image.id)
12754 if (event->xbutton.button == Button2)
12757 Update magnified image.
12759 x=event->xbutton.x;
12760 y=event->xbutton.y;
12764 if (x >= (int) windows->image.width)
12765 x=(int) (windows->image.width-1);
12766 windows->magnify.x=(int) windows->image.x+x;
12770 if (y >= (int) windows->image.height)
12771 y=(int) (windows->image.height-1);
12772 windows->magnify.y=windows->image.y+y;
12773 if (windows->magnify.mapped == MagickFalse)
12774 (void) XMapRaised(display,windows->magnify.id);
12775 XMakeMagnifyImage(display,windows,exception);
12776 if (event->type == ButtonRelease)
12777 (void) XWithdrawWindow(display,windows->info.id,
12778 windows->info.screen);
12783 case ClientMessage:
12786 If client window delete message, exit.
12788 if (event->xclient.message_type != windows->wm_protocols)
12790 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12792 if (event->xclient.window == windows->magnify.id)
12794 (void) XWithdrawWindow(display,windows->magnify.id,
12795 windows->magnify.screen);
12800 case ConfigureNotify:
12802 if (event->xconfigure.window == windows->magnify.id)
12808 Magnify window has a new configuration.
12810 windows->magnify.width=(unsigned int) event->xconfigure.width;
12811 windows->magnify.height=(unsigned int) event->xconfigure.height;
12812 if (windows->magnify.mapped == MagickFalse)
12815 while ((int) magnify <= event->xconfigure.width)
12817 while ((int) magnify <= event->xconfigure.height)
12820 if (((int) magnify != event->xconfigure.width) ||
12821 ((int) magnify != event->xconfigure.height))
12826 window_changes.width=(int) magnify;
12827 window_changes.height=(int) magnify;
12828 (void) XReconfigureWMWindow(display,windows->magnify.id,
12829 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12833 XMakeMagnifyImage(display,windows,exception);
12840 if (event->xexpose.window == windows->image.id)
12842 XRefreshWindow(display,&windows->image,event);
12845 if (event->xexpose.window == windows->pan.id)
12846 if (event->xexpose.count == 0)
12848 XDrawPanRectangle(display,windows);
12851 if (event->xexpose.window == windows->magnify.id)
12852 if (event->xexpose.count == 0)
12854 XMakeMagnifyImage(display,windows,exception);
12862 command[MaxTextExtent];
12867 if (event->xkey.window != windows->magnify.id)
12870 Respond to a user key press.
12872 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12873 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12874 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12880 if (event->xmap.window == windows->magnify.id)
12882 windows->magnify.mapped=MagickTrue;
12883 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12886 if (event->xmap.window == windows->info.id)
12888 windows->info.mapped=MagickTrue;
12895 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12896 if (event->xmotion.window == windows->image.id)
12897 if (windows->magnify.mapped != MagickFalse)
12900 Update magnified image.
12902 x=event->xmotion.x;
12903 y=event->xmotion.y;
12907 if (x >= (int) windows->image.width)
12908 x=(int) (windows->image.width-1);
12909 windows->magnify.x=(int) windows->image.x+x;
12913 if (y >= (int) windows->image.height)
12914 y=(int) (windows->image.height-1);
12915 windows->magnify.y=windows->image.y+y;
12916 XMakeMagnifyImage(display,windows,exception);
12922 if (event->xunmap.window == windows->magnify.id)
12924 windows->magnify.mapped=MagickFalse;
12927 if (event->xunmap.window == windows->info.id)
12929 windows->info.mapped=MagickFalse;
12940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12944 + X S e t C r o p G e o m e t r y %
12948 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12950 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12951 % and translates it to a cropping geometry relative to the image.
12953 % The format of the XSetCropGeometry method is:
12955 % void XSetCropGeometry(Display *display,XWindows *windows,
12956 % RectangleInfo *crop_info,Image *image)
12958 % A description of each parameter follows:
12960 % o display: Specifies a connection to an X server; returned from
12963 % o windows: Specifies a pointer to a XWindows structure.
12965 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12966 % Image window to crop.
12968 % o image: the image.
12971 static void XSetCropGeometry(Display *display,XWindows *windows,
12972 RectangleInfo *crop_info,Image *image)
12975 text[MaxTextExtent];
12988 if (windows->info.mapped != MagickFalse)
12991 Display info on cropping rectangle.
12993 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12994 (double) crop_info->width,(double) crop_info->height,(double)
12995 crop_info->x,(double) crop_info->y);
12996 XInfoWidget(display,windows,text);
12999 Cropping geometry is relative to any previous crop geometry.
13003 width=(unsigned int) image->columns;
13004 height=(unsigned int) image->rows;
13005 if (windows->image.crop_geometry != (char *) NULL)
13006 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13008 windows->image.crop_geometry=AcquireString((char *) NULL);
13010 Define the crop geometry string from the cropping rectangle.
13012 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13013 if (crop_info->x > 0)
13014 x+=(int) (scale_factor*crop_info->x+0.5);
13015 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13018 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13019 if (crop_info->y > 0)
13020 y+=(int) (scale_factor*crop_info->y+0.5);
13021 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13024 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13025 "%ux%u%+d%+d",width,height,x,y);
13029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13033 + X T i l e I m a g e %
13037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13039 % XTileImage() loads or deletes a selected tile from a visual image directory.
13040 % The load or delete command is chosen from a menu.
13042 % The format of the XTileImage method is:
13044 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13045 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13047 % A description of each parameter follows:
13049 % o tile_image: XTileImage reads or deletes the tile image
13050 % and returns it. A null image is returned if an error occurs.
13052 % o display: Specifies a connection to an X server; returned from
13055 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13057 % o windows: Specifies a pointer to a XWindows structure.
13059 % o image: the image; returned from ReadImage.
13061 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13062 % the entire image is refreshed.
13064 % o exception: return any errors or warnings in this structure.
13067 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13068 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13081 static const ModeType
13092 command[MaxTextExtent],
13093 filename[MaxTextExtent];
13120 Tile image is relative to montage image configuration.
13124 width=(unsigned int) image->columns;
13125 height=(unsigned int) image->rows;
13126 if (windows->image.crop_geometry != (char *) NULL)
13127 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13128 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13129 event->xbutton.x+=windows->image.x;
13130 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13131 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13132 event->xbutton.y+=windows->image.y;
13133 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13135 Determine size and location of each tile in the visual image directory.
13137 width=(unsigned int) image->columns;
13138 height=(unsigned int) image->rows;
13141 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13142 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13143 (event->xbutton.x-x)/width;
13147 Button press is outside any tile.
13149 (void) XBell(display,0);
13150 return((Image *) NULL);
13153 Determine file name from the tile directory.
13155 p=image->directory;
13156 for (i=tile; (i != 0) && (*p != '\0'); )
13165 Button press is outside any tile.
13167 (void) XBell(display,0);
13168 return((Image *) NULL);
13171 Select a command from the pop-up menu.
13173 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13175 return((Image *) NULL);
13177 while ((*q != '\n') && (*q != '\0'))
13179 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13181 Perform command for the selected tile.
13183 XSetCursorState(display,windows,MagickTrue);
13184 XCheckRefreshWindows(display,windows);
13185 tile_image=NewImageList();
13186 switch (TileCommands[id])
13188 case TileLoadCommand:
13193 XCheckRefreshWindows(display,windows);
13194 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13196 (void) CopyMagickString(resource_info->image_info->filename,filename,
13198 tile_image=ReadImage(resource_info->image_info,exception);
13199 CatchException(exception);
13200 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13203 case TileNextCommand:
13206 Display next image.
13208 XClientMessage(display,windows->image.id,windows->im_protocols,
13209 windows->im_next_image,CurrentTime);
13212 case TileFormerCommand:
13215 Display former image.
13217 XClientMessage(display,windows->image.id,windows->im_protocols,
13218 windows->im_former_image,CurrentTime);
13221 case TileDeleteCommand:
13226 if (IsPathAccessible(filename) == MagickFalse)
13228 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13231 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13234 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
13235 if (status != MagickFalse)
13237 XNoticeWidget(display,windows,"Unable to delete image file:",
13242 case TileUpdateCommand:
13252 virtual_pixel[CompositePixelChannel];
13261 Ensure all the images exist.
13264 GetPixelInfo(image,&pixel);
13265 for (p=image->directory; *p != '\0'; p++)
13271 while ((*q != '\n') && (*q != '\0'))
13273 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13275 if (IsPathAccessible(filename) != MagickFalse)
13281 Overwrite tile with background color.
13283 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13284 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13285 image_view=AcquireCacheView(image);
13286 (void) GetOneCacheViewVirtualPixel(image_view,0,0,virtual_pixel,
13288 pixel.red=virtual_pixel[RedPixelChannel];
13289 pixel.green=virtual_pixel[GreenPixelChannel];
13290 pixel.blue=virtual_pixel[BluePixelChannel];
13291 pixel.alpha=virtual_pixel[AlphaPixelChannel];
13292 for (i=0; i < (int) height; i++)
13294 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13295 y_offset+i,width,1,exception);
13296 if (s == (Quantum *) NULL)
13298 for (j=0; j < (int) width; j++)
13300 SetPixelInfoPixel(image,&pixel,s);
13301 s+=GetPixelChannels(image);
13303 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13306 image_view=DestroyCacheView(image_view);
13309 windows->image.window_changes.width=(int) image->columns;
13310 windows->image.window_changes.height=(int) image->rows;
13311 XConfigureImageColormap(display,resource_info,windows,image,exception);
13312 (void) XConfigureImage(display,resource_info,windows,image,exception);
13318 XSetCursorState(display,windows,MagickFalse);
13319 return(tile_image);
13323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13327 + X T r a n s l a t e I m a g e %
13331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13333 % XTranslateImage() translates the image within an Image window by one pixel
13334 % as specified by the key symbol. If the image has a `montage string the
13335 % translation is respect to the width and height contained within the string.
13337 % The format of the XTranslateImage method is:
13339 % void XTranslateImage(Display *display,XWindows *windows,
13340 % Image *image,const KeySym key_symbol)
13342 % A description of each parameter follows:
13344 % o display: Specifies a connection to an X server; returned from
13347 % o windows: Specifies a pointer to a XWindows structure.
13349 % o image: the image.
13351 % o key_symbol: Specifies a KeySym which indicates which side of the image
13355 static void XTranslateImage(Display *display,XWindows *windows,
13356 Image *image,const KeySym key_symbol)
13359 text[MaxTextExtent];
13370 User specified a pan position offset.
13372 x_offset=windows->image.width;
13373 y_offset=windows->image.height;
13374 if (image->montage != (char *) NULL)
13375 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13376 switch ((int) key_symbol)
13381 windows->image.x=(int) windows->image.width/2;
13382 windows->image.y=(int) windows->image.height/2;
13388 windows->image.x-=x_offset;
13395 windows->image.y-=y_offset;
13401 windows->image.x+=x_offset;
13408 windows->image.y+=y_offset;
13415 Check boundary conditions.
13417 if (windows->image.x < 0)
13418 windows->image.x=0;
13420 if ((int) (windows->image.x+windows->image.width) >
13421 windows->image.ximage->width)
13422 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13423 if (windows->image.y < 0)
13424 windows->image.y=0;
13426 if ((int) (windows->image.y+windows->image.height) >
13427 windows->image.ximage->height)
13428 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13430 Refresh Image window.
13432 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13433 windows->image.width,windows->image.height,windows->image.x,
13435 XInfoWidget(display,windows,text);
13436 XCheckRefreshWindows(display,windows);
13437 XDrawPanRectangle(display,windows);
13438 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13439 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13447 + X T r i m I m a g e %
13451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13453 % XTrimImage() trims the edges from the Image window.
13455 % The format of the XTrimImage method is:
13457 % MagickBooleanType XTrimImage(Display *display,
13458 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13459 % ExceptionInfo *exception)
13461 % A description of each parameter follows:
13463 % o display: Specifies a connection to an X server; returned from
13466 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13468 % o windows: Specifies a pointer to a XWindows structure.
13470 % o image: the image.
13472 % o exception: return any errors or warnings in this structure.
13475 static MagickBooleanType XTrimImage(Display *display,
13476 XResourceInfo *resource_info,XWindows *windows,Image *image,
13477 ExceptionInfo *exception)
13491 Trim edges from image.
13493 XSetCursorState(display,windows,MagickTrue);
13494 XCheckRefreshWindows(display,windows);
13496 Crop the left edge.
13498 background=XGetPixel(windows->image.ximage,0,0);
13499 trim_info.width=(size_t) windows->image.ximage->width;
13500 for (x=0; x < windows->image.ximage->width; x++)
13502 for (y=0; y < windows->image.ximage->height; y++)
13504 pixel=XGetPixel(windows->image.ximage,x,y);
13505 if (pixel != background)
13508 if (y < windows->image.ximage->height)
13511 trim_info.x=(ssize_t) x;
13512 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13514 XSetCursorState(display,windows,MagickFalse);
13515 return(MagickFalse);
13518 Crop the right edge.
13520 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13521 for (x=windows->image.ximage->width-1; x != 0; x--)
13523 for (y=0; y < windows->image.ximage->height; y++)
13525 pixel=XGetPixel(windows->image.ximage,x,y);
13526 if (pixel != background)
13529 if (y < windows->image.ximage->height)
13532 trim_info.width=(size_t) (x-trim_info.x+1);
13536 background=XGetPixel(windows->image.ximage,0,0);
13537 trim_info.height=(size_t) windows->image.ximage->height;
13538 for (y=0; y < windows->image.ximage->height; y++)
13540 for (x=0; x < windows->image.ximage->width; x++)
13542 pixel=XGetPixel(windows->image.ximage,x,y);
13543 if (pixel != background)
13546 if (x < windows->image.ximage->width)
13549 trim_info.y=(ssize_t) y;
13551 Crop the bottom edge.
13553 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13554 for (y=windows->image.ximage->height-1; y != 0; y--)
13556 for (x=0; x < windows->image.ximage->width; x++)
13558 pixel=XGetPixel(windows->image.ximage,x,y);
13559 if (pixel != background)
13562 if (x < windows->image.ximage->width)
13565 trim_info.height=(size_t) y-trim_info.y+1;
13566 if (((unsigned int) trim_info.width != windows->image.width) ||
13567 ((unsigned int) trim_info.height != windows->image.height))
13570 Reconfigure Image window as defined by the trimming rectangle.
13572 XSetCropGeometry(display,windows,&trim_info,image);
13573 windows->image.window_changes.width=(int) trim_info.width;
13574 windows->image.window_changes.height=(int) trim_info.height;
13575 (void) XConfigureImage(display,resource_info,windows,image,exception);
13577 XSetCursorState(display,windows,MagickFalse);
13578 return(MagickTrue);
13582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13586 + X V i s u a l D i r e c t o r y I m a g e %
13590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13592 % XVisualDirectoryImage() creates a Visual Image Directory.
13594 % The format of the XVisualDirectoryImage method is:
13596 % Image *XVisualDirectoryImage(Display *display,
13597 % XResourceInfo *resource_info,XWindows *windows,
13598 % ExceptionInfo *exception)
13600 % A description of each parameter follows:
13602 % o display: Specifies a connection to an X server; returned from
13605 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13607 % o windows: Specifies a pointer to a XWindows structure.
13609 % o exception: return any errors or warnings in this structure.
13612 static Image *XVisualDirectoryImage(Display *display,
13613 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13615 #define TileImageTag "Scale/Image"
13616 #define XClientName "montage"
13649 filename[MaxTextExtent] = "\0",
13650 filenames[MaxTextExtent] = "*";
13653 background_resources;
13656 Request file name from user.
13658 XFileBrowserWidget(display,windows,"Directory",filenames);
13659 if (*filenames == '\0')
13660 return((Image *) NULL);
13662 Expand the filenames.
13664 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13665 if (filelist == (char **) NULL)
13667 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13669 return((Image *) NULL);
13672 filelist[0]=filenames;
13673 status=ExpandFilenames(&number_files,&filelist);
13674 if ((status == MagickFalse) || (number_files == 0))
13676 if (number_files == 0)
13677 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13679 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13681 return((Image *) NULL);
13684 Set image background resources.
13686 background_resources=(*resource_info);
13687 background_resources.window_id=AcquireString("");
13688 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13689 "0x%lx",windows->image.id);
13690 background_resources.backdrop=MagickTrue;
13692 Read each image and convert them to a tile.
13694 backdrop=(windows->visual_info->klass == TrueColor) ||
13695 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13696 read_info=CloneImageInfo(resource_info->image_info);
13697 (void) SetImageOption(read_info,"jpeg:size","120x120");
13698 (void) CloneString(&read_info->size,DefaultTileGeometry);
13699 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13701 images=NewImageList();
13702 XSetCursorState(display,windows,MagickTrue);
13703 XCheckRefreshWindows(display,windows);
13704 for (i=0; i < (int) number_files; i++)
13706 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13707 filelist[i]=DestroyString(filelist[i]);
13708 *read_info->magick='\0';
13709 next_image=ReadImage(read_info,exception);
13710 CatchException(exception);
13711 if (next_image != (Image *) NULL)
13713 (void) DeleteImageProperty(next_image,"label");
13714 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13715 read_info,next_image,DefaultTileLabel,exception),exception);
13716 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13718 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13719 geometry.height,exception);
13720 if (thumbnail_image != (Image *) NULL)
13722 next_image=DestroyImage(next_image);
13723 next_image=thumbnail_image;
13727 (void) XDisplayBackgroundImage(display,&background_resources,
13728 next_image,exception);
13729 XSetCursorState(display,windows,MagickTrue);
13731 AppendImageToList(&images,next_image);
13732 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13737 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13738 (MagickSizeType) number_files);
13739 if (proceed == MagickFalse)
13744 filelist=(char **) RelinquishMagickMemory(filelist);
13745 if (images == (Image *) NULL)
13747 read_info=DestroyImageInfo(read_info);
13748 XSetCursorState(display,windows,MagickFalse);
13749 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13750 return((Image *) NULL);
13753 Create the Visual Image Directory.
13755 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13756 montage_info->pointsize=10;
13757 if (resource_info->font != (char *) NULL)
13758 (void) CloneString(&montage_info->font,resource_info->font);
13759 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13760 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13761 images),exception);
13762 images=DestroyImageList(images);
13763 montage_info=DestroyMontageInfo(montage_info);
13764 read_info=DestroyImageInfo(read_info);
13765 XSetCursorState(display,windows,MagickFalse);
13766 if (montage_image == (Image *) NULL)
13767 return(montage_image);
13768 XClientMessage(display,windows->image.id,windows->im_protocols,
13769 windows->im_next_image,CurrentTime);
13770 return(montage_image);
13774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13778 % X D i s p l a y B a c k g r o u n d I m a g e %
13782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13784 % XDisplayBackgroundImage() displays an image in the background of a window.
13786 % The format of the XDisplayBackgroundImage method is:
13788 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13789 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13791 % A description of each parameter follows:
13793 % o display: Specifies a connection to an X server; returned from
13796 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13798 % o image: the image.
13800 % o exception: return any errors or warnings in this structure.
13803 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13804 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13807 geometry[MaxTextExtent],
13808 visual_type[MaxTextExtent];
13821 static XStandardColormap
13825 *visual_info = (XVisualInfo *) NULL;
13846 Determine target window.
13848 assert(image != (Image *) NULL);
13849 assert(image->signature == MagickSignature);
13850 if (image->debug != MagickFalse)
13851 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13852 resources=(*resource_info);
13853 window_info.id=(Window) NULL;
13854 root_window=XRootWindow(display,XDefaultScreen(display));
13855 if (LocaleCompare(resources.window_id,"root") == 0)
13856 window_info.id=root_window;
13859 if (isdigit((unsigned char) *resources.window_id) != 0)
13860 window_info.id=XWindowByID(display,root_window,
13861 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13862 if (window_info.id == (Window) NULL)
13863 window_info.id=XWindowByName(display,root_window,resources.window_id);
13865 if (window_info.id == (Window) NULL)
13867 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13868 resources.window_id);
13869 return(MagickFalse);
13872 Determine window visual id.
13874 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13875 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13876 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13877 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13879 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13880 XVisualIDFromVisual(window_attributes.visual));
13881 if (visual_info == (XVisualInfo *) NULL)
13884 Allocate standard colormap.
13886 map_info=XAllocStandardColormap();
13887 if (map_info == (XStandardColormap *) NULL)
13888 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13890 map_info->colormap=(Colormap) NULL;
13891 pixel.pixels=(unsigned long *) NULL;
13893 Initialize visual info.
13895 resources.map_type=(char *) NULL;
13896 resources.visual_type=visual_type;
13897 visual_info=XBestVisualInfo(display,map_info,&resources);
13898 if (visual_info == (XVisualInfo *) NULL)
13899 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13900 resources.visual_type);
13902 Initialize window info.
13904 window_info.ximage=(XImage *) NULL;
13905 window_info.matte_image=(XImage *) NULL;
13906 window_info.pixmap=(Pixmap) NULL;
13907 window_info.matte_pixmap=(Pixmap) NULL;
13910 Free previous root colors.
13912 if (window_info.id == root_window)
13913 (void) XDestroyWindowColors(display,root_window);
13915 Initialize Standard Colormap.
13917 resources.colormap=SharedColormap;
13918 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13921 Graphic context superclass.
13923 context_values.background=pixel.background_color.pixel;
13924 context_values.foreground=pixel.foreground_color.pixel;
13925 pixel.annotate_context=XCreateGC(display,window_info.id,
13926 (size_t) (GCBackground | GCForeground),&context_values);
13927 if (pixel.annotate_context == (GC) NULL)
13928 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13931 Initialize Image window attributes.
13933 window_info.name=AcquireString("\0");
13934 window_info.icon_name=AcquireString("\0");
13935 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13936 &resources,&window_info);
13938 Create the X image.
13940 window_info.width=(unsigned int) image->columns;
13941 window_info.height=(unsigned int) image->rows;
13942 if ((image->columns != window_info.width) ||
13943 (image->rows != window_info.height))
13944 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13946 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13947 window_attributes.width,window_attributes.height);
13948 geometry_info.width=window_info.width;
13949 geometry_info.height=window_info.height;
13950 geometry_info.x=(ssize_t) window_info.x;
13951 geometry_info.y=(ssize_t) window_info.y;
13952 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13953 &geometry_info.width,&geometry_info.height);
13954 window_info.width=(unsigned int) geometry_info.width;
13955 window_info.height=(unsigned int) geometry_info.height;
13956 window_info.x=(int) geometry_info.x;
13957 window_info.y=(int) geometry_info.y;
13958 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13959 window_info.height,exception);
13960 if (status == MagickFalse)
13961 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13965 if (image->debug != MagickFalse)
13967 (void) LogMagickEvent(X11Event,GetMagickModule(),
13968 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13969 (double) image->columns,(double) image->rows);
13970 if (image->colors != 0)
13971 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13973 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13976 Adjust image dimensions as specified by backdrop or geometry options.
13978 width=(int) window_info.width;
13979 height=(int) window_info.height;
13980 if (resources.backdrop != MagickFalse)
13983 Center image on window.
13985 window_info.x=(window_attributes.width/2)-
13986 (window_info.ximage->width/2);
13987 window_info.y=(window_attributes.height/2)-
13988 (window_info.ximage->height/2);
13989 width=window_attributes.width;
13990 height=window_attributes.height;
13992 if ((resources.image_geometry != (char *) NULL) &&
13993 (*resources.image_geometry != '\0'))
13996 default_geometry[MaxTextExtent];
14006 User specified geometry.
14008 size_hints=XAllocSizeHints();
14009 if (size_hints == (XSizeHints *) NULL)
14010 ThrowXWindowFatalException(ResourceLimitFatalError,
14011 "MemoryAllocationFailed",image->filename);
14012 size_hints->flags=0L;
14013 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
14015 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
14016 default_geometry,window_info.border_width,size_hints,&window_info.x,
14017 &window_info.y,&width,&height,&gravity);
14018 if (flags & (XValue | YValue))
14020 width=window_attributes.width;
14021 height=window_attributes.height;
14023 (void) XFree((void *) size_hints);
14026 Create the X pixmap.
14028 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14029 (unsigned int) height,window_info.depth);
14030 if (window_info.pixmap == (Pixmap) NULL)
14031 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14034 Display pixmap on the window.
14036 if (((unsigned int) width > window_info.width) ||
14037 ((unsigned int) height > window_info.height))
14038 (void) XFillRectangle(display,window_info.pixmap,
14039 window_info.annotate_context,0,0,(unsigned int) width,
14040 (unsigned int) height);
14041 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14042 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14043 window_info.width,(unsigned int) window_info.height);
14044 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14045 (void) XClearWindow(display,window_info.id);
14046 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14047 XDelay(display,delay == 0UL ? 10UL : delay);
14048 (void) XSync(display,MagickFalse);
14049 return(window_info.id == root_window ? MagickTrue : MagickFalse);
14053 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14057 + X D i s p l a y I m a g e %
14061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14063 % XDisplayImage() displays an image via X11. A new image is created and
14064 % returned if the user interactively transforms the displayed image.
14066 % The format of the XDisplayImage method is:
14068 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14069 % char **argv,int argc,Image **image,size_t *state,
14070 % ExceptionInfo *exception)
14072 % A description of each parameter follows:
14074 % o nexus: Method XDisplayImage returns an image when the
14075 % user chooses 'Open Image' from the command menu or picks a tile
14076 % from the image directory. Otherwise a null image is returned.
14078 % o display: Specifies a connection to an X server; returned from
14081 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14083 % o argv: Specifies the application's argument list.
14085 % o argc: Specifies the number of arguments.
14087 % o image: Specifies an address to an address of an Image structure;
14089 % o exception: return any errors or warnings in this structure.
14092 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14093 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14095 #define MagnifySize 256 /* must be a power of 2 */
14096 #define MagickMenus 10
14097 #define MagickTitle "Commands"
14124 "Visual Directory...",
14170 "Contrast Stretch...",
14171 "Sigmoidal Contrast...",
14205 "Charcoal Draw...",
14219 "Region of Interest...",
14222 *MiscellanyMenu[] =
14237 "Browse Documentation",
14264 **Menus[MagickMenus] =
14302 VisualDirectoryCommand,
14316 OriginalSizeCommand,
14323 TransformCommands[] =
14329 RotateRightCommand,
14336 EnhanceCommands[] =
14344 ContrastStretchCommand,
14345 SigmoidalContrastCommand,
14353 EffectsCommands[] =
14357 ReduceNoiseCommand,
14377 CharcoalDrawCommand
14379 ImageEditCommands[] =
14390 RegionofInterestCommand
14392 MiscellanyCommands[] =
14396 ShowPreviewCommand,
14397 ShowHistogramCommand,
14406 BrowseDocumentationCommand,
14409 ShortCutsCommands[] =
14421 VirtualCommands[] =
14430 *Commands[MagickMenus] =
14440 MiscellanyCommands,
14445 command[MaxTextExtent],
14447 geometry[MaxTextExtent],
14448 resource_name[MaxTextExtent];
14475 working_directory[MaxTextExtent];
14481 *magick_windows[MaxXWindows];
14483 static unsigned int
14543 assert(image != (Image **) NULL);
14544 assert((*image)->signature == MagickSignature);
14545 if ((*image)->debug != MagickFalse)
14546 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14547 display_image=(*image);
14548 warning_handler=(WarningHandler) NULL;
14549 windows=XSetWindows((XWindows *) ~0);
14550 if (windows != (XWindows *) NULL)
14555 status=chdir(working_directory);
14557 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14558 "UnableToOpenFile","%s",working_directory);
14559 warning_handler=resource_info->display_warnings ?
14560 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14561 warning_handler=resource_info->display_warnings ?
14562 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14567 Allocate windows structure.
14569 resource_info->colors=display_image->colors;
14570 windows=XSetWindows(XInitializeWindows(display,resource_info));
14571 if (windows == (XWindows *) NULL)
14572 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14573 (*image)->filename);
14575 Initialize window id's.
14578 magick_windows[number_windows++]=(&windows->icon);
14579 magick_windows[number_windows++]=(&windows->backdrop);
14580 magick_windows[number_windows++]=(&windows->image);
14581 magick_windows[number_windows++]=(&windows->info);
14582 magick_windows[number_windows++]=(&windows->command);
14583 magick_windows[number_windows++]=(&windows->widget);
14584 magick_windows[number_windows++]=(&windows->popup);
14585 magick_windows[number_windows++]=(&windows->magnify);
14586 magick_windows[number_windows++]=(&windows->pan);
14587 for (i=0; i < (int) number_windows; i++)
14588 magick_windows[i]->id=(Window) NULL;
14593 Initialize font info.
14595 if (windows->font_info != (XFontStruct *) NULL)
14596 (void) XFreeFont(display,windows->font_info);
14597 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14598 if (windows->font_info == (XFontStruct *) NULL)
14599 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14600 resource_info->font);
14602 Initialize Standard Colormap.
14604 map_info=windows->map_info;
14605 icon_map=windows->icon_map;
14606 visual_info=windows->visual_info;
14607 icon_visual=windows->icon_visual;
14608 pixel=windows->pixel_info;
14609 icon_pixel=windows->icon_pixel;
14610 font_info=windows->font_info;
14611 icon_resources=windows->icon_resources;
14612 class_hints=windows->class_hints;
14613 manager_hints=windows->manager_hints;
14614 root_window=XRootWindow(display,visual_info->screen);
14615 nexus=NewImageList();
14616 if (display_image->debug != MagickFalse)
14618 (void) LogMagickEvent(X11Event,GetMagickModule(),
14619 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14620 (double) display_image->scene,(double) display_image->columns,
14621 (double) display_image->rows);
14622 if (display_image->colors != 0)
14623 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14624 display_image->colors);
14625 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14626 display_image->magick);
14628 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14629 map_info,pixel,exception);
14630 display_image->taint=MagickFalse;
14632 Initialize graphic context.
14634 windows->context.id=(Window) NULL;
14635 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14636 resource_info,&windows->context);
14637 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14638 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14639 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14640 manager_hints->flags=InputHint | StateHint;
14641 manager_hints->input=MagickFalse;
14642 manager_hints->initial_state=WithdrawnState;
14643 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14644 &windows->context);
14645 if (display_image->debug != MagickFalse)
14646 (void) LogMagickEvent(X11Event,GetMagickModule(),
14647 "Window id: 0x%lx (context)",windows->context.id);
14648 context_values.background=pixel->background_color.pixel;
14649 context_values.font=font_info->fid;
14650 context_values.foreground=pixel->foreground_color.pixel;
14651 context_values.graphics_exposures=MagickFalse;
14652 context_mask=(MagickStatusType)
14653 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14654 if (pixel->annotate_context != (GC) NULL)
14655 (void) XFreeGC(display,pixel->annotate_context);
14656 pixel->annotate_context=XCreateGC(display,windows->context.id,
14657 context_mask,&context_values);
14658 if (pixel->annotate_context == (GC) NULL)
14659 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14660 display_image->filename);
14661 context_values.background=pixel->depth_color.pixel;
14662 if (pixel->widget_context != (GC) NULL)
14663 (void) XFreeGC(display,pixel->widget_context);
14664 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14666 if (pixel->widget_context == (GC) NULL)
14667 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14668 display_image->filename);
14669 context_values.background=pixel->foreground_color.pixel;
14670 context_values.foreground=pixel->background_color.pixel;
14671 context_values.plane_mask=context_values.background ^
14672 context_values.foreground;
14673 if (pixel->highlight_context != (GC) NULL)
14674 (void) XFreeGC(display,pixel->highlight_context);
14675 pixel->highlight_context=XCreateGC(display,windows->context.id,
14676 (size_t) (context_mask | GCPlaneMask),&context_values);
14677 if (pixel->highlight_context == (GC) NULL)
14678 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14679 display_image->filename);
14680 (void) XDestroyWindow(display,windows->context.id);
14682 Initialize icon window.
14684 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14685 icon_resources,&windows->icon);
14686 windows->icon.geometry=resource_info->icon_geometry;
14687 XBestIconSize(display,&windows->icon,display_image);
14688 windows->icon.attributes.colormap=XDefaultColormap(display,
14689 icon_visual->screen);
14690 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14691 manager_hints->flags=InputHint | StateHint;
14692 manager_hints->input=MagickFalse;
14693 manager_hints->initial_state=IconicState;
14694 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14696 if (display_image->debug != MagickFalse)
14697 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14700 Initialize graphic context for icon window.
14702 if (icon_pixel->annotate_context != (GC) NULL)
14703 (void) XFreeGC(display,icon_pixel->annotate_context);
14704 context_values.background=icon_pixel->background_color.pixel;
14705 context_values.foreground=icon_pixel->foreground_color.pixel;
14706 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14707 (size_t) (GCBackground | GCForeground),&context_values);
14708 if (icon_pixel->annotate_context == (GC) NULL)
14709 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14710 display_image->filename);
14711 windows->icon.annotate_context=icon_pixel->annotate_context;
14713 Initialize Image window.
14715 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14717 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14718 if (resource_info->use_shared_memory == MagickFalse)
14719 windows->image.shared_memory=MagickFalse;
14720 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14725 title=InterpretImageProperties(resource_info->image_info,display_image,
14726 resource_info->title,exception);
14727 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14728 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14729 title=DestroyString(title);
14734 filename[MaxTextExtent];
14737 Window name is the base of the filename.
14739 GetPathComponent(display_image->magick_filename,TailPath,filename);
14740 if (display_image->scene == 0)
14741 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14742 "%s: %s",MagickPackageName,filename);
14744 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14745 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14746 (double) display_image->scene,(double) GetImageListLength(
14748 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14750 if (resource_info->immutable)
14751 windows->image.immutable=MagickTrue;
14752 windows->image.use_pixmap=resource_info->use_pixmap;
14753 windows->image.geometry=resource_info->image_geometry;
14754 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14755 XDisplayWidth(display,visual_info->screen),
14756 XDisplayHeight(display,visual_info->screen));
14757 geometry_info.width=display_image->columns;
14758 geometry_info.height=display_image->rows;
14761 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14762 &geometry_info.width,&geometry_info.height);
14763 windows->image.width=(unsigned int) geometry_info.width;
14764 windows->image.height=(unsigned int) geometry_info.height;
14765 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14766 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14767 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14768 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14769 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14770 resource_info,&windows->backdrop);
14771 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14774 Initialize backdrop window.
14776 windows->backdrop.x=0;
14777 windows->backdrop.y=0;
14778 (void) CloneString(&windows->backdrop.name,"Backdrop");
14779 windows->backdrop.flags=(size_t) (USSize | USPosition);
14780 windows->backdrop.width=(unsigned int)
14781 XDisplayWidth(display,visual_info->screen);
14782 windows->backdrop.height=(unsigned int)
14783 XDisplayHeight(display,visual_info->screen);
14784 windows->backdrop.border_width=0;
14785 windows->backdrop.immutable=MagickTrue;
14786 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14788 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14789 StructureNotifyMask;
14790 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14791 manager_hints->icon_window=windows->icon.id;
14792 manager_hints->input=MagickTrue;
14793 manager_hints->initial_state=resource_info->iconic ? IconicState :
14795 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14796 &windows->backdrop);
14797 if (display_image->debug != MagickFalse)
14798 (void) LogMagickEvent(X11Event,GetMagickModule(),
14799 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14800 (void) XMapWindow(display,windows->backdrop.id);
14801 (void) XClearWindow(display,windows->backdrop.id);
14802 if (windows->image.id != (Window) NULL)
14804 (void) XDestroyWindow(display,windows->image.id);
14805 windows->image.id=(Window) NULL;
14808 Position image in the center the backdrop.
14810 windows->image.flags|=USPosition;
14811 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14812 (windows->image.width/2);
14813 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14814 (windows->image.height/2);
14816 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14817 manager_hints->icon_window=windows->icon.id;
14818 manager_hints->input=MagickTrue;
14819 manager_hints->initial_state=resource_info->iconic ? IconicState :
14821 if (windows->group_leader.id != (Window) NULL)
14826 manager_hints->flags|=WindowGroupHint;
14827 manager_hints->window_group=windows->group_leader.id;
14828 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14829 if (display_image->debug != MagickFalse)
14830 (void) LogMagickEvent(X11Event,GetMagickModule(),
14831 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14833 XMakeWindow(display,
14834 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14835 argv,argc,class_hints,manager_hints,&windows->image);
14836 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14837 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14838 if (windows->group_leader.id != (Window) NULL)
14839 (void) XSetTransientForHint(display,windows->image.id,
14840 windows->group_leader.id);
14841 if (display_image->debug != MagickFalse)
14842 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14843 windows->image.id);
14845 Initialize Info widget.
14847 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14849 (void) CloneString(&windows->info.name,"Info");
14850 (void) CloneString(&windows->info.icon_name,"Info");
14851 windows->info.border_width=1;
14854 windows->info.flags|=PPosition;
14855 windows->info.attributes.win_gravity=UnmapGravity;
14856 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14857 StructureNotifyMask;
14858 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14859 manager_hints->input=MagickFalse;
14860 manager_hints->initial_state=NormalState;
14861 manager_hints->window_group=windows->image.id;
14862 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14864 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14865 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14866 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14867 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14868 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14869 if (windows->image.mapped != MagickFalse)
14870 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14871 if (display_image->debug != MagickFalse)
14872 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14875 Initialize Command widget.
14877 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14878 resource_info,&windows->command);
14879 windows->command.data=MagickMenus;
14880 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14881 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14882 resource_info->client_name);
14883 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14884 resource_name,"geometry",(char *) NULL);
14885 (void) CloneString(&windows->command.name,MagickTitle);
14886 windows->command.border_width=0;
14887 windows->command.flags|=PPosition;
14888 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14889 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14890 OwnerGrabButtonMask | StructureNotifyMask;
14891 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14892 manager_hints->input=MagickTrue;
14893 manager_hints->initial_state=NormalState;
14894 manager_hints->window_group=windows->image.id;
14895 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14896 &windows->command);
14897 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14898 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14900 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14901 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14902 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14903 if (windows->command.mapped != MagickFalse)
14904 (void) XMapRaised(display,windows->command.id);
14905 if (display_image->debug != MagickFalse)
14906 (void) LogMagickEvent(X11Event,GetMagickModule(),
14907 "Window id: 0x%lx (command)",windows->command.id);
14909 Initialize Widget window.
14911 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14912 resource_info,&windows->widget);
14913 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14914 resource_info->client_name);
14915 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14916 resource_name,"geometry",(char *) NULL);
14917 windows->widget.border_width=0;
14918 windows->widget.flags|=PPosition;
14919 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14920 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14921 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14922 StructureNotifyMask;
14923 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14924 manager_hints->input=MagickTrue;
14925 manager_hints->initial_state=NormalState;
14926 manager_hints->window_group=windows->image.id;
14927 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14929 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14930 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14931 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14932 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14933 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14934 if (display_image->debug != MagickFalse)
14935 (void) LogMagickEvent(X11Event,GetMagickModule(),
14936 "Window id: 0x%lx (widget)",windows->widget.id);
14938 Initialize popup window.
14940 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14941 resource_info,&windows->popup);
14942 windows->popup.border_width=0;
14943 windows->popup.flags|=PPosition;
14944 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14945 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14946 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14947 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14948 manager_hints->input=MagickTrue;
14949 manager_hints->initial_state=NormalState;
14950 manager_hints->window_group=windows->image.id;
14951 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14953 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14954 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14955 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14956 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14957 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14958 if (display_image->debug != MagickFalse)
14959 (void) LogMagickEvent(X11Event,GetMagickModule(),
14960 "Window id: 0x%lx (pop up)",windows->popup.id);
14962 Initialize Magnify window and cursor.
14964 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14965 resource_info,&windows->magnify);
14966 if (resource_info->use_shared_memory == MagickFalse)
14967 windows->magnify.shared_memory=MagickFalse;
14968 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14969 resource_info->client_name);
14970 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14971 resource_name,"geometry",(char *) NULL);
14972 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14973 resource_info->magnify);
14974 if (windows->magnify.cursor != (Cursor) NULL)
14975 (void) XFreeCursor(display,windows->magnify.cursor);
14976 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14977 map_info->colormap,resource_info->background_color,
14978 resource_info->foreground_color);
14979 if (windows->magnify.cursor == (Cursor) NULL)
14980 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14981 display_image->filename);
14982 windows->magnify.width=MagnifySize;
14983 windows->magnify.height=MagnifySize;
14984 windows->magnify.flags|=PPosition;
14985 windows->magnify.min_width=MagnifySize;
14986 windows->magnify.min_height=MagnifySize;
14987 windows->magnify.width_inc=MagnifySize;
14988 windows->magnify.height_inc=MagnifySize;
14989 windows->magnify.data=resource_info->magnify;
14990 windows->magnify.attributes.cursor=windows->magnify.cursor;
14991 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14992 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14993 StructureNotifyMask;
14994 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14995 manager_hints->input=MagickTrue;
14996 manager_hints->initial_state=NormalState;
14997 manager_hints->window_group=windows->image.id;
14998 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14999 &windows->magnify);
15000 if (display_image->debug != MagickFalse)
15001 (void) LogMagickEvent(X11Event,GetMagickModule(),
15002 "Window id: 0x%lx (magnify)",windows->magnify.id);
15003 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
15005 Initialize panning window.
15007 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
15008 resource_info,&windows->pan);
15009 (void) CloneString(&windows->pan.name,"Pan Icon");
15010 windows->pan.width=windows->icon.width;
15011 windows->pan.height=windows->icon.height;
15012 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
15013 resource_info->client_name);
15014 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
15015 resource_name,"geometry",(char *) NULL);
15016 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
15017 &windows->pan.width,&windows->pan.height);
15018 windows->pan.flags|=PPosition;
15019 windows->pan.immutable=MagickTrue;
15020 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15021 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15022 StructureNotifyMask;
15023 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15024 manager_hints->input=MagickFalse;
15025 manager_hints->initial_state=NormalState;
15026 manager_hints->window_group=windows->image.id;
15027 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15029 if (display_image->debug != MagickFalse)
15030 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15032 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15033 if (windows->info.mapped != MagickFalse)
15034 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15035 if ((windows->image.mapped == MagickFalse) ||
15036 (windows->backdrop.id != (Window) NULL))
15037 (void) XMapWindow(display,windows->image.id);
15039 Set our progress monitor and warning handlers.
15041 if (warning_handler == (WarningHandler) NULL)
15043 warning_handler=resource_info->display_warnings ?
15044 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15045 warning_handler=resource_info->display_warnings ?
15046 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15049 Initialize Image and Magnify X images.
15051 windows->image.x=0;
15052 windows->image.y=0;
15053 windows->magnify.shape=MagickFalse;
15054 width=(unsigned int) display_image->columns;
15055 height=(unsigned int) display_image->rows;
15056 if ((display_image->columns != width) || (display_image->rows != height))
15057 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15058 display_image->filename);
15059 status=XMakeImage(display,resource_info,&windows->image,display_image,
15060 width,height,exception);
15061 if (status == MagickFalse)
15062 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15063 display_image->filename);
15064 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15065 windows->magnify.width,windows->magnify.height,exception);
15066 if (status == MagickFalse)
15067 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15068 display_image->filename);
15069 if (windows->magnify.mapped != MagickFalse)
15070 (void) XMapRaised(display,windows->magnify.id);
15071 if (windows->pan.mapped != MagickFalse)
15072 (void) XMapRaised(display,windows->pan.id);
15073 windows->image.window_changes.width=(int) display_image->columns;
15074 windows->image.window_changes.height=(int) display_image->rows;
15075 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15076 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15077 (void) XSync(display,MagickFalse);
15081 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15082 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15084 if (resource_info->update != MagickFalse)
15090 Determine when file data was last modified.
15092 status=GetPathAttributes(display_image->filename,&attributes);
15093 if (status != MagickFalse)
15094 update_time=attributes.st_mtime;
15096 *state&=(~FormerImageState);
15097 *state&=(~MontageImageState);
15098 *state&=(~NextImageState);
15102 Handle a window event.
15104 if (windows->image.mapped != MagickFalse)
15105 if ((display_image->delay != 0) || (resource_info->update != 0))
15107 if (timer < time((time_t *) NULL))
15109 if (resource_info->update == MagickFalse)
15110 *state|=NextImageState | ExitState;
15117 Determine if image file was modified.
15119 status=GetPathAttributes(display_image->filename,&attributes);
15120 if (status != MagickFalse)
15121 if (update_time != attributes.st_mtime)
15126 (void) FormatLocaleString(
15127 resource_info->image_info->filename,MaxTextExtent,
15128 "%s:%s",display_image->magick,
15129 display_image->filename);
15130 nexus=ReadImage(resource_info->image_info,exception);
15131 if (nexus != (Image *) NULL)
15133 nexus=DestroyImage(nexus);
15134 *state|=NextImageState | ExitState;
15137 delay=display_image->delay/MagickMax(
15138 display_image->ticks_per_second,1L);
15139 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15142 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15145 Do not block if delay > 0.
15147 XDelay(display,SuspendTime << 2);
15151 timestamp=time((time_t *) NULL);
15152 (void) XNextEvent(display,&event);
15153 if (windows->image.stasis == MagickFalse)
15154 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15155 MagickTrue : MagickFalse;
15156 if (windows->magnify.stasis == MagickFalse)
15157 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15158 MagickTrue : MagickFalse;
15159 if (event.xany.window == windows->command.id)
15162 Select a command from the Command widget.
15164 id=XCommandWidget(display,windows,CommandMenu,&event);
15167 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15168 command_type=CommandMenus[id];
15169 if (id < MagickMenus)
15172 Select a command from a pop-up menu.
15174 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15178 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15179 command_type=Commands[id][entry];
15181 if (command_type != NullCommand)
15182 nexus=XMagickCommand(display,resource_info,windows,command_type,
15183 &display_image,exception);
15186 switch (event.type)
15190 if (display_image->debug != MagickFalse)
15191 (void) LogMagickEvent(X11Event,GetMagickModule(),
15192 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15193 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15194 if ((event.xbutton.button == Button3) &&
15195 (event.xbutton.state & Mod1Mask))
15198 Convert Alt-Button3 to Button2.
15200 event.xbutton.button=Button2;
15201 event.xbutton.state&=(~Mod1Mask);
15203 if (event.xbutton.window == windows->backdrop.id)
15205 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15206 event.xbutton.time);
15209 if (event.xbutton.window == windows->image.id)
15211 switch (event.xbutton.button)
15215 if (resource_info->immutable)
15218 Select a command from the Virtual menu.
15220 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15223 nexus=XMagickCommand(display,resource_info,windows,
15224 VirtualCommands[entry],&display_image,exception);
15228 Map/unmap Command widget.
15230 if (windows->command.mapped != MagickFalse)
15231 (void) XWithdrawWindow(display,windows->command.id,
15232 windows->command.screen);
15235 (void) XCommandWidget(display,windows,CommandMenu,
15237 (void) XMapRaised(display,windows->command.id);
15244 User pressed the image magnify button.
15246 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15247 &display_image,exception);
15248 XMagnifyImage(display,windows,&event,exception);
15253 if (resource_info->immutable)
15256 Select a command from the Virtual menu.
15258 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15261 nexus=XMagickCommand(display,resource_info,windows,
15262 VirtualCommands[entry],&display_image,exception);
15265 if (display_image->montage != (char *) NULL)
15268 Open or delete a tile from a visual image directory.
15270 nexus=XTileImage(display,resource_info,windows,
15271 display_image,&event,exception);
15272 if (nexus != (Image *) NULL)
15273 *state|=MontageImageState | NextImageState | ExitState;
15274 vid_info.x=(short int) windows->image.x;
15275 vid_info.y=(short int) windows->image.y;
15279 Select a command from the Short Cuts menu.
15281 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15284 nexus=XMagickCommand(display,resource_info,windows,
15285 ShortCutsCommands[entry],&display_image,exception);
15293 XTranslateImage(display,windows,*image,XK_Up);
15301 XTranslateImage(display,windows,*image,XK_Down);
15309 if (event.xbutton.window == windows->magnify.id)
15329 MagnifyCommands[] =
15342 Select a magnify factor from the pop-up menu.
15344 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15346 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15350 if (event.xbutton.window == windows->pan.id)
15352 switch (event.xbutton.button)
15359 XTranslateImage(display,windows,*image,XK_Up);
15367 XTranslateImage(display,windows,*image,XK_Down);
15372 XPanImage(display,windows,&event,exception);
15378 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15380 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15383 case ButtonRelease:
15385 if (display_image->debug != MagickFalse)
15386 (void) LogMagickEvent(X11Event,GetMagickModule(),
15387 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15388 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15391 case ClientMessage:
15393 if (display_image->debug != MagickFalse)
15394 (void) LogMagickEvent(X11Event,GetMagickModule(),
15395 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15396 event.xclient.message_type,event.xclient.format,(unsigned long)
15397 event.xclient.data.l[0]);
15398 if (event.xclient.message_type == windows->im_protocols)
15400 if (*event.xclient.data.l == (long) windows->im_update_widget)
15402 (void) CloneString(&windows->command.name,MagickTitle);
15403 windows->command.data=MagickMenus;
15404 (void) XCommandWidget(display,windows,CommandMenu,
15408 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15411 Update graphic context and window colormap.
15413 for (i=0; i < (int) number_windows; i++)
15415 if (magick_windows[i]->id == windows->icon.id)
15417 context_values.background=pixel->background_color.pixel;
15418 context_values.foreground=pixel->foreground_color.pixel;
15419 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15420 context_mask,&context_values);
15421 (void) XChangeGC(display,magick_windows[i]->widget_context,
15422 context_mask,&context_values);
15423 context_values.background=pixel->foreground_color.pixel;
15424 context_values.foreground=pixel->background_color.pixel;
15425 context_values.plane_mask=context_values.background ^
15426 context_values.foreground;
15427 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15428 (size_t) (context_mask | GCPlaneMask),
15430 magick_windows[i]->attributes.background_pixel=
15431 pixel->background_color.pixel;
15432 magick_windows[i]->attributes.border_pixel=
15433 pixel->border_color.pixel;
15434 magick_windows[i]->attributes.colormap=map_info->colormap;
15435 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15436 (unsigned long) magick_windows[i]->mask,
15437 &magick_windows[i]->attributes);
15439 if (windows->pan.mapped != MagickFalse)
15441 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15442 windows->pan.pixmap);
15443 (void) XClearWindow(display,windows->pan.id);
15444 XDrawPanRectangle(display,windows);
15446 if (windows->backdrop.id != (Window) NULL)
15447 (void) XInstallColormap(display,map_info->colormap);
15450 if (*event.xclient.data.l == (long) windows->im_former_image)
15452 *state|=FormerImageState | ExitState;
15455 if (*event.xclient.data.l == (long) windows->im_next_image)
15457 *state|=NextImageState | ExitState;
15460 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15462 *state|=RetainColorsState;
15465 if (*event.xclient.data.l == (long) windows->im_exit)
15472 if (event.xclient.message_type == windows->dnd_protocols)
15490 Display image named by the Drag-and-Drop selection.
15492 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15494 selection=XInternAtom(display,"DndSelection",MagickFalse);
15495 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15496 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15497 &length,&after,&data);
15498 if ((status != Success) || (length == 0))
15500 if (*event.xclient.data.l == 2)
15505 (void) CopyMagickString(resource_info->image_info->filename,
15506 (char *) data,MaxTextExtent);
15513 if (strncmp((char *) data, "file:", 5) != 0)
15515 (void) XFree((void *) data);
15518 (void) CopyMagickString(resource_info->image_info->filename,
15519 ((char *) data)+5,MaxTextExtent);
15521 nexus=ReadImage(resource_info->image_info,exception);
15522 CatchException(exception);
15523 if (nexus != (Image *) NULL)
15524 *state|=NextImageState | ExitState;
15525 (void) XFree((void *) data);
15529 If client window delete message, exit.
15531 if (event.xclient.message_type != windows->wm_protocols)
15533 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15535 (void) XWithdrawWindow(display,event.xclient.window,
15536 visual_info->screen);
15537 if (event.xclient.window == windows->image.id)
15542 if (event.xclient.window == windows->pan.id)
15545 Restore original image size when pan window is deleted.
15547 windows->image.window_changes.width=windows->image.ximage->width;
15548 windows->image.window_changes.height=windows->image.ximage->height;
15549 (void) XConfigureImage(display,resource_info,windows,
15550 display_image,exception);
15554 case ConfigureNotify:
15556 if (display_image->debug != MagickFalse)
15557 (void) LogMagickEvent(X11Event,GetMagickModule(),
15558 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15559 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15560 event.xconfigure.y,event.xconfigure.send_event);
15561 if (event.xconfigure.window == windows->image.id)
15564 Image window has a new configuration.
15566 if (event.xconfigure.send_event != 0)
15572 Position the transient windows relative of the Image window.
15574 if (windows->command.geometry == (char *) NULL)
15575 if (windows->command.mapped == MagickFalse)
15577 windows->command.x=event.xconfigure.x-
15578 windows->command.width-25;
15579 windows->command.y=event.xconfigure.y;
15580 XConstrainWindowPosition(display,&windows->command);
15581 window_changes.x=windows->command.x;
15582 window_changes.y=windows->command.y;
15583 (void) XReconfigureWMWindow(display,windows->command.id,
15584 windows->command.screen,(unsigned int) (CWX | CWY),
15587 if (windows->widget.geometry == (char *) NULL)
15588 if (windows->widget.mapped == MagickFalse)
15590 windows->widget.x=event.xconfigure.x+
15591 event.xconfigure.width/10;
15592 windows->widget.y=event.xconfigure.y+
15593 event.xconfigure.height/10;
15594 XConstrainWindowPosition(display,&windows->widget);
15595 window_changes.x=windows->widget.x;
15596 window_changes.y=windows->widget.y;
15597 (void) XReconfigureWMWindow(display,windows->widget.id,
15598 windows->widget.screen,(unsigned int) (CWX | CWY),
15601 if (windows->magnify.geometry == (char *) NULL)
15602 if (windows->magnify.mapped == MagickFalse)
15604 windows->magnify.x=event.xconfigure.x+
15605 event.xconfigure.width+25;
15606 windows->magnify.y=event.xconfigure.y;
15607 XConstrainWindowPosition(display,&windows->magnify);
15608 window_changes.x=windows->magnify.x;
15609 window_changes.y=windows->magnify.y;
15610 (void) XReconfigureWMWindow(display,windows->magnify.id,
15611 windows->magnify.screen,(unsigned int) (CWX | CWY),
15614 if (windows->pan.geometry == (char *) NULL)
15615 if (windows->pan.mapped == MagickFalse)
15617 windows->pan.x=event.xconfigure.x+
15618 event.xconfigure.width+25;
15619 windows->pan.y=event.xconfigure.y+
15620 windows->magnify.height+50;
15621 XConstrainWindowPosition(display,&windows->pan);
15622 window_changes.x=windows->pan.x;
15623 window_changes.y=windows->pan.y;
15624 (void) XReconfigureWMWindow(display,windows->pan.id,
15625 windows->pan.screen,(unsigned int) (CWX | CWY),
15629 if ((event.xconfigure.width == (int) windows->image.width) &&
15630 (event.xconfigure.height == (int) windows->image.height))
15632 windows->image.width=(unsigned int) event.xconfigure.width;
15633 windows->image.height=(unsigned int) event.xconfigure.height;
15634 windows->image.x=0;
15635 windows->image.y=0;
15636 if (display_image->montage != (char *) NULL)
15638 windows->image.x=vid_info.x;
15639 windows->image.y=vid_info.y;
15641 if ((windows->image.mapped != MagickFalse) &&
15642 (windows->image.stasis != MagickFalse))
15645 Update image window configuration.
15647 windows->image.window_changes.width=event.xconfigure.width;
15648 windows->image.window_changes.height=event.xconfigure.height;
15649 (void) XConfigureImage(display,resource_info,windows,
15650 display_image,exception);
15653 Update pan window configuration.
15655 if ((event.xconfigure.width < windows->image.ximage->width) ||
15656 (event.xconfigure.height < windows->image.ximage->height))
15658 (void) XMapRaised(display,windows->pan.id);
15659 XDrawPanRectangle(display,windows);
15662 if (windows->pan.mapped != MagickFalse)
15663 (void) XWithdrawWindow(display,windows->pan.id,
15664 windows->pan.screen);
15667 if (event.xconfigure.window == windows->magnify.id)
15673 Magnify window has a new configuration.
15675 windows->magnify.width=(unsigned int) event.xconfigure.width;
15676 windows->magnify.height=(unsigned int) event.xconfigure.height;
15677 if (windows->magnify.mapped == MagickFalse)
15680 while ((int) magnify <= event.xconfigure.width)
15682 while ((int) magnify <= event.xconfigure.height)
15685 if (((int) magnify != event.xconfigure.width) ||
15686 ((int) magnify != event.xconfigure.height))
15688 window_changes.width=(int) magnify;
15689 window_changes.height=(int) magnify;
15690 (void) XReconfigureWMWindow(display,windows->magnify.id,
15691 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15695 if ((windows->magnify.mapped != MagickFalse) &&
15696 (windows->magnify.stasis != MagickFalse))
15698 status=XMakeImage(display,resource_info,&windows->magnify,
15699 display_image,windows->magnify.width,windows->magnify.height,
15701 XMakeMagnifyImage(display,windows,exception);
15705 if ((windows->magnify.mapped != MagickFalse) &&
15706 (event.xconfigure.window == windows->pan.id))
15709 Pan icon window has a new configuration.
15711 if (event.xconfigure.send_event != 0)
15713 windows->pan.x=event.xconfigure.x;
15714 windows->pan.y=event.xconfigure.y;
15716 windows->pan.width=(unsigned int) event.xconfigure.width;
15717 windows->pan.height=(unsigned int) event.xconfigure.height;
15720 if (event.xconfigure.window == windows->icon.id)
15723 Icon window has a new configuration.
15725 windows->icon.width=(unsigned int) event.xconfigure.width;
15726 windows->icon.height=(unsigned int) event.xconfigure.height;
15731 case DestroyNotify:
15734 Group leader has exited.
15736 if (display_image->debug != MagickFalse)
15737 (void) LogMagickEvent(X11Event,GetMagickModule(),
15738 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15739 if (event.xdestroywindow.window == windows->group_leader.id)
15749 Selectively install colormap.
15751 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15752 if (event.xcrossing.mode != NotifyUngrab)
15753 XInstallColormap(display,map_info->colormap);
15758 if (display_image->debug != MagickFalse)
15759 (void) LogMagickEvent(X11Event,GetMagickModule(),
15760 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15761 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15764 Refresh windows that are now exposed.
15766 if ((event.xexpose.window == windows->image.id) &&
15767 (windows->image.mapped != MagickFalse))
15769 XRefreshWindow(display,&windows->image,&event);
15770 delay=display_image->delay/MagickMax(
15771 display_image->ticks_per_second,1L);
15772 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15775 if ((event.xexpose.window == windows->magnify.id) &&
15776 (windows->magnify.mapped != MagickFalse))
15778 XMakeMagnifyImage(display,windows,exception);
15781 if (event.xexpose.window == windows->pan.id)
15783 XDrawPanRectangle(display,windows);
15786 if (event.xexpose.window == windows->icon.id)
15788 XRefreshWindow(display,&windows->icon,&event);
15799 Respond to a user key press.
15801 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15802 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15803 *(command+length)='\0';
15804 if (display_image->debug != MagickFalse)
15805 (void) LogMagickEvent(X11Event,GetMagickModule(),
15806 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15807 key_symbol,command);
15808 if (event.xkey.window == windows->image.id)
15810 command_type=XImageWindowCommand(display,resource_info,windows,
15811 event.xkey.state,key_symbol,&display_image,exception);
15812 if (command_type != NullCommand)
15813 nexus=XMagickCommand(display,resource_info,windows,command_type,
15814 &display_image,exception);
15816 if (event.xkey.window == windows->magnify.id)
15817 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15819 if (event.xkey.window == windows->pan.id)
15821 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15822 (void) XWithdrawWindow(display,windows->pan.id,
15823 windows->pan.screen);
15825 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15826 XTextViewWidget(display,resource_info,windows,MagickFalse,
15827 "Help Viewer - Image Pan",ImagePanHelp);
15829 XTranslateImage(display,windows,*image,key_symbol);
15831 delay=display_image->delay/MagickMax(
15832 display_image->ticks_per_second,1L);
15833 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15839 Respond to a user key release.
15841 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15842 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15843 if (display_image->debug != MagickFalse)
15844 (void) LogMagickEvent(X11Event,GetMagickModule(),
15845 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15851 Selectively uninstall colormap.
15853 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15854 if (event.xcrossing.mode != NotifyUngrab)
15855 XUninstallColormap(display,map_info->colormap);
15860 if (display_image->debug != MagickFalse)
15861 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15862 event.xmap.window);
15863 if (event.xmap.window == windows->backdrop.id)
15865 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15867 windows->backdrop.mapped=MagickTrue;
15870 if (event.xmap.window == windows->image.id)
15872 if (windows->backdrop.id != (Window) NULL)
15873 (void) XInstallColormap(display,map_info->colormap);
15874 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15876 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15877 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15879 if (((int) windows->image.width < windows->image.ximage->width) ||
15880 ((int) windows->image.height < windows->image.ximage->height))
15881 (void) XMapRaised(display,windows->pan.id);
15882 windows->image.mapped=MagickTrue;
15885 if (event.xmap.window == windows->magnify.id)
15887 XMakeMagnifyImage(display,windows,exception);
15888 windows->magnify.mapped=MagickTrue;
15889 (void) XWithdrawWindow(display,windows->info.id,
15890 windows->info.screen);
15893 if (event.xmap.window == windows->pan.id)
15895 XMakePanImage(display,resource_info,windows,display_image,
15897 windows->pan.mapped=MagickTrue;
15900 if (event.xmap.window == windows->info.id)
15902 windows->info.mapped=MagickTrue;
15905 if (event.xmap.window == windows->icon.id)
15911 Create an icon image.
15913 taint=display_image->taint;
15914 XMakeStandardColormap(display,icon_visual,icon_resources,
15915 display_image,icon_map,icon_pixel,exception);
15916 (void) XMakeImage(display,icon_resources,&windows->icon,
15917 display_image,windows->icon.width,windows->icon.height,
15919 display_image->taint=taint;
15920 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15921 windows->icon.pixmap);
15922 (void) XClearWindow(display,windows->icon.id);
15923 (void) XWithdrawWindow(display,windows->info.id,
15924 windows->info.screen);
15925 windows->icon.mapped=MagickTrue;
15928 if (event.xmap.window == windows->command.id)
15930 windows->command.mapped=MagickTrue;
15933 if (event.xmap.window == windows->popup.id)
15935 windows->popup.mapped=MagickTrue;
15938 if (event.xmap.window == windows->widget.id)
15940 windows->widget.mapped=MagickTrue;
15945 case MappingNotify:
15947 (void) XRefreshKeyboardMapping(&event.xmapping);
15952 case PropertyNotify:
15968 if (display_image->debug != MagickFalse)
15969 (void) LogMagickEvent(X11Event,GetMagickModule(),
15970 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15971 event.xproperty.atom,event.xproperty.state);
15972 if (event.xproperty.atom != windows->im_remote_command)
15975 Display image named by the remote command protocol.
15977 status=XGetWindowProperty(display,event.xproperty.window,
15978 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15979 AnyPropertyType,&type,&format,&length,&after,&data);
15980 if ((status != Success) || (length == 0))
15982 if (LocaleCompare((char *) data,"-quit") == 0)
15984 XClientMessage(display,windows->image.id,windows->im_protocols,
15985 windows->im_exit,CurrentTime);
15986 (void) XFree((void *) data);
15989 (void) CopyMagickString(resource_info->image_info->filename,
15990 (char *) data,MaxTextExtent);
15991 (void) XFree((void *) data);
15992 nexus=ReadImage(resource_info->image_info,exception);
15993 CatchException(exception);
15994 if (nexus != (Image *) NULL)
15995 *state|=NextImageState | ExitState;
15998 case ReparentNotify:
16000 if (display_image->debug != MagickFalse)
16001 (void) LogMagickEvent(X11Event,GetMagickModule(),
16002 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
16003 event.xreparent.window);
16008 if (display_image->debug != MagickFalse)
16009 (void) LogMagickEvent(X11Event,GetMagickModule(),
16010 "Unmap Notify: 0x%lx",event.xunmap.window);
16011 if (event.xunmap.window == windows->backdrop.id)
16013 windows->backdrop.mapped=MagickFalse;
16016 if (event.xunmap.window == windows->image.id)
16018 windows->image.mapped=MagickFalse;
16021 if (event.xunmap.window == windows->magnify.id)
16023 windows->magnify.mapped=MagickFalse;
16026 if (event.xunmap.window == windows->pan.id)
16028 windows->pan.mapped=MagickFalse;
16031 if (event.xunmap.window == windows->info.id)
16033 windows->info.mapped=MagickFalse;
16036 if (event.xunmap.window == windows->icon.id)
16038 if (map_info->colormap == icon_map->colormap)
16039 XConfigureImageColormap(display,resource_info,windows,
16040 display_image,exception);
16041 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16043 windows->icon.mapped=MagickFalse;
16046 if (event.xunmap.window == windows->command.id)
16048 windows->command.mapped=MagickFalse;
16051 if (event.xunmap.window == windows->popup.id)
16053 if (windows->backdrop.id != (Window) NULL)
16054 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16056 windows->popup.mapped=MagickFalse;
16059 if (event.xunmap.window == windows->widget.id)
16061 if (windows->backdrop.id != (Window) NULL)
16062 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16064 windows->widget.mapped=MagickFalse;
16071 if (display_image->debug != MagickFalse)
16072 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16077 } while (!(*state & ExitState));
16078 if ((*state & ExitState) == 0)
16079 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16080 &display_image,exception);
16082 if (resource_info->confirm_edit != MagickFalse)
16085 Query user if image has changed.
16087 if ((resource_info->immutable == MagickFalse) &&
16088 (display_image->taint != MagickFalse))
16093 status=XConfirmWidget(display,windows,"Your image changed.",
16094 "Do you want to save it");
16096 *state&=(~ExitState);
16099 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16100 &display_image,exception);
16103 if ((windows->visual_info->klass == GrayScale) ||
16104 (windows->visual_info->klass == PseudoColor) ||
16105 (windows->visual_info->klass == DirectColor))
16108 Withdraw pan and Magnify window.
16110 if (windows->info.mapped != MagickFalse)
16111 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16112 if (windows->magnify.mapped != MagickFalse)
16113 (void) XWithdrawWindow(display,windows->magnify.id,
16114 windows->magnify.screen);
16115 if (windows->command.mapped != MagickFalse)
16116 (void) XWithdrawWindow(display,windows->command.id,
16117 windows->command.screen);
16119 if (windows->pan.mapped != MagickFalse)
16120 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16121 if (resource_info->backdrop == MagickFalse)
16122 if (windows->backdrop.mapped)
16124 (void) XWithdrawWindow(display,windows->backdrop.id,
16125 windows->backdrop.screen);
16126 (void) XDestroyWindow(display,windows->backdrop.id);
16127 windows->backdrop.id=(Window) NULL;
16128 (void) XWithdrawWindow(display,windows->image.id,
16129 windows->image.screen);
16130 (void) XDestroyWindow(display,windows->image.id);
16131 windows->image.id=(Window) NULL;
16133 XSetCursorState(display,windows,MagickTrue);
16134 XCheckRefreshWindows(display,windows);
16135 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16136 *state&=(~ExitState);
16137 if (*state & ExitState)
16140 Free Standard Colormap.
16142 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16143 if (resource_info->map_type == (char *) NULL)
16144 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16148 if (resource_info->copy_image != (Image *) NULL)
16150 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16151 resource_info->copy_image=NewImageList();
16153 DestroyXResources();
16155 (void) XSync(display,MagickFalse);
16157 Restore our progress monitor and warning handlers.
16159 (void) SetErrorHandler(warning_handler);
16160 (void) SetWarningHandler(warning_handler);
16162 Change to home directory.
16164 directory=getcwd(working_directory,MaxTextExtent);
16170 status=chdir(resource_info->home_directory);
16172 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16173 "UnableToOpenFile","%s",resource_info->home_directory);
16175 *image=display_image;
16181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16185 + D i s p l a y I m a g e s %
16189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16191 % DisplayImages() displays an image sequence to any X window screen. It
16192 % returns a value other than 0 if successful. Check the exception member
16193 % of image to determine the reason for any failure.
16195 % The format of the DisplayImages method is:
16197 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16198 % Image *images,ExceptionInfo *exception)
16200 % A description of each parameter follows:
16202 % o image_info: the image info.
16204 % o image: the image.
16206 % o exception: return any errors or warnings in this structure.
16209 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16210 Image *image,ExceptionInfo *exception)
16212 assert(image_info != (const ImageInfo *) NULL);
16213 assert(image_info->signature == MagickSignature);
16214 assert(image != (Image *) NULL);
16215 assert(image->signature == MagickSignature);
16216 if (image->debug != MagickFalse)
16217 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16218 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16219 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
16220 return(MagickFalse);
16224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16228 + R e m o t e D i s p l a y C o m m a n d %
16232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16234 % RemoteDisplayCommand() encourages a remote display program to display the
16235 % specified image filename.
16237 % The format of the RemoteDisplayCommand method is:
16239 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16240 % const char *window,const char *filename,ExceptionInfo *exception)
16242 % A description of each parameter follows:
16244 % o image_info: the image info.
16246 % o window: Specifies the name or id of an X window.
16248 % o filename: the name of the image filename to display.
16250 % o exception: return any errors or warnings in this structure.
16253 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16254 const char *window,const char *filename,ExceptionInfo *exception)
16256 assert(image_info != (const ImageInfo *) NULL);
16257 assert(image_info->signature == MagickSignature);
16258 assert(filename != (char *) NULL);
16260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16261 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16262 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename);
16263 return(MagickFalse);