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 if ((*image)->matte == MagickFalse)
10103 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10104 image_view=AcquireCacheView(*image);
10111 Update matte information using point algorithm.
10113 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10114 (ssize_t) y_offset,1,1,exception);
10115 if (q == (Quantum *) NULL)
10117 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10118 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10121 case ReplaceMethod:
10128 virtual_pixel[CompositePixelChannel];
10131 Update matte information using replace algorithm.
10133 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
10134 (ssize_t) y_offset,virtual_pixel,exception);
10135 target.red=virtual_pixel[RedPixelChannel];
10136 target.green=virtual_pixel[GreenPixelChannel];
10137 target.blue=virtual_pixel[BluePixelChannel];
10138 target.alpha=virtual_pixel[AlphaPixelChannel];
10139 for (y=0; y < (int) (*image)->rows; y++)
10141 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10142 (*image)->columns,1,exception);
10143 if (q == (Quantum *) NULL)
10145 for (x=0; x < (int) (*image)->columns; x++)
10147 GetPixelInfoPixel(*image,q,&pixel);
10148 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10149 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10150 q+=GetPixelChannels(*image);
10152 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10157 case FloodfillMethod:
10158 case FillToBorderMethod:
10170 Update matte information using floodfill algorithm.
10172 (void) GetOneVirtualPixelInfo(*image,
10173 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10174 y_offset,&target,exception);
10175 if (method == FillToBorderMethod)
10177 target.red=(MagickRealType) ScaleShortToQuantum(
10179 target.green=(MagickRealType) ScaleShortToQuantum(
10180 border_color.green);
10181 target.blue=(MagickRealType) ScaleShortToQuantum(
10182 border_color.blue);
10184 draw_info=CloneDrawInfo(resource_info->image_info,
10185 (DrawInfo *) NULL);
10186 draw_info->fill.alpha=ClampToQuantum(StringToDouble(matte,
10188 channel_mask=SetPixelChannelMask(*image,AlphaChannel);
10189 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10190 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
10191 MagickFalse : MagickTrue,exception);
10192 (void) SetPixelChannelMapMask(*image,channel_mask);
10193 draw_info=DestroyDrawInfo(draw_info);
10199 Update matte information using reset algorithm.
10201 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10202 return(MagickFalse);
10203 for (y=0; y < (int) (*image)->rows; y++)
10205 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10206 (*image)->columns,1,exception);
10207 if (q == (Quantum *) NULL)
10209 for (x=0; x < (int) (*image)->columns; x++)
10211 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10212 q+=GetPixelChannels(*image);
10214 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10217 if (StringToLong(matte) == (long) OpaqueAlpha)
10218 (*image)->matte=MagickFalse;
10222 image_view=DestroyCacheView(image_view);
10223 state&=(~UpdateConfigurationState);
10225 } while ((state & ExitState) == 0);
10226 (void) XSelectInput(display,windows->image.id,
10227 windows->image.attributes.event_mask);
10228 XSetCursorState(display,windows,MagickFalse);
10229 (void) XFreeCursor(display,cursor);
10230 return(MagickTrue);
10234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10238 + X O p e n I m a g e %
10242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10244 % XOpenImage() loads an image from a file.
10246 % The format of the XOpenImage method is:
10248 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10249 % XWindows *windows,const unsigned int command)
10251 % A description of each parameter follows:
10253 % o display: Specifies a connection to an X server; returned from
10256 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10258 % o windows: Specifies a pointer to a XWindows structure.
10260 % o command: A value other than zero indicates that the file is selected
10261 % from the command line argument list.
10264 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10265 XWindows *windows,const MagickBooleanType command)
10280 filename[MaxTextExtent] = "\0";
10283 Request file name from user.
10285 if (command == MagickFalse)
10286 XFileBrowserWidget(display,windows,"Open",filename);
10302 Select next image from the command line.
10304 status=XGetCommand(display,windows->image.id,&files,&count);
10307 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10308 return((Image *) NULL);
10310 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10311 if (filelist == (char **) NULL)
10313 ThrowXWindowFatalException(ResourceLimitError,
10314 "MemoryAllocationFailed","...");
10315 (void) XFreeStringList(files);
10316 return((Image *) NULL);
10319 for (i=1; i < count; i++)
10320 if (*files[i] != '-')
10321 filelist[j++]=files[i];
10322 filelist[j]=(char *) NULL;
10323 XListBrowserWidget(display,windows,&windows->widget,
10324 (const char **) filelist,"Load","Select Image to Load:",filename);
10325 filelist=(char **) RelinquishMagickMemory(filelist);
10326 (void) XFreeStringList(files);
10328 if (*filename == '\0')
10329 return((Image *) NULL);
10330 image_info=CloneImageInfo(resource_info->image_info);
10331 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10333 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10334 exception=AcquireExceptionInfo();
10335 (void) SetImageInfo(image_info,0,exception);
10336 if (LocaleCompare(image_info->magick,"X") == 0)
10339 seconds[MaxTextExtent];
10342 User may want to delay the X server screen grab.
10344 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10345 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10347 if (*seconds == '\0')
10348 return((Image *) NULL);
10349 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10351 magick_info=GetMagickInfo(image_info->magick,exception);
10352 if ((magick_info != (const MagickInfo *) NULL) &&
10353 (magick_info->raw != MagickFalse))
10356 geometry[MaxTextExtent];
10359 Request image size from the user.
10361 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10362 if (image_info->size != (char *) NULL)
10363 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10364 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10366 (void) CloneString(&image_info->size,geometry);
10371 XSetCursorState(display,windows,MagickTrue);
10372 XCheckRefreshWindows(display,windows);
10373 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10374 nexus=ReadImage(image_info,exception);
10375 CatchException(exception);
10376 XSetCursorState(display,windows,MagickFalse);
10377 if (nexus != (Image *) NULL)
10378 XClientMessage(display,windows->image.id,windows->im_protocols,
10379 windows->im_next_image,CurrentTime);
10387 Unknown image format.
10389 text=FileToString(filename,~0,exception);
10390 if (text == (char *) NULL)
10391 return((Image *) NULL);
10392 textlist=StringToList(text);
10393 if (textlist != (char **) NULL)
10396 title[MaxTextExtent];
10401 (void) FormatLocaleString(title,MaxTextExtent,
10402 "Unknown format: %s",filename);
10403 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10404 (const char **) textlist);
10405 for (i=0; textlist[i] != (char *) NULL; i++)
10406 textlist[i]=DestroyString(textlist[i]);
10407 textlist=(char **) RelinquishMagickMemory(textlist);
10409 text=DestroyString(text);
10411 exception=DestroyExceptionInfo(exception);
10412 image_info=DestroyImageInfo(image_info);
10417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10421 + X P a n I m a g e %
10425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10427 % XPanImage() pans the image until the mouse button is released.
10429 % The format of the XPanImage method is:
10431 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10432 % ExceptionInfo *exception)
10434 % A description of each parameter follows:
10436 % o display: Specifies a connection to an X server; returned from
10439 % o windows: Specifies a pointer to a XWindows structure.
10441 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10442 % the entire image is refreshed.
10444 % o exception: return any errors or warnings in this structure.
10447 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10448 ExceptionInfo *exception)
10451 text[MaxTextExtent];
10469 if ((windows->image.ximage->width > (int) windows->image.width) &&
10470 (windows->image.ximage->height > (int) windows->image.height))
10471 cursor=XCreateFontCursor(display,XC_fleur);
10473 if (windows->image.ximage->width > (int) windows->image.width)
10474 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10476 if (windows->image.ximage->height > (int) windows->image.height)
10477 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10479 cursor=XCreateFontCursor(display,XC_arrow);
10480 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10482 Pan image as pointer moves until the mouse button is released.
10484 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10485 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10486 pan_info.width=windows->pan.width*windows->image.width/
10487 windows->image.ximage->width;
10488 pan_info.height=windows->pan.height*windows->image.height/
10489 windows->image.ximage->height;
10492 state=UpdateConfigurationState;
10495 switch (event->type)
10500 User choose an initial pan location.
10502 pan_info.x=(ssize_t) event->xbutton.x;
10503 pan_info.y=(ssize_t) event->xbutton.y;
10504 state|=UpdateConfigurationState;
10507 case ButtonRelease:
10510 User has finished panning the image.
10512 pan_info.x=(ssize_t) event->xbutton.x;
10513 pan_info.y=(ssize_t) event->xbutton.y;
10514 state|=UpdateConfigurationState | ExitState;
10519 pan_info.x=(ssize_t) event->xmotion.x;
10520 pan_info.y=(ssize_t) event->xmotion.y;
10521 state|=UpdateConfigurationState;
10526 if ((state & UpdateConfigurationState) != 0)
10529 Check boundary conditions.
10531 if (pan_info.x < (ssize_t) (pan_info.width/2))
10534 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10535 if (pan_info.x < 0)
10538 if ((int) (pan_info.x+windows->image.width) >
10539 windows->image.ximage->width)
10540 pan_info.x=(ssize_t)
10541 (windows->image.ximage->width-windows->image.width);
10542 if (pan_info.y < (ssize_t) (pan_info.height/2))
10545 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10546 if (pan_info.y < 0)
10549 if ((int) (pan_info.y+windows->image.height) >
10550 windows->image.ximage->height)
10551 pan_info.y=(ssize_t)
10552 (windows->image.ximage->height-windows->image.height);
10553 if ((windows->image.x != (int) pan_info.x) ||
10554 (windows->image.y != (int) pan_info.y))
10557 Display image pan offset.
10559 windows->image.x=(int) pan_info.x;
10560 windows->image.y=(int) pan_info.y;
10561 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10562 windows->image.width,windows->image.height,windows->image.x,
10564 XInfoWidget(display,windows,text);
10566 Refresh Image window.
10568 XDrawPanRectangle(display,windows);
10569 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10571 state&=(~UpdateConfigurationState);
10574 Wait for next event.
10576 if ((state & ExitState) == 0)
10577 XScreenEvent(display,windows,event,exception);
10578 } while ((state & ExitState) == 0);
10582 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10583 (void) XFreeCursor(display,cursor);
10584 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10592 + X P a s t e I m a g e %
10596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10598 % XPasteImage() pastes an image previously saved with XCropImage in the X
10599 % window image at a location the user chooses with the pointer.
10601 % The format of the XPasteImage method is:
10603 % MagickBooleanType XPasteImage(Display *display,
10604 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10605 % ExceptionInfo *exception)
10607 % A description of each parameter follows:
10609 % o display: Specifies a connection to an X server; returned from
10612 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10614 % o windows: Specifies a pointer to a XWindows structure.
10616 % o image: the image; returned from ReadImage.
10618 % o exception: return any errors or warnings in this structure.
10621 static MagickBooleanType XPasteImage(Display *display,
10622 XResourceInfo *resource_info,XWindows *windows,Image *image,
10623 ExceptionInfo *exception)
10634 static const ModeType
10637 PasteOperatorsCommand,
10639 PasteDismissCommand
10642 static CompositeOperator
10643 compose = CopyCompositeOp;
10646 text[MaxTextExtent];
10680 if (resource_info->copy_image == (Image *) NULL)
10681 return(MagickFalse);
10682 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10684 Map Command widget.
10686 (void) CloneString(&windows->command.name,"Paste");
10687 windows->command.data=1;
10688 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10689 (void) XMapRaised(display,windows->command.id);
10690 XClientMessage(display,windows->image.id,windows->im_protocols,
10691 windows->im_update_widget,CurrentTime);
10693 Track pointer until button 1 is pressed.
10695 XSetCursorState(display,windows,MagickFalse);
10696 XQueryPosition(display,windows->image.id,&x,&y);
10697 (void) XSelectInput(display,windows->image.id,
10698 windows->image.attributes.event_mask | PointerMotionMask);
10699 paste_info.x=(ssize_t) windows->image.x+x;
10700 paste_info.y=(ssize_t) windows->image.y+y;
10701 paste_info.width=0;
10702 paste_info.height=0;
10703 cursor=XCreateFontCursor(display,XC_ul_angle);
10704 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10705 state=DefaultState;
10708 if (windows->info.mapped != MagickFalse)
10711 Display pointer position.
10713 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10714 (long) paste_info.x,(long) paste_info.y);
10715 XInfoWidget(display,windows,text);
10717 highlight_info=paste_info;
10718 highlight_info.x=paste_info.x-windows->image.x;
10719 highlight_info.y=paste_info.y-windows->image.y;
10720 XHighlightRectangle(display,windows->image.id,
10721 windows->image.highlight_context,&highlight_info);
10723 Wait for next event.
10725 XScreenEvent(display,windows,&event,exception);
10726 XHighlightRectangle(display,windows->image.id,
10727 windows->image.highlight_context,&highlight_info);
10728 if (event.xany.window == windows->command.id)
10731 Select a command from the Command widget.
10733 id=XCommandWidget(display,windows,PasteMenu,&event);
10736 switch (PasteCommands[id])
10738 case PasteOperatorsCommand:
10741 command[MaxTextExtent],
10745 Select a command from the pop-up menu.
10747 operators=GetCommandOptions(MagickComposeOptions);
10748 if (operators == (char **) NULL)
10750 entry=XMenuWidget(display,windows,PasteMenu[id],
10751 (const char **) operators,command);
10753 compose=(CompositeOperator) ParseCommandOption(
10754 MagickComposeOptions,MagickFalse,operators[entry]);
10755 operators=DestroyStringList(operators);
10758 case PasteHelpCommand:
10760 XTextViewWidget(display,resource_info,windows,MagickFalse,
10761 "Help Viewer - Image Composite",ImagePasteHelp);
10764 case PasteDismissCommand:
10769 state|=EscapeState;
10778 switch (event.type)
10782 if (image->debug != MagickFalse)
10783 (void) LogMagickEvent(X11Event,GetMagickModule(),
10784 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10785 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10786 if (event.xbutton.button != Button1)
10788 if (event.xbutton.window != windows->image.id)
10791 Paste rectangle is relative to image configuration.
10793 width=(unsigned int) image->columns;
10794 height=(unsigned int) image->rows;
10797 if (windows->image.crop_geometry != (char *) NULL)
10798 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10800 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10801 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10802 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10803 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10804 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10805 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10806 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10809 case ButtonRelease:
10811 if (image->debug != MagickFalse)
10812 (void) LogMagickEvent(X11Event,GetMagickModule(),
10813 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10814 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10815 if (event.xbutton.button != Button1)
10817 if (event.xbutton.window != windows->image.id)
10819 if ((paste_info.width != 0) && (paste_info.height != 0))
10822 User has selected the location of the paste image.
10824 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10825 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10835 command[MaxTextExtent];
10843 if (event.xkey.window != windows->image.id)
10846 Respond to a user key press.
10848 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10849 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10850 *(command+length)='\0';
10851 if (image->debug != MagickFalse)
10852 (void) LogMagickEvent(X11Event,GetMagickModule(),
10853 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10854 switch ((int) key_symbol)
10862 paste_image=DestroyImage(paste_image);
10863 state|=EscapeState;
10870 (void) XSetFunction(display,windows->image.highlight_context,
10872 XTextViewWidget(display,resource_info,windows,MagickFalse,
10873 "Help Viewer - Image Composite",ImagePasteHelp);
10874 (void) XSetFunction(display,windows->image.highlight_context,
10880 (void) XBell(display,0);
10889 Map and unmap Info widget as text cursor crosses its boundaries.
10893 if (windows->info.mapped != MagickFalse)
10895 if ((x < (int) (windows->info.x+windows->info.width)) &&
10896 (y < (int) (windows->info.y+windows->info.height)))
10897 (void) XWithdrawWindow(display,windows->info.id,
10898 windows->info.screen);
10901 if ((x > (int) (windows->info.x+windows->info.width)) ||
10902 (y > (int) (windows->info.y+windows->info.height)))
10903 (void) XMapWindow(display,windows->info.id);
10904 paste_info.x=(ssize_t) windows->image.x+x;
10905 paste_info.y=(ssize_t) windows->image.y+y;
10910 if (image->debug != MagickFalse)
10911 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10916 } while ((state & ExitState) == 0);
10917 (void) XSelectInput(display,windows->image.id,
10918 windows->image.attributes.event_mask);
10919 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10920 XSetCursorState(display,windows,MagickFalse);
10921 (void) XFreeCursor(display,cursor);
10922 if ((state & EscapeState) != 0)
10923 return(MagickTrue);
10925 Image pasting is relative to image configuration.
10927 XSetCursorState(display,windows,MagickTrue);
10928 XCheckRefreshWindows(display,windows);
10929 width=(unsigned int) image->columns;
10930 height=(unsigned int) image->rows;
10933 if (windows->image.crop_geometry != (char *) NULL)
10934 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10935 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10937 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10938 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10939 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10941 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10942 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10944 Paste image with X Image window.
10946 (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y,
10948 paste_image=DestroyImage(paste_image);
10949 XSetCursorState(display,windows,MagickFalse);
10951 Update image colormap.
10953 XConfigureImageColormap(display,resource_info,windows,image,exception);
10954 (void) XConfigureImage(display,resource_info,windows,image,exception);
10955 return(MagickTrue);
10959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10963 + X P r i n t I m a g e %
10967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10969 % XPrintImage() prints an image to a Postscript printer.
10971 % The format of the XPrintImage method is:
10973 % MagickBooleanType XPrintImage(Display *display,
10974 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10975 % ExceptionInfo *exception)
10977 % A description of each parameter follows:
10979 % o display: Specifies a connection to an X server; returned from
10982 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10984 % o windows: Specifies a pointer to a XWindows structure.
10986 % o image: the image.
10988 % o exception: return any errors or warnings in this structure.
10991 static MagickBooleanType XPrintImage(Display *display,
10992 XResourceInfo *resource_info,XWindows *windows,Image *image,
10993 ExceptionInfo *exception)
10996 filename[MaxTextExtent],
10997 geometry[MaxTextExtent];
11009 Request Postscript page geometry from user.
11011 image_info=CloneImageInfo(resource_info->image_info);
11012 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
11013 if (image_info->page != (char *) NULL)
11014 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11015 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11016 "Select Postscript Page Geometry:",geometry);
11017 if (*geometry == '\0')
11018 return(MagickTrue);
11019 image_info->page=GetPageGeometry(geometry);
11021 Apply image transforms.
11023 XSetCursorState(display,windows,MagickTrue);
11024 XCheckRefreshWindows(display,windows);
11025 print_image=CloneImage(image,0,0,MagickTrue,exception);
11026 if (print_image == (Image *) NULL)
11027 return(MagickFalse);
11028 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11029 windows->image.ximage->width,windows->image.ximage->height);
11030 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11035 (void) AcquireUniqueFilename(filename);
11036 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11038 status=WriteImage(image_info,print_image,exception);
11039 (void) RelinquishUniqueFileResource(filename);
11040 print_image=DestroyImage(print_image);
11041 image_info=DestroyImageInfo(image_info);
11042 XSetCursorState(display,windows,MagickFalse);
11043 return(status != 0 ? MagickTrue : MagickFalse);
11047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11051 + X R O I I m a g e %
11055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11057 % XROIImage() applies an image processing technique to a region of interest.
11059 % The format of the XROIImage method is:
11061 % MagickBooleanType XROIImage(Display *display,
11062 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11063 % ExceptionInfo *exception)
11065 % A description of each parameter follows:
11067 % o display: Specifies a connection to an X server; returned from
11070 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11072 % o windows: Specifies a pointer to a XWindows structure.
11074 % o image: the image; returned from ReadImage.
11076 % o exception: return any errors or warnings in this structure.
11079 static MagickBooleanType XROIImage(Display *display,
11080 XResourceInfo *resource_info,XWindows *windows,Image **image,
11081 ExceptionInfo *exception)
11083 #define ApplyMenus 7
11133 "Contrast Stretch...",
11134 "Sigmoidal Contrast...",
11168 "Charcoal Draw...",
11171 *MiscellanyMenu[] =
11182 **Menus[ApplyMenus] =
11193 static const CommandType
11216 TransformCommands[] =
11220 RotateRightCommand,
11223 EnhanceCommands[] =
11231 ContrastStretchCommand,
11232 SigmoidalContrastCommand,
11240 EffectsCommands[] =
11244 ReduceNoiseCommand,
11263 CharcoalDrawCommand
11265 MiscellanyCommands[] =
11269 ShowPreviewCommand,
11270 ShowHistogramCommand,
11279 static const CommandType
11280 *Commands[ApplyMenus] =
11292 command[MaxTextExtent],
11293 text[MaxTextExtent];
11313 MagickProgressMonitor
11332 Map Command widget.
11334 (void) CloneString(&windows->command.name,"ROI");
11335 windows->command.data=0;
11336 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11337 (void) XMapRaised(display,windows->command.id);
11338 XClientMessage(display,windows->image.id,windows->im_protocols,
11339 windows->im_update_widget,CurrentTime);
11341 Track pointer until button 1 is pressed.
11343 XQueryPosition(display,windows->image.id,&x,&y);
11344 (void) XSelectInput(display,windows->image.id,
11345 windows->image.attributes.event_mask | PointerMotionMask);
11346 roi_info.x=(ssize_t) windows->image.x+x;
11347 roi_info.y=(ssize_t) windows->image.y+y;
11350 cursor=XCreateFontCursor(display,XC_fleur);
11351 state=DefaultState;
11354 if (windows->info.mapped != MagickFalse)
11357 Display pointer position.
11359 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11360 (long) roi_info.x,(long) roi_info.y);
11361 XInfoWidget(display,windows,text);
11364 Wait for next event.
11366 XScreenEvent(display,windows,&event,exception);
11367 if (event.xany.window == windows->command.id)
11370 Select a command from the Command widget.
11372 id=XCommandWidget(display,windows,ROIMenu,&event);
11375 switch (ROICommands[id])
11377 case ROIHelpCommand:
11379 XTextViewWidget(display,resource_info,windows,MagickFalse,
11380 "Help Viewer - Region of Interest",ImageROIHelp);
11383 case ROIDismissCommand:
11388 state|=EscapeState;
11397 switch (event.type)
11401 if (event.xbutton.button != Button1)
11403 if (event.xbutton.window != windows->image.id)
11406 Note first corner of region of interest rectangle-- exit loop.
11408 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11409 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11410 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11414 case ButtonRelease:
11423 if (event.xkey.window != windows->image.id)
11426 Respond to a user key press.
11428 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11429 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11430 switch ((int) key_symbol)
11438 state|=EscapeState;
11445 XTextViewWidget(display,resource_info,windows,MagickFalse,
11446 "Help Viewer - Region of Interest",ImageROIHelp);
11451 (void) XBell(display,0);
11460 Map and unmap Info widget as text cursor crosses its boundaries.
11464 if (windows->info.mapped != MagickFalse)
11466 if ((x < (int) (windows->info.x+windows->info.width)) &&
11467 (y < (int) (windows->info.y+windows->info.height)))
11468 (void) XWithdrawWindow(display,windows->info.id,
11469 windows->info.screen);
11472 if ((x > (int) (windows->info.x+windows->info.width)) ||
11473 (y > (int) (windows->info.y+windows->info.height)))
11474 (void) XMapWindow(display,windows->info.id);
11475 roi_info.x=(ssize_t) windows->image.x+x;
11476 roi_info.y=(ssize_t) windows->image.y+y;
11482 } while ((state & ExitState) == 0);
11483 (void) XSelectInput(display,windows->image.id,
11484 windows->image.attributes.event_mask);
11485 if ((state & EscapeState) != 0)
11488 User want to exit without region of interest.
11490 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11491 (void) XFreeCursor(display,cursor);
11492 return(MagickTrue);
11494 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11498 Size rectangle as pointer moves until the mouse button is released.
11500 x=(int) roi_info.x;
11501 y=(int) roi_info.y;
11504 state=DefaultState;
11507 highlight_info=roi_info;
11508 highlight_info.x=roi_info.x-windows->image.x;
11509 highlight_info.y=roi_info.y-windows->image.y;
11510 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11513 Display info and draw region of interest rectangle.
11515 if (windows->info.mapped == MagickFalse)
11516 (void) XMapWindow(display,windows->info.id);
11517 (void) FormatLocaleString(text,MaxTextExtent,
11518 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11519 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11520 XInfoWidget(display,windows,text);
11521 XHighlightRectangle(display,windows->image.id,
11522 windows->image.highlight_context,&highlight_info);
11525 if (windows->info.mapped != MagickFalse)
11526 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11528 Wait for next event.
11530 XScreenEvent(display,windows,&event,exception);
11531 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11532 XHighlightRectangle(display,windows->image.id,
11533 windows->image.highlight_context,&highlight_info);
11534 switch (event.type)
11538 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11539 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11542 case ButtonRelease:
11545 User has committed to region of interest rectangle.
11547 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11548 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11549 XSetCursorState(display,windows,MagickFalse);
11551 if (LocaleCompare(windows->command.name,"Apply") == 0)
11553 (void) CloneString(&windows->command.name,"Apply");
11554 windows->command.data=ApplyMenus;
11555 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11562 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11563 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11568 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11569 ((state & ExitState) != 0))
11572 Check boundary conditions.
11574 if (roi_info.x < 0)
11577 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11578 roi_info.x=(ssize_t) windows->image.ximage->width;
11579 if ((int) roi_info.x < x)
11580 roi_info.width=(unsigned int) (x-roi_info.x);
11583 roi_info.width=(unsigned int) (roi_info.x-x);
11584 roi_info.x=(ssize_t) x;
11586 if (roi_info.y < 0)
11589 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11590 roi_info.y=(ssize_t) windows->image.ximage->height;
11591 if ((int) roi_info.y < y)
11592 roi_info.height=(unsigned int) (y-roi_info.y);
11595 roi_info.height=(unsigned int) (roi_info.y-y);
11596 roi_info.y=(ssize_t) y;
11599 } while ((state & ExitState) == 0);
11601 Wait for user to grab a corner of the rectangle or press return.
11603 state=DefaultState;
11604 command_type=NullCommand;
11605 (void) XMapWindow(display,windows->info.id);
11608 if (windows->info.mapped != MagickFalse)
11611 Display pointer position.
11613 (void) FormatLocaleString(text,MaxTextExtent,
11614 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11615 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11616 XInfoWidget(display,windows,text);
11618 highlight_info=roi_info;
11619 highlight_info.x=roi_info.x-windows->image.x;
11620 highlight_info.y=roi_info.y-windows->image.y;
11621 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11623 state|=EscapeState;
11627 if ((state & UpdateRegionState) != 0)
11629 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11630 switch (command_type)
11635 (void) XMagickCommand(display,resource_info,windows,command_type,
11642 Region of interest is relative to image configuration.
11644 progress_monitor=SetImageProgressMonitor(*image,
11645 (MagickProgressMonitor) NULL,(*image)->client_data);
11646 crop_info=roi_info;
11647 width=(unsigned int) (*image)->columns;
11648 height=(unsigned int) (*image)->rows;
11651 if (windows->image.crop_geometry != (char *) NULL)
11652 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11654 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11656 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11657 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11658 scale_factor=(MagickRealType)
11659 height/windows->image.ximage->height;
11661 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11662 crop_info.height=(unsigned int)
11663 (scale_factor*crop_info.height+0.5);
11664 roi_image=CropImage(*image,&crop_info,exception);
11665 (void) SetImageProgressMonitor(*image,progress_monitor,
11666 (*image)->client_data);
11667 if (roi_image == (Image *) NULL)
11670 Apply image processing technique to the region of interest.
11672 windows->image.orphan=MagickTrue;
11673 (void) XMagickCommand(display,resource_info,windows,command_type,
11674 &roi_image,exception);
11675 progress_monitor=SetImageProgressMonitor(*image,
11676 (MagickProgressMonitor) NULL,(*image)->client_data);
11677 (void) XMagickCommand(display,resource_info,windows,
11678 SaveToUndoBufferCommand,image,exception);
11679 windows->image.orphan=MagickFalse;
11680 (void) CompositeImage(*image,CopyCompositeOp,roi_image,
11681 crop_info.x,crop_info.y,exception);
11682 roi_image=DestroyImage(roi_image);
11683 (void) SetImageProgressMonitor(*image,progress_monitor,
11684 (*image)->client_data);
11688 if (command_type != InfoCommand)
11690 XConfigureImageColormap(display,resource_info,windows,*image,
11692 (void) XConfigureImage(display,resource_info,windows,*image,
11695 XCheckRefreshWindows(display,windows);
11696 XInfoWidget(display,windows,text);
11697 (void) XSetFunction(display,windows->image.highlight_context,
11699 state&=(~UpdateRegionState);
11701 XHighlightRectangle(display,windows->image.id,
11702 windows->image.highlight_context,&highlight_info);
11703 XScreenEvent(display,windows,&event,exception);
11704 if (event.xany.window == windows->command.id)
11707 Select a command from the Command widget.
11709 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11710 command_type=NullCommand;
11711 id=XCommandWidget(display,windows,ApplyMenu,&event);
11714 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11715 command_type=ApplyCommands[id];
11716 if (id < ApplyMenus)
11719 Select a command from a pop-up menu.
11721 entry=XMenuWidget(display,windows,ApplyMenu[id],
11722 (const char **) Menus[id],command);
11725 (void) CopyMagickString(command,Menus[id][entry],
11727 command_type=Commands[id][entry];
11731 (void) XSetFunction(display,windows->image.highlight_context,
11733 XHighlightRectangle(display,windows->image.id,
11734 windows->image.highlight_context,&highlight_info);
11735 if (command_type == HelpCommand)
11737 (void) XSetFunction(display,windows->image.highlight_context,
11739 XTextViewWidget(display,resource_info,windows,MagickFalse,
11740 "Help Viewer - Region of Interest",ImageROIHelp);
11741 (void) XSetFunction(display,windows->image.highlight_context,
11745 if (command_type == QuitCommand)
11750 state|=EscapeState;
11754 if (command_type != NullCommand)
11755 state|=UpdateRegionState;
11758 XHighlightRectangle(display,windows->image.id,
11759 windows->image.highlight_context,&highlight_info);
11760 switch (event.type)
11764 x=windows->image.x;
11765 y=windows->image.y;
11766 if (event.xbutton.button != Button1)
11768 if (event.xbutton.window != windows->image.id)
11770 x=windows->image.x+event.xbutton.x;
11771 y=windows->image.y+event.xbutton.y;
11772 if ((x < (int) (roi_info.x+RoiDelta)) &&
11773 (x > (int) (roi_info.x-RoiDelta)) &&
11774 (y < (int) (roi_info.y+RoiDelta)) &&
11775 (y > (int) (roi_info.y-RoiDelta)))
11777 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11778 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11779 state|=UpdateConfigurationState;
11782 if ((x < (int) (roi_info.x+RoiDelta)) &&
11783 (x > (int) (roi_info.x-RoiDelta)) &&
11784 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11785 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11787 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11788 state|=UpdateConfigurationState;
11791 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11792 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11793 (y < (int) (roi_info.y+RoiDelta)) &&
11794 (y > (int) (roi_info.y-RoiDelta)))
11796 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11797 state|=UpdateConfigurationState;
11800 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11801 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11802 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11803 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11805 state|=UpdateConfigurationState;
11809 case ButtonRelease:
11811 if (event.xbutton.window == windows->pan.id)
11812 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11813 (highlight_info.y != crop_info.y-windows->image.y))
11814 XHighlightRectangle(display,windows->image.id,
11815 windows->image.highlight_context,&highlight_info);
11816 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11817 event.xbutton.time);
11822 if (event.xexpose.window == windows->image.id)
11823 if (event.xexpose.count == 0)
11825 event.xexpose.x=(int) highlight_info.x;
11826 event.xexpose.y=(int) highlight_info.y;
11827 event.xexpose.width=(int) highlight_info.width;
11828 event.xexpose.height=(int) highlight_info.height;
11829 XRefreshWindow(display,&windows->image,&event);
11831 if (event.xexpose.window == windows->info.id)
11832 if (event.xexpose.count == 0)
11833 XInfoWidget(display,windows,text);
11841 if (event.xkey.window != windows->image.id)
11844 Respond to a user key press.
11846 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11847 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11848 switch ((int) key_symbol)
11855 state|=EscapeState;
11864 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11865 roi_info.y=(ssize_t) (windows->image.height/2L-
11866 roi_info.height/2L);
11898 (void) XSetFunction(display,windows->image.highlight_context,
11900 XTextViewWidget(display,resource_info,windows,MagickFalse,
11901 "Help Viewer - Region of Interest",ImageROIHelp);
11902 (void) XSetFunction(display,windows->image.highlight_context,
11908 command_type=XImageWindowCommand(display,resource_info,windows,
11909 event.xkey.state,key_symbol,image,exception);
11910 if (command_type != NullCommand)
11911 state|=UpdateRegionState;
11915 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11923 if (event.xbutton.window != windows->image.id)
11926 Map and unmap Info widget as text cursor crosses its boundaries.
11930 if (windows->info.mapped != MagickFalse)
11932 if ((x < (int) (windows->info.x+windows->info.width)) &&
11933 (y < (int) (windows->info.y+windows->info.height)))
11934 (void) XWithdrawWindow(display,windows->info.id,
11935 windows->info.screen);
11938 if ((x > (int) (windows->info.x+windows->info.width)) ||
11939 (y > (int) (windows->info.y+windows->info.height)))
11940 (void) XMapWindow(display,windows->info.id);
11941 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11942 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11945 case SelectionRequest:
11950 XSelectionRequestEvent
11954 Set primary selection.
11956 (void) FormatLocaleString(text,MaxTextExtent,
11957 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11958 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11959 request=(&(event.xselectionrequest));
11960 (void) XChangeProperty(request->display,request->requestor,
11961 request->property,request->target,8,PropModeReplace,
11962 (unsigned char *) text,(int) strlen(text));
11963 notify.type=SelectionNotify;
11964 notify.display=request->display;
11965 notify.requestor=request->requestor;
11966 notify.selection=request->selection;
11967 notify.target=request->target;
11968 notify.time=request->time;
11969 if (request->property == None)
11970 notify.property=request->target;
11972 notify.property=request->property;
11973 (void) XSendEvent(request->display,request->requestor,False,0,
11974 (XEvent *) ¬ify);
11979 if ((state & UpdateConfigurationState) != 0)
11981 (void) XPutBackEvent(display,&event);
11982 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11985 } while ((state & ExitState) == 0);
11986 } while ((state & ExitState) == 0);
11987 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11988 XSetCursorState(display,windows,MagickFalse);
11989 if ((state & EscapeState) != 0)
11990 return(MagickTrue);
11991 return(MagickTrue);
11995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11999 + X R o t a t e I m a g e %
12003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12005 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
12006 % rotation angle is computed from the slope of a line drawn by the user.
12008 % The format of the XRotateImage method is:
12010 % MagickBooleanType XRotateImage(Display *display,
12011 % XResourceInfo *resource_info,XWindows *windows,double degrees,
12012 % Image **image,ExceptionInfo *exception)
12014 % A description of each parameter follows:
12016 % o display: Specifies a connection to an X server; returned from
12019 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12021 % o windows: Specifies a pointer to a XWindows structure.
12023 % o degrees: Specifies the number of degrees to rotate the image.
12025 % o image: the image.
12027 % o exception: return any errors or warnings in this structure.
12030 static MagickBooleanType XRotateImage(Display *display,
12031 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12032 ExceptionInfo *exception)
12045 direction = HorizontalRotateCommand;
12047 static const ModeType
12048 DirectionCommands[] =
12050 HorizontalRotateCommand,
12051 VerticalRotateCommand
12055 RotateColorCommand,
12056 RotateDirectionCommand,
12058 RotateDismissCommand
12061 static unsigned int
12065 command[MaxTextExtent],
12066 text[MaxTextExtent];
12077 normalized_degrees;
12087 if (degrees == 0.0)
12102 Map Command widget.
12104 (void) CloneString(&windows->command.name,"Rotate");
12105 windows->command.data=2;
12106 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12107 (void) XMapRaised(display,windows->command.id);
12108 XClientMessage(display,windows->image.id,windows->im_protocols,
12109 windows->im_update_widget,CurrentTime);
12111 Wait for first button press.
12113 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12114 XQueryPosition(display,windows->image.id,&x,&y);
12119 state=DefaultState;
12122 XHighlightLine(display,windows->image.id,
12123 windows->image.highlight_context,&rotate_info);
12125 Wait for next event.
12127 XScreenEvent(display,windows,&event,exception);
12128 XHighlightLine(display,windows->image.id,
12129 windows->image.highlight_context,&rotate_info);
12130 if (event.xany.window == windows->command.id)
12133 Select a command from the Command widget.
12135 id=XCommandWidget(display,windows,RotateMenu,&event);
12138 (void) XSetFunction(display,windows->image.highlight_context,
12140 switch (RotateCommands[id])
12142 case RotateColorCommand:
12145 *ColorMenu[MaxNumberPens];
12154 Initialize menu selections.
12156 for (i=0; i < (int) (MaxNumberPens-2); i++)
12157 ColorMenu[i]=resource_info->pen_colors[i];
12158 ColorMenu[MaxNumberPens-2]="Browser...";
12159 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12161 Select a pen color from the pop-up menu.
12163 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12164 (const char **) ColorMenu,command);
12165 if (pen_number < 0)
12167 if (pen_number == (MaxNumberPens-2))
12170 color_name[MaxTextExtent] = "gray";
12173 Select a pen color from a dialog.
12175 resource_info->pen_colors[pen_number]=color_name;
12176 XColorBrowserWidget(display,windows,"Select",color_name);
12177 if (*color_name == '\0')
12183 (void) XParseColor(display,windows->map_info->colormap,
12184 resource_info->pen_colors[pen_number],&color);
12185 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12186 (unsigned int) MaxColors,&color);
12187 windows->pixel_info->pen_colors[pen_number]=color;
12188 pen_id=(unsigned int) pen_number;
12191 case RotateDirectionCommand:
12202 Select a command from the pop-up menu.
12204 id=XMenuWidget(display,windows,RotateMenu[id],
12205 Directions,command);
12207 direction=DirectionCommands[id];
12210 case RotateHelpCommand:
12212 XTextViewWidget(display,resource_info,windows,MagickFalse,
12213 "Help Viewer - Image Rotation",ImageRotateHelp);
12216 case RotateDismissCommand:
12221 state|=EscapeState;
12228 (void) XSetFunction(display,windows->image.highlight_context,
12232 switch (event.type)
12236 if (event.xbutton.button != Button1)
12238 if (event.xbutton.window != windows->image.id)
12243 (void) XSetFunction(display,windows->image.highlight_context,
12245 rotate_info.x1=event.xbutton.x;
12246 rotate_info.y1=event.xbutton.y;
12250 case ButtonRelease:
12257 command[MaxTextExtent];
12262 if (event.xkey.window != windows->image.id)
12265 Respond to a user key press.
12267 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12268 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12269 switch ((int) key_symbol)
12277 state|=EscapeState;
12284 (void) XSetFunction(display,windows->image.highlight_context,
12286 XTextViewWidget(display,resource_info,windows,MagickFalse,
12287 "Help Viewer - Image Rotation",ImageRotateHelp);
12288 (void) XSetFunction(display,windows->image.highlight_context,
12294 (void) XBell(display,0);
12302 rotate_info.x1=event.xmotion.x;
12303 rotate_info.y1=event.xmotion.y;
12306 rotate_info.x2=rotate_info.x1;
12307 rotate_info.y2=rotate_info.y1;
12308 if (direction == HorizontalRotateCommand)
12309 rotate_info.x2+=32;
12311 rotate_info.y2-=32;
12312 } while ((state & ExitState) == 0);
12313 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12314 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12315 if ((state & EscapeState) != 0)
12316 return(MagickTrue);
12318 Draw line as pointer moves until the mouse button is released.
12321 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12322 state=DefaultState;
12328 Display info and draw rotation line.
12330 if (windows->info.mapped == MagickFalse)
12331 (void) XMapWindow(display,windows->info.id);
12332 (void) FormatLocaleString(text,MaxTextExtent," %g",
12333 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12334 XInfoWidget(display,windows,text);
12335 XHighlightLine(display,windows->image.id,
12336 windows->image.highlight_context,&rotate_info);
12339 if (windows->info.mapped != MagickFalse)
12340 (void) XWithdrawWindow(display,windows->info.id,
12341 windows->info.screen);
12343 Wait for next event.
12345 XScreenEvent(display,windows,&event,exception);
12347 XHighlightLine(display,windows->image.id,
12348 windows->image.highlight_context,&rotate_info);
12349 switch (event.type)
12353 case ButtonRelease:
12356 User has committed to rotation line.
12358 rotate_info.x2=event.xbutton.x;
12359 rotate_info.y2=event.xbutton.y;
12367 rotate_info.x2=event.xmotion.x;
12368 rotate_info.y2=event.xmotion.y;
12374 Check boundary conditions.
12376 if (rotate_info.x2 < 0)
12379 if (rotate_info.x2 > (int) windows->image.width)
12380 rotate_info.x2=(short) windows->image.width;
12381 if (rotate_info.y2 < 0)
12384 if (rotate_info.y2 > (int) windows->image.height)
12385 rotate_info.y2=(short) windows->image.height;
12387 Compute rotation angle from the slope of the line.
12390 distance=(unsigned int)
12391 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12392 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12394 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12395 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12396 } while ((state & ExitState) == 0);
12397 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12398 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12400 return(MagickTrue);
12402 if (direction == VerticalRotateCommand)
12404 if (degrees == 0.0)
12405 return(MagickTrue);
12409 normalized_degrees=degrees;
12410 while (normalized_degrees < -45.0)
12411 normalized_degrees+=360.0;
12412 for (rotations=0; normalized_degrees > 45.0; rotations++)
12413 normalized_degrees-=90.0;
12414 if (normalized_degrees != 0.0)
12415 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12417 XSetCursorState(display,windows,MagickTrue);
12418 XCheckRefreshWindows(display,windows);
12419 (*image)->background_color.red=ScaleShortToQuantum(
12420 windows->pixel_info->pen_colors[pen_id].red);
12421 (*image)->background_color.green=ScaleShortToQuantum(
12422 windows->pixel_info->pen_colors[pen_id].green);
12423 (*image)->background_color.blue=ScaleShortToQuantum(
12424 windows->pixel_info->pen_colors[pen_id].blue);
12425 rotate_image=RotateImage(*image,degrees,exception);
12426 XSetCursorState(display,windows,MagickFalse);
12427 if (rotate_image == (Image *) NULL)
12428 return(MagickFalse);
12429 *image=DestroyImage(*image);
12430 *image=rotate_image;
12431 if (windows->image.crop_geometry != (char *) NULL)
12434 Rotate crop geometry.
12436 width=(unsigned int) (*image)->columns;
12437 height=(unsigned int) (*image)->rows;
12438 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12439 switch (rotations % 4)
12449 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12450 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12457 Rotate 180 degrees.
12459 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12460 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12466 Rotate 270 degrees.
12468 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12469 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12474 if (windows->image.orphan != MagickFalse)
12475 return(MagickTrue);
12476 if (normalized_degrees != 0.0)
12479 Update image colormap.
12481 windows->image.window_changes.width=(int) (*image)->columns;
12482 windows->image.window_changes.height=(int) (*image)->rows;
12483 if (windows->image.crop_geometry != (char *) NULL)
12486 Obtain dimensions of image from crop geometry.
12488 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12490 windows->image.window_changes.width=(int) width;
12491 windows->image.window_changes.height=(int) height;
12493 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12496 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12498 windows->image.window_changes.width=windows->image.ximage->height;
12499 windows->image.window_changes.height=windows->image.ximage->width;
12502 Update image configuration.
12504 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12505 return(MagickTrue);
12509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12513 + X S a v e I m a g e %
12517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12519 % XSaveImage() saves an image to a file.
12521 % The format of the XSaveImage method is:
12523 % MagickBooleanType XSaveImage(Display *display,
12524 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12525 % ExceptionInfo *exception)
12527 % A description of each parameter follows:
12529 % o display: Specifies a connection to an X server; returned from
12532 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12534 % o windows: Specifies a pointer to a XWindows structure.
12536 % o image: the image.
12538 % o exception: return any errors or warnings in this structure.
12541 static MagickBooleanType XSaveImage(Display *display,
12542 XResourceInfo *resource_info,XWindows *windows,Image *image,
12543 ExceptionInfo *exception)
12546 filename[MaxTextExtent],
12547 geometry[MaxTextExtent];
12559 Request file name from user.
12561 if (resource_info->write_filename != (char *) NULL)
12562 (void) CopyMagickString(filename,resource_info->write_filename,
12567 path[MaxTextExtent];
12572 GetPathComponent(image->filename,HeadPath,path);
12573 GetPathComponent(image->filename,TailPath,filename);
12576 status=chdir(path);
12578 (void) ThrowMagickException(exception,GetMagickModule(),
12579 FileOpenError,"UnableToOpenFile","%s",path);
12582 XFileBrowserWidget(display,windows,"Save",filename);
12583 if (*filename == '\0')
12584 return(MagickTrue);
12585 if (IsPathAccessible(filename) != MagickFalse)
12591 File exists-- seek user's permission before overwriting.
12593 status=XConfirmWidget(display,windows,"Overwrite",filename);
12595 return(MagickTrue);
12597 image_info=CloneImageInfo(resource_info->image_info);
12598 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12599 (void) SetImageInfo(image_info,1,exception);
12600 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12601 (LocaleCompare(image_info->magick,"JPG") == 0))
12604 quality[MaxTextExtent];
12610 Request JPEG quality from user.
12612 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12614 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12616 if (*quality == '\0')
12617 return(MagickTrue);
12618 image->quality=StringToUnsignedLong(quality);
12619 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12621 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12622 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12623 (LocaleCompare(image_info->magick,"PS") == 0) ||
12624 (LocaleCompare(image_info->magick,"PS2") == 0))
12627 geometry[MaxTextExtent];
12630 Request page geometry from user.
12632 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12633 if (LocaleCompare(image_info->magick,"PDF") == 0)
12634 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12635 if (image_info->page != (char *) NULL)
12636 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12637 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12638 "Select page geometry:",geometry);
12639 if (*geometry != '\0')
12640 image_info->page=GetPageGeometry(geometry);
12643 Apply image transforms.
12645 XSetCursorState(display,windows,MagickTrue);
12646 XCheckRefreshWindows(display,windows);
12647 save_image=CloneImage(image,0,0,MagickTrue,exception);
12648 if (save_image == (Image *) NULL)
12649 return(MagickFalse);
12650 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12651 windows->image.ximage->width,windows->image.ximage->height);
12652 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12657 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12658 status=WriteImage(image_info,save_image,exception);
12659 if (status != MagickFalse)
12660 image->taint=MagickFalse;
12661 save_image=DestroyImage(save_image);
12662 image_info=DestroyImageInfo(image_info);
12663 XSetCursorState(display,windows,MagickFalse);
12664 return(status != 0 ? MagickTrue : MagickFalse);
12668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12672 + X S c r e e n E v e n t %
12676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12678 % XScreenEvent() handles global events associated with the Pan and Magnify
12681 % The format of the XScreenEvent function is:
12683 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12684 % ExceptionInfo *exception)
12686 % A description of each parameter follows:
12688 % o display: Specifies a pointer to the Display structure; returned from
12691 % o windows: Specifies a pointer to a XWindows structure.
12693 % o event: Specifies a pointer to a X11 XEvent structure.
12695 % o exception: return any errors or warnings in this structure.
12699 #if defined(__cplusplus) || defined(c_plusplus)
12703 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12708 windows=(XWindows *) data;
12709 if ((event->type == ClientMessage) &&
12710 (event->xclient.window == windows->image.id))
12711 return(MagickFalse);
12712 return(MagickTrue);
12715 #if defined(__cplusplus) || defined(c_plusplus)
12719 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12720 ExceptionInfo *exception)
12726 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12727 if (event->xany.window == windows->command.id)
12729 switch (event->type)
12732 case ButtonRelease:
12734 if ((event->xbutton.button == Button3) &&
12735 (event->xbutton.state & Mod1Mask))
12738 Convert Alt-Button3 to Button2.
12740 event->xbutton.button=Button2;
12741 event->xbutton.state&=(~Mod1Mask);
12743 if (event->xbutton.window == windows->backdrop.id)
12745 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12746 event->xbutton.time);
12749 if (event->xbutton.window == windows->pan.id)
12751 XPanImage(display,windows,event,exception);
12754 if (event->xbutton.window == windows->image.id)
12755 if (event->xbutton.button == Button2)
12758 Update magnified image.
12760 x=event->xbutton.x;
12761 y=event->xbutton.y;
12765 if (x >= (int) windows->image.width)
12766 x=(int) (windows->image.width-1);
12767 windows->magnify.x=(int) windows->image.x+x;
12771 if (y >= (int) windows->image.height)
12772 y=(int) (windows->image.height-1);
12773 windows->magnify.y=windows->image.y+y;
12774 if (windows->magnify.mapped == MagickFalse)
12775 (void) XMapRaised(display,windows->magnify.id);
12776 XMakeMagnifyImage(display,windows,exception);
12777 if (event->type == ButtonRelease)
12778 (void) XWithdrawWindow(display,windows->info.id,
12779 windows->info.screen);
12784 case ClientMessage:
12787 If client window delete message, exit.
12789 if (event->xclient.message_type != windows->wm_protocols)
12791 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12793 if (event->xclient.window == windows->magnify.id)
12795 (void) XWithdrawWindow(display,windows->magnify.id,
12796 windows->magnify.screen);
12801 case ConfigureNotify:
12803 if (event->xconfigure.window == windows->magnify.id)
12809 Magnify window has a new configuration.
12811 windows->magnify.width=(unsigned int) event->xconfigure.width;
12812 windows->magnify.height=(unsigned int) event->xconfigure.height;
12813 if (windows->magnify.mapped == MagickFalse)
12816 while ((int) magnify <= event->xconfigure.width)
12818 while ((int) magnify <= event->xconfigure.height)
12821 if (((int) magnify != event->xconfigure.width) ||
12822 ((int) magnify != event->xconfigure.height))
12827 window_changes.width=(int) magnify;
12828 window_changes.height=(int) magnify;
12829 (void) XReconfigureWMWindow(display,windows->magnify.id,
12830 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12834 XMakeMagnifyImage(display,windows,exception);
12841 if (event->xexpose.window == windows->image.id)
12843 XRefreshWindow(display,&windows->image,event);
12846 if (event->xexpose.window == windows->pan.id)
12847 if (event->xexpose.count == 0)
12849 XDrawPanRectangle(display,windows);
12852 if (event->xexpose.window == windows->magnify.id)
12853 if (event->xexpose.count == 0)
12855 XMakeMagnifyImage(display,windows,exception);
12863 command[MaxTextExtent];
12868 if (event->xkey.window != windows->magnify.id)
12871 Respond to a user key press.
12873 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12874 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12875 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12881 if (event->xmap.window == windows->magnify.id)
12883 windows->magnify.mapped=MagickTrue;
12884 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12887 if (event->xmap.window == windows->info.id)
12889 windows->info.mapped=MagickTrue;
12896 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12897 if (event->xmotion.window == windows->image.id)
12898 if (windows->magnify.mapped != MagickFalse)
12901 Update magnified image.
12903 x=event->xmotion.x;
12904 y=event->xmotion.y;
12908 if (x >= (int) windows->image.width)
12909 x=(int) (windows->image.width-1);
12910 windows->magnify.x=(int) windows->image.x+x;
12914 if (y >= (int) windows->image.height)
12915 y=(int) (windows->image.height-1);
12916 windows->magnify.y=windows->image.y+y;
12917 XMakeMagnifyImage(display,windows,exception);
12923 if (event->xunmap.window == windows->magnify.id)
12925 windows->magnify.mapped=MagickFalse;
12928 if (event->xunmap.window == windows->info.id)
12930 windows->info.mapped=MagickFalse;
12941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12945 + X S e t C r o p G e o m e t r y %
12949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12951 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12952 % and translates it to a cropping geometry relative to the image.
12954 % The format of the XSetCropGeometry method is:
12956 % void XSetCropGeometry(Display *display,XWindows *windows,
12957 % RectangleInfo *crop_info,Image *image)
12959 % A description of each parameter follows:
12961 % o display: Specifies a connection to an X server; returned from
12964 % o windows: Specifies a pointer to a XWindows structure.
12966 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12967 % Image window to crop.
12969 % o image: the image.
12972 static void XSetCropGeometry(Display *display,XWindows *windows,
12973 RectangleInfo *crop_info,Image *image)
12976 text[MaxTextExtent];
12989 if (windows->info.mapped != MagickFalse)
12992 Display info on cropping rectangle.
12994 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12995 (double) crop_info->width,(double) crop_info->height,(double)
12996 crop_info->x,(double) crop_info->y);
12997 XInfoWidget(display,windows,text);
13000 Cropping geometry is relative to any previous crop geometry.
13004 width=(unsigned int) image->columns;
13005 height=(unsigned int) image->rows;
13006 if (windows->image.crop_geometry != (char *) NULL)
13007 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13009 windows->image.crop_geometry=AcquireString((char *) NULL);
13011 Define the crop geometry string from the cropping rectangle.
13013 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13014 if (crop_info->x > 0)
13015 x+=(int) (scale_factor*crop_info->x+0.5);
13016 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13019 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13020 if (crop_info->y > 0)
13021 y+=(int) (scale_factor*crop_info->y+0.5);
13022 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13025 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13026 "%ux%u%+d%+d",width,height,x,y);
13030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13034 + X T i l e I m a g e %
13038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13040 % XTileImage() loads or deletes a selected tile from a visual image directory.
13041 % The load or delete command is chosen from a menu.
13043 % The format of the XTileImage method is:
13045 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13046 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13048 % A description of each parameter follows:
13050 % o tile_image: XTileImage reads or deletes the tile image
13051 % and returns it. A null image is returned if an error occurs.
13053 % o display: Specifies a connection to an X server; returned from
13056 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13058 % o windows: Specifies a pointer to a XWindows structure.
13060 % o image: the image; returned from ReadImage.
13062 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13063 % the entire image is refreshed.
13065 % o exception: return any errors or warnings in this structure.
13068 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13069 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13082 static const ModeType
13093 command[MaxTextExtent],
13094 filename[MaxTextExtent];
13121 Tile image is relative to montage image configuration.
13125 width=(unsigned int) image->columns;
13126 height=(unsigned int) image->rows;
13127 if (windows->image.crop_geometry != (char *) NULL)
13128 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13129 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13130 event->xbutton.x+=windows->image.x;
13131 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13132 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13133 event->xbutton.y+=windows->image.y;
13134 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13136 Determine size and location of each tile in the visual image directory.
13138 width=(unsigned int) image->columns;
13139 height=(unsigned int) image->rows;
13142 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13143 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13144 (event->xbutton.x-x)/width;
13148 Button press is outside any tile.
13150 (void) XBell(display,0);
13151 return((Image *) NULL);
13154 Determine file name from the tile directory.
13156 p=image->directory;
13157 for (i=tile; (i != 0) && (*p != '\0'); )
13166 Button press is outside any tile.
13168 (void) XBell(display,0);
13169 return((Image *) NULL);
13172 Select a command from the pop-up menu.
13174 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13176 return((Image *) NULL);
13178 while ((*q != '\n') && (*q != '\0'))
13180 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13182 Perform command for the selected tile.
13184 XSetCursorState(display,windows,MagickTrue);
13185 XCheckRefreshWindows(display,windows);
13186 tile_image=NewImageList();
13187 switch (TileCommands[id])
13189 case TileLoadCommand:
13194 XCheckRefreshWindows(display,windows);
13195 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13197 (void) CopyMagickString(resource_info->image_info->filename,filename,
13199 tile_image=ReadImage(resource_info->image_info,exception);
13200 CatchException(exception);
13201 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13204 case TileNextCommand:
13207 Display next image.
13209 XClientMessage(display,windows->image.id,windows->im_protocols,
13210 windows->im_next_image,CurrentTime);
13213 case TileFormerCommand:
13216 Display former image.
13218 XClientMessage(display,windows->image.id,windows->im_protocols,
13219 windows->im_former_image,CurrentTime);
13222 case TileDeleteCommand:
13227 if (IsPathAccessible(filename) == MagickFalse)
13229 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13232 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13235 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
13236 if (status != MagickFalse)
13238 XNoticeWidget(display,windows,"Unable to delete image file:",
13243 case TileUpdateCommand:
13253 virtual_pixel[CompositePixelChannel];
13262 Ensure all the images exist.
13265 GetPixelInfo(image,&pixel);
13266 for (p=image->directory; *p != '\0'; p++)
13272 while ((*q != '\n') && (*q != '\0'))
13274 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13276 if (IsPathAccessible(filename) != MagickFalse)
13282 Overwrite tile with background color.
13284 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13285 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13286 image_view=AcquireCacheView(image);
13287 (void) GetOneCacheViewVirtualPixel(image_view,0,0,virtual_pixel,
13289 pixel.red=virtual_pixel[RedPixelChannel];
13290 pixel.green=virtual_pixel[GreenPixelChannel];
13291 pixel.blue=virtual_pixel[BluePixelChannel];
13292 pixel.alpha=virtual_pixel[AlphaPixelChannel];
13293 for (i=0; i < (int) height; i++)
13295 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13296 y_offset+i,width,1,exception);
13297 if (s == (Quantum *) NULL)
13299 for (j=0; j < (int) width; j++)
13301 SetPixelInfoPixel(image,&pixel,s);
13302 s+=GetPixelChannels(image);
13304 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13307 image_view=DestroyCacheView(image_view);
13310 windows->image.window_changes.width=(int) image->columns;
13311 windows->image.window_changes.height=(int) image->rows;
13312 XConfigureImageColormap(display,resource_info,windows,image,exception);
13313 (void) XConfigureImage(display,resource_info,windows,image,exception);
13319 XSetCursorState(display,windows,MagickFalse);
13320 return(tile_image);
13324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13328 + X T r a n s l a t e I m a g e %
13332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13334 % XTranslateImage() translates the image within an Image window by one pixel
13335 % as specified by the key symbol. If the image has a `montage string the
13336 % translation is respect to the width and height contained within the string.
13338 % The format of the XTranslateImage method is:
13340 % void XTranslateImage(Display *display,XWindows *windows,
13341 % Image *image,const KeySym key_symbol)
13343 % A description of each parameter follows:
13345 % o display: Specifies a connection to an X server; returned from
13348 % o windows: Specifies a pointer to a XWindows structure.
13350 % o image: the image.
13352 % o key_symbol: Specifies a KeySym which indicates which side of the image
13356 static void XTranslateImage(Display *display,XWindows *windows,
13357 Image *image,const KeySym key_symbol)
13360 text[MaxTextExtent];
13371 User specified a pan position offset.
13373 x_offset=windows->image.width;
13374 y_offset=windows->image.height;
13375 if (image->montage != (char *) NULL)
13376 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13377 switch ((int) key_symbol)
13382 windows->image.x=(int) windows->image.width/2;
13383 windows->image.y=(int) windows->image.height/2;
13389 windows->image.x-=x_offset;
13396 windows->image.y-=y_offset;
13402 windows->image.x+=x_offset;
13409 windows->image.y+=y_offset;
13416 Check boundary conditions.
13418 if (windows->image.x < 0)
13419 windows->image.x=0;
13421 if ((int) (windows->image.x+windows->image.width) >
13422 windows->image.ximage->width)
13423 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13424 if (windows->image.y < 0)
13425 windows->image.y=0;
13427 if ((int) (windows->image.y+windows->image.height) >
13428 windows->image.ximage->height)
13429 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13431 Refresh Image window.
13433 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13434 windows->image.width,windows->image.height,windows->image.x,
13436 XInfoWidget(display,windows,text);
13437 XCheckRefreshWindows(display,windows);
13438 XDrawPanRectangle(display,windows);
13439 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13440 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13448 + X T r i m I m a g e %
13452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13454 % XTrimImage() trims the edges from the Image window.
13456 % The format of the XTrimImage method is:
13458 % MagickBooleanType XTrimImage(Display *display,
13459 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13460 % ExceptionInfo *exception)
13462 % A description of each parameter follows:
13464 % o display: Specifies a connection to an X server; returned from
13467 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13469 % o windows: Specifies a pointer to a XWindows structure.
13471 % o image: the image.
13473 % o exception: return any errors or warnings in this structure.
13476 static MagickBooleanType XTrimImage(Display *display,
13477 XResourceInfo *resource_info,XWindows *windows,Image *image,
13478 ExceptionInfo *exception)
13492 Trim edges from image.
13494 XSetCursorState(display,windows,MagickTrue);
13495 XCheckRefreshWindows(display,windows);
13497 Crop the left edge.
13499 background=XGetPixel(windows->image.ximage,0,0);
13500 trim_info.width=(size_t) windows->image.ximage->width;
13501 for (x=0; x < windows->image.ximage->width; x++)
13503 for (y=0; y < windows->image.ximage->height; y++)
13505 pixel=XGetPixel(windows->image.ximage,x,y);
13506 if (pixel != background)
13509 if (y < windows->image.ximage->height)
13512 trim_info.x=(ssize_t) x;
13513 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13515 XSetCursorState(display,windows,MagickFalse);
13516 return(MagickFalse);
13519 Crop the right edge.
13521 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13522 for (x=windows->image.ximage->width-1; x != 0; x--)
13524 for (y=0; y < windows->image.ximage->height; y++)
13526 pixel=XGetPixel(windows->image.ximage,x,y);
13527 if (pixel != background)
13530 if (y < windows->image.ximage->height)
13533 trim_info.width=(size_t) (x-trim_info.x+1);
13537 background=XGetPixel(windows->image.ximage,0,0);
13538 trim_info.height=(size_t) windows->image.ximage->height;
13539 for (y=0; y < windows->image.ximage->height; y++)
13541 for (x=0; x < windows->image.ximage->width; x++)
13543 pixel=XGetPixel(windows->image.ximage,x,y);
13544 if (pixel != background)
13547 if (x < windows->image.ximage->width)
13550 trim_info.y=(ssize_t) y;
13552 Crop the bottom edge.
13554 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13555 for (y=windows->image.ximage->height-1; y != 0; y--)
13557 for (x=0; x < windows->image.ximage->width; x++)
13559 pixel=XGetPixel(windows->image.ximage,x,y);
13560 if (pixel != background)
13563 if (x < windows->image.ximage->width)
13566 trim_info.height=(size_t) y-trim_info.y+1;
13567 if (((unsigned int) trim_info.width != windows->image.width) ||
13568 ((unsigned int) trim_info.height != windows->image.height))
13571 Reconfigure Image window as defined by the trimming rectangle.
13573 XSetCropGeometry(display,windows,&trim_info,image);
13574 windows->image.window_changes.width=(int) trim_info.width;
13575 windows->image.window_changes.height=(int) trim_info.height;
13576 (void) XConfigureImage(display,resource_info,windows,image,exception);
13578 XSetCursorState(display,windows,MagickFalse);
13579 return(MagickTrue);
13583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13587 + X V i s u a l D i r e c t o r y I m a g e %
13591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13593 % XVisualDirectoryImage() creates a Visual Image Directory.
13595 % The format of the XVisualDirectoryImage method is:
13597 % Image *XVisualDirectoryImage(Display *display,
13598 % XResourceInfo *resource_info,XWindows *windows,
13599 % ExceptionInfo *exception)
13601 % A description of each parameter follows:
13603 % o display: Specifies a connection to an X server; returned from
13606 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13608 % o windows: Specifies a pointer to a XWindows structure.
13610 % o exception: return any errors or warnings in this structure.
13613 static Image *XVisualDirectoryImage(Display *display,
13614 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13616 #define TileImageTag "Scale/Image"
13617 #define XClientName "montage"
13650 filename[MaxTextExtent] = "\0",
13651 filenames[MaxTextExtent] = "*";
13654 background_resources;
13657 Request file name from user.
13659 XFileBrowserWidget(display,windows,"Directory",filenames);
13660 if (*filenames == '\0')
13661 return((Image *) NULL);
13663 Expand the filenames.
13665 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13666 if (filelist == (char **) NULL)
13668 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13670 return((Image *) NULL);
13673 filelist[0]=filenames;
13674 status=ExpandFilenames(&number_files,&filelist);
13675 if ((status == MagickFalse) || (number_files == 0))
13677 if (number_files == 0)
13678 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13680 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13682 return((Image *) NULL);
13685 Set image background resources.
13687 background_resources=(*resource_info);
13688 background_resources.window_id=AcquireString("");
13689 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13690 "0x%lx",windows->image.id);
13691 background_resources.backdrop=MagickTrue;
13693 Read each image and convert them to a tile.
13695 backdrop=(windows->visual_info->klass == TrueColor) ||
13696 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13697 read_info=CloneImageInfo(resource_info->image_info);
13698 (void) SetImageOption(read_info,"jpeg:size","120x120");
13699 (void) CloneString(&read_info->size,DefaultTileGeometry);
13700 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13702 images=NewImageList();
13703 XSetCursorState(display,windows,MagickTrue);
13704 XCheckRefreshWindows(display,windows);
13705 for (i=0; i < (int) number_files; i++)
13707 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13708 filelist[i]=DestroyString(filelist[i]);
13709 *read_info->magick='\0';
13710 next_image=ReadImage(read_info,exception);
13711 CatchException(exception);
13712 if (next_image != (Image *) NULL)
13714 (void) DeleteImageProperty(next_image,"label");
13715 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13716 read_info,next_image,DefaultTileLabel,exception),exception);
13717 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13719 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13720 geometry.height,exception);
13721 if (thumbnail_image != (Image *) NULL)
13723 next_image=DestroyImage(next_image);
13724 next_image=thumbnail_image;
13728 (void) XDisplayBackgroundImage(display,&background_resources,
13729 next_image,exception);
13730 XSetCursorState(display,windows,MagickTrue);
13732 AppendImageToList(&images,next_image);
13733 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13738 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13739 (MagickSizeType) number_files);
13740 if (proceed == MagickFalse)
13745 filelist=(char **) RelinquishMagickMemory(filelist);
13746 if (images == (Image *) NULL)
13748 read_info=DestroyImageInfo(read_info);
13749 XSetCursorState(display,windows,MagickFalse);
13750 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13751 return((Image *) NULL);
13754 Create the Visual Image Directory.
13756 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13757 montage_info->pointsize=10;
13758 if (resource_info->font != (char *) NULL)
13759 (void) CloneString(&montage_info->font,resource_info->font);
13760 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13761 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13762 images),exception);
13763 images=DestroyImageList(images);
13764 montage_info=DestroyMontageInfo(montage_info);
13765 read_info=DestroyImageInfo(read_info);
13766 XSetCursorState(display,windows,MagickFalse);
13767 if (montage_image == (Image *) NULL)
13768 return(montage_image);
13769 XClientMessage(display,windows->image.id,windows->im_protocols,
13770 windows->im_next_image,CurrentTime);
13771 return(montage_image);
13775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13779 % X D i s p l a y B a c k g r o u n d I m a g e %
13783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13785 % XDisplayBackgroundImage() displays an image in the background of a window.
13787 % The format of the XDisplayBackgroundImage method is:
13789 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13790 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13792 % A description of each parameter follows:
13794 % o display: Specifies a connection to an X server; returned from
13797 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13799 % o image: the image.
13801 % o exception: return any errors or warnings in this structure.
13804 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13805 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13808 geometry[MaxTextExtent],
13809 visual_type[MaxTextExtent];
13822 static XStandardColormap
13826 *visual_info = (XVisualInfo *) NULL;
13847 Determine target window.
13849 assert(image != (Image *) NULL);
13850 assert(image->signature == MagickSignature);
13851 if (image->debug != MagickFalse)
13852 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13853 resources=(*resource_info);
13854 window_info.id=(Window) NULL;
13855 root_window=XRootWindow(display,XDefaultScreen(display));
13856 if (LocaleCompare(resources.window_id,"root") == 0)
13857 window_info.id=root_window;
13860 if (isdigit((unsigned char) *resources.window_id) != 0)
13861 window_info.id=XWindowByID(display,root_window,
13862 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13863 if (window_info.id == (Window) NULL)
13864 window_info.id=XWindowByName(display,root_window,resources.window_id);
13866 if (window_info.id == (Window) NULL)
13868 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13869 resources.window_id);
13870 return(MagickFalse);
13873 Determine window visual id.
13875 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13876 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13877 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13878 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13880 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13881 XVisualIDFromVisual(window_attributes.visual));
13882 if (visual_info == (XVisualInfo *) NULL)
13885 Allocate standard colormap.
13887 map_info=XAllocStandardColormap();
13888 if (map_info == (XStandardColormap *) NULL)
13889 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13891 map_info->colormap=(Colormap) NULL;
13892 pixel.pixels=(unsigned long *) NULL;
13894 Initialize visual info.
13896 resources.map_type=(char *) NULL;
13897 resources.visual_type=visual_type;
13898 visual_info=XBestVisualInfo(display,map_info,&resources);
13899 if (visual_info == (XVisualInfo *) NULL)
13900 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13901 resources.visual_type);
13903 Initialize window info.
13905 window_info.ximage=(XImage *) NULL;
13906 window_info.matte_image=(XImage *) NULL;
13907 window_info.pixmap=(Pixmap) NULL;
13908 window_info.matte_pixmap=(Pixmap) NULL;
13911 Free previous root colors.
13913 if (window_info.id == root_window)
13914 (void) XDestroyWindowColors(display,root_window);
13916 Initialize Standard Colormap.
13918 resources.colormap=SharedColormap;
13919 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13922 Graphic context superclass.
13924 context_values.background=pixel.background_color.pixel;
13925 context_values.foreground=pixel.foreground_color.pixel;
13926 pixel.annotate_context=XCreateGC(display,window_info.id,
13927 (size_t) (GCBackground | GCForeground),&context_values);
13928 if (pixel.annotate_context == (GC) NULL)
13929 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13932 Initialize Image window attributes.
13934 window_info.name=AcquireString("\0");
13935 window_info.icon_name=AcquireString("\0");
13936 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13937 &resources,&window_info);
13939 Create the X image.
13941 window_info.width=(unsigned int) image->columns;
13942 window_info.height=(unsigned int) image->rows;
13943 if ((image->columns != window_info.width) ||
13944 (image->rows != window_info.height))
13945 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13947 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13948 window_attributes.width,window_attributes.height);
13949 geometry_info.width=window_info.width;
13950 geometry_info.height=window_info.height;
13951 geometry_info.x=(ssize_t) window_info.x;
13952 geometry_info.y=(ssize_t) window_info.y;
13953 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13954 &geometry_info.width,&geometry_info.height);
13955 window_info.width=(unsigned int) geometry_info.width;
13956 window_info.height=(unsigned int) geometry_info.height;
13957 window_info.x=(int) geometry_info.x;
13958 window_info.y=(int) geometry_info.y;
13959 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13960 window_info.height,exception);
13961 if (status == MagickFalse)
13962 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13966 if (image->debug != MagickFalse)
13968 (void) LogMagickEvent(X11Event,GetMagickModule(),
13969 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13970 (double) image->columns,(double) image->rows);
13971 if (image->colors != 0)
13972 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13974 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13977 Adjust image dimensions as specified by backdrop or geometry options.
13979 width=(int) window_info.width;
13980 height=(int) window_info.height;
13981 if (resources.backdrop != MagickFalse)
13984 Center image on window.
13986 window_info.x=(window_attributes.width/2)-
13987 (window_info.ximage->width/2);
13988 window_info.y=(window_attributes.height/2)-
13989 (window_info.ximage->height/2);
13990 width=window_attributes.width;
13991 height=window_attributes.height;
13993 if ((resources.image_geometry != (char *) NULL) &&
13994 (*resources.image_geometry != '\0'))
13997 default_geometry[MaxTextExtent];
14007 User specified geometry.
14009 size_hints=XAllocSizeHints();
14010 if (size_hints == (XSizeHints *) NULL)
14011 ThrowXWindowFatalException(ResourceLimitFatalError,
14012 "MemoryAllocationFailed",image->filename);
14013 size_hints->flags=0L;
14014 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
14016 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
14017 default_geometry,window_info.border_width,size_hints,&window_info.x,
14018 &window_info.y,&width,&height,&gravity);
14019 if (flags & (XValue | YValue))
14021 width=window_attributes.width;
14022 height=window_attributes.height;
14024 (void) XFree((void *) size_hints);
14027 Create the X pixmap.
14029 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14030 (unsigned int) height,window_info.depth);
14031 if (window_info.pixmap == (Pixmap) NULL)
14032 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14035 Display pixmap on the window.
14037 if (((unsigned int) width > window_info.width) ||
14038 ((unsigned int) height > window_info.height))
14039 (void) XFillRectangle(display,window_info.pixmap,
14040 window_info.annotate_context,0,0,(unsigned int) width,
14041 (unsigned int) height);
14042 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14043 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14044 window_info.width,(unsigned int) window_info.height);
14045 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14046 (void) XClearWindow(display,window_info.id);
14047 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14048 XDelay(display,delay == 0UL ? 10UL : delay);
14049 (void) XSync(display,MagickFalse);
14050 return(window_info.id == root_window ? MagickTrue : MagickFalse);
14054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14058 + X D i s p l a y I m a g e %
14062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14064 % XDisplayImage() displays an image via X11. A new image is created and
14065 % returned if the user interactively transforms the displayed image.
14067 % The format of the XDisplayImage method is:
14069 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14070 % char **argv,int argc,Image **image,size_t *state,
14071 % ExceptionInfo *exception)
14073 % A description of each parameter follows:
14075 % o nexus: Method XDisplayImage returns an image when the
14076 % user chooses 'Open Image' from the command menu or picks a tile
14077 % from the image directory. Otherwise a null image is returned.
14079 % o display: Specifies a connection to an X server; returned from
14082 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14084 % o argv: Specifies the application's argument list.
14086 % o argc: Specifies the number of arguments.
14088 % o image: Specifies an address to an address of an Image structure;
14090 % o exception: return any errors or warnings in this structure.
14093 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14094 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14096 #define MagnifySize 256 /* must be a power of 2 */
14097 #define MagickMenus 10
14098 #define MagickTitle "Commands"
14125 "Visual Directory...",
14171 "Contrast Stretch...",
14172 "Sigmoidal Contrast...",
14206 "Charcoal Draw...",
14220 "Region of Interest...",
14223 *MiscellanyMenu[] =
14238 "Browse Documentation",
14265 **Menus[MagickMenus] =
14303 VisualDirectoryCommand,
14317 OriginalSizeCommand,
14324 TransformCommands[] =
14330 RotateRightCommand,
14337 EnhanceCommands[] =
14345 ContrastStretchCommand,
14346 SigmoidalContrastCommand,
14354 EffectsCommands[] =
14358 ReduceNoiseCommand,
14378 CharcoalDrawCommand
14380 ImageEditCommands[] =
14391 RegionofInterestCommand
14393 MiscellanyCommands[] =
14397 ShowPreviewCommand,
14398 ShowHistogramCommand,
14407 BrowseDocumentationCommand,
14410 ShortCutsCommands[] =
14422 VirtualCommands[] =
14431 *Commands[MagickMenus] =
14441 MiscellanyCommands,
14446 command[MaxTextExtent],
14448 geometry[MaxTextExtent],
14449 resource_name[MaxTextExtent];
14476 working_directory[MaxTextExtent];
14482 *magick_windows[MaxXWindows];
14484 static unsigned int
14544 assert(image != (Image **) NULL);
14545 assert((*image)->signature == MagickSignature);
14546 if ((*image)->debug != MagickFalse)
14547 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14548 display_image=(*image);
14549 warning_handler=(WarningHandler) NULL;
14550 windows=XSetWindows((XWindows *) ~0);
14551 if (windows != (XWindows *) NULL)
14556 status=chdir(working_directory);
14558 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14559 "UnableToOpenFile","%s",working_directory);
14560 warning_handler=resource_info->display_warnings ?
14561 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14562 warning_handler=resource_info->display_warnings ?
14563 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14568 Allocate windows structure.
14570 resource_info->colors=display_image->colors;
14571 windows=XSetWindows(XInitializeWindows(display,resource_info));
14572 if (windows == (XWindows *) NULL)
14573 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14574 (*image)->filename);
14576 Initialize window id's.
14579 magick_windows[number_windows++]=(&windows->icon);
14580 magick_windows[number_windows++]=(&windows->backdrop);
14581 magick_windows[number_windows++]=(&windows->image);
14582 magick_windows[number_windows++]=(&windows->info);
14583 magick_windows[number_windows++]=(&windows->command);
14584 magick_windows[number_windows++]=(&windows->widget);
14585 magick_windows[number_windows++]=(&windows->popup);
14586 magick_windows[number_windows++]=(&windows->magnify);
14587 magick_windows[number_windows++]=(&windows->pan);
14588 for (i=0; i < (int) number_windows; i++)
14589 magick_windows[i]->id=(Window) NULL;
14594 Initialize font info.
14596 if (windows->font_info != (XFontStruct *) NULL)
14597 (void) XFreeFont(display,windows->font_info);
14598 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14599 if (windows->font_info == (XFontStruct *) NULL)
14600 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14601 resource_info->font);
14603 Initialize Standard Colormap.
14605 map_info=windows->map_info;
14606 icon_map=windows->icon_map;
14607 visual_info=windows->visual_info;
14608 icon_visual=windows->icon_visual;
14609 pixel=windows->pixel_info;
14610 icon_pixel=windows->icon_pixel;
14611 font_info=windows->font_info;
14612 icon_resources=windows->icon_resources;
14613 class_hints=windows->class_hints;
14614 manager_hints=windows->manager_hints;
14615 root_window=XRootWindow(display,visual_info->screen);
14616 nexus=NewImageList();
14617 if (display_image->debug != MagickFalse)
14619 (void) LogMagickEvent(X11Event,GetMagickModule(),
14620 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14621 (double) display_image->scene,(double) display_image->columns,
14622 (double) display_image->rows);
14623 if (display_image->colors != 0)
14624 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14625 display_image->colors);
14626 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14627 display_image->magick);
14629 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14630 map_info,pixel,exception);
14631 display_image->taint=MagickFalse;
14633 Initialize graphic context.
14635 windows->context.id=(Window) NULL;
14636 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14637 resource_info,&windows->context);
14638 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14639 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14640 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14641 manager_hints->flags=InputHint | StateHint;
14642 manager_hints->input=MagickFalse;
14643 manager_hints->initial_state=WithdrawnState;
14644 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14645 &windows->context);
14646 if (display_image->debug != MagickFalse)
14647 (void) LogMagickEvent(X11Event,GetMagickModule(),
14648 "Window id: 0x%lx (context)",windows->context.id);
14649 context_values.background=pixel->background_color.pixel;
14650 context_values.font=font_info->fid;
14651 context_values.foreground=pixel->foreground_color.pixel;
14652 context_values.graphics_exposures=MagickFalse;
14653 context_mask=(MagickStatusType)
14654 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14655 if (pixel->annotate_context != (GC) NULL)
14656 (void) XFreeGC(display,pixel->annotate_context);
14657 pixel->annotate_context=XCreateGC(display,windows->context.id,
14658 context_mask,&context_values);
14659 if (pixel->annotate_context == (GC) NULL)
14660 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14661 display_image->filename);
14662 context_values.background=pixel->depth_color.pixel;
14663 if (pixel->widget_context != (GC) NULL)
14664 (void) XFreeGC(display,pixel->widget_context);
14665 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14667 if (pixel->widget_context == (GC) NULL)
14668 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14669 display_image->filename);
14670 context_values.background=pixel->foreground_color.pixel;
14671 context_values.foreground=pixel->background_color.pixel;
14672 context_values.plane_mask=context_values.background ^
14673 context_values.foreground;
14674 if (pixel->highlight_context != (GC) NULL)
14675 (void) XFreeGC(display,pixel->highlight_context);
14676 pixel->highlight_context=XCreateGC(display,windows->context.id,
14677 (size_t) (context_mask | GCPlaneMask),&context_values);
14678 if (pixel->highlight_context == (GC) NULL)
14679 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14680 display_image->filename);
14681 (void) XDestroyWindow(display,windows->context.id);
14683 Initialize icon window.
14685 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14686 icon_resources,&windows->icon);
14687 windows->icon.geometry=resource_info->icon_geometry;
14688 XBestIconSize(display,&windows->icon,display_image);
14689 windows->icon.attributes.colormap=XDefaultColormap(display,
14690 icon_visual->screen);
14691 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14692 manager_hints->flags=InputHint | StateHint;
14693 manager_hints->input=MagickFalse;
14694 manager_hints->initial_state=IconicState;
14695 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14697 if (display_image->debug != MagickFalse)
14698 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14701 Initialize graphic context for icon window.
14703 if (icon_pixel->annotate_context != (GC) NULL)
14704 (void) XFreeGC(display,icon_pixel->annotate_context);
14705 context_values.background=icon_pixel->background_color.pixel;
14706 context_values.foreground=icon_pixel->foreground_color.pixel;
14707 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14708 (size_t) (GCBackground | GCForeground),&context_values);
14709 if (icon_pixel->annotate_context == (GC) NULL)
14710 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14711 display_image->filename);
14712 windows->icon.annotate_context=icon_pixel->annotate_context;
14714 Initialize Image window.
14716 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14718 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14719 if (resource_info->use_shared_memory == MagickFalse)
14720 windows->image.shared_memory=MagickFalse;
14721 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14726 title=InterpretImageProperties(resource_info->image_info,display_image,
14727 resource_info->title,exception);
14728 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14729 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14730 title=DestroyString(title);
14735 filename[MaxTextExtent];
14738 Window name is the base of the filename.
14740 GetPathComponent(display_image->magick_filename,TailPath,filename);
14741 if (display_image->scene == 0)
14742 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14743 "%s: %s",MagickPackageName,filename);
14745 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14746 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14747 (double) display_image->scene,(double) GetImageListLength(
14749 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14751 if (resource_info->immutable)
14752 windows->image.immutable=MagickTrue;
14753 windows->image.use_pixmap=resource_info->use_pixmap;
14754 windows->image.geometry=resource_info->image_geometry;
14755 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14756 XDisplayWidth(display,visual_info->screen),
14757 XDisplayHeight(display,visual_info->screen));
14758 geometry_info.width=display_image->columns;
14759 geometry_info.height=display_image->rows;
14762 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14763 &geometry_info.width,&geometry_info.height);
14764 windows->image.width=(unsigned int) geometry_info.width;
14765 windows->image.height=(unsigned int) geometry_info.height;
14766 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14767 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14768 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14769 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14770 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14771 resource_info,&windows->backdrop);
14772 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14775 Initialize backdrop window.
14777 windows->backdrop.x=0;
14778 windows->backdrop.y=0;
14779 (void) CloneString(&windows->backdrop.name,"Backdrop");
14780 windows->backdrop.flags=(size_t) (USSize | USPosition);
14781 windows->backdrop.width=(unsigned int)
14782 XDisplayWidth(display,visual_info->screen);
14783 windows->backdrop.height=(unsigned int)
14784 XDisplayHeight(display,visual_info->screen);
14785 windows->backdrop.border_width=0;
14786 windows->backdrop.immutable=MagickTrue;
14787 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14789 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14790 StructureNotifyMask;
14791 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14792 manager_hints->icon_window=windows->icon.id;
14793 manager_hints->input=MagickTrue;
14794 manager_hints->initial_state=resource_info->iconic ? IconicState :
14796 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14797 &windows->backdrop);
14798 if (display_image->debug != MagickFalse)
14799 (void) LogMagickEvent(X11Event,GetMagickModule(),
14800 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14801 (void) XMapWindow(display,windows->backdrop.id);
14802 (void) XClearWindow(display,windows->backdrop.id);
14803 if (windows->image.id != (Window) NULL)
14805 (void) XDestroyWindow(display,windows->image.id);
14806 windows->image.id=(Window) NULL;
14809 Position image in the center the backdrop.
14811 windows->image.flags|=USPosition;
14812 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14813 (windows->image.width/2);
14814 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14815 (windows->image.height/2);
14817 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14818 manager_hints->icon_window=windows->icon.id;
14819 manager_hints->input=MagickTrue;
14820 manager_hints->initial_state=resource_info->iconic ? IconicState :
14822 if (windows->group_leader.id != (Window) NULL)
14827 manager_hints->flags|=WindowGroupHint;
14828 manager_hints->window_group=windows->group_leader.id;
14829 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14830 if (display_image->debug != MagickFalse)
14831 (void) LogMagickEvent(X11Event,GetMagickModule(),
14832 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14834 XMakeWindow(display,
14835 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14836 argv,argc,class_hints,manager_hints,&windows->image);
14837 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14838 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14839 if (windows->group_leader.id != (Window) NULL)
14840 (void) XSetTransientForHint(display,windows->image.id,
14841 windows->group_leader.id);
14842 if (display_image->debug != MagickFalse)
14843 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14844 windows->image.id);
14846 Initialize Info widget.
14848 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14850 (void) CloneString(&windows->info.name,"Info");
14851 (void) CloneString(&windows->info.icon_name,"Info");
14852 windows->info.border_width=1;
14855 windows->info.flags|=PPosition;
14856 windows->info.attributes.win_gravity=UnmapGravity;
14857 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14858 StructureNotifyMask;
14859 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14860 manager_hints->input=MagickFalse;
14861 manager_hints->initial_state=NormalState;
14862 manager_hints->window_group=windows->image.id;
14863 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14865 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14866 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14867 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14868 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14869 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14870 if (windows->image.mapped != MagickFalse)
14871 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14872 if (display_image->debug != MagickFalse)
14873 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14876 Initialize Command widget.
14878 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14879 resource_info,&windows->command);
14880 windows->command.data=MagickMenus;
14881 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14882 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14883 resource_info->client_name);
14884 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14885 resource_name,"geometry",(char *) NULL);
14886 (void) CloneString(&windows->command.name,MagickTitle);
14887 windows->command.border_width=0;
14888 windows->command.flags|=PPosition;
14889 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14890 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14891 OwnerGrabButtonMask | StructureNotifyMask;
14892 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14893 manager_hints->input=MagickTrue;
14894 manager_hints->initial_state=NormalState;
14895 manager_hints->window_group=windows->image.id;
14896 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14897 &windows->command);
14898 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14899 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14901 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14902 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14903 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14904 if (windows->command.mapped != MagickFalse)
14905 (void) XMapRaised(display,windows->command.id);
14906 if (display_image->debug != MagickFalse)
14907 (void) LogMagickEvent(X11Event,GetMagickModule(),
14908 "Window id: 0x%lx (command)",windows->command.id);
14910 Initialize Widget window.
14912 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14913 resource_info,&windows->widget);
14914 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14915 resource_info->client_name);
14916 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14917 resource_name,"geometry",(char *) NULL);
14918 windows->widget.border_width=0;
14919 windows->widget.flags|=PPosition;
14920 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14921 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14922 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14923 StructureNotifyMask;
14924 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14925 manager_hints->input=MagickTrue;
14926 manager_hints->initial_state=NormalState;
14927 manager_hints->window_group=windows->image.id;
14928 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14930 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14931 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14932 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14933 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14934 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14935 if (display_image->debug != MagickFalse)
14936 (void) LogMagickEvent(X11Event,GetMagickModule(),
14937 "Window id: 0x%lx (widget)",windows->widget.id);
14939 Initialize popup window.
14941 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14942 resource_info,&windows->popup);
14943 windows->popup.border_width=0;
14944 windows->popup.flags|=PPosition;
14945 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14946 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14947 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14948 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14949 manager_hints->input=MagickTrue;
14950 manager_hints->initial_state=NormalState;
14951 manager_hints->window_group=windows->image.id;
14952 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14954 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14955 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14956 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14957 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14958 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14959 if (display_image->debug != MagickFalse)
14960 (void) LogMagickEvent(X11Event,GetMagickModule(),
14961 "Window id: 0x%lx (pop up)",windows->popup.id);
14963 Initialize Magnify window and cursor.
14965 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14966 resource_info,&windows->magnify);
14967 if (resource_info->use_shared_memory == MagickFalse)
14968 windows->magnify.shared_memory=MagickFalse;
14969 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14970 resource_info->client_name);
14971 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14972 resource_name,"geometry",(char *) NULL);
14973 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14974 resource_info->magnify);
14975 if (windows->magnify.cursor != (Cursor) NULL)
14976 (void) XFreeCursor(display,windows->magnify.cursor);
14977 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14978 map_info->colormap,resource_info->background_color,
14979 resource_info->foreground_color);
14980 if (windows->magnify.cursor == (Cursor) NULL)
14981 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14982 display_image->filename);
14983 windows->magnify.width=MagnifySize;
14984 windows->magnify.height=MagnifySize;
14985 windows->magnify.flags|=PPosition;
14986 windows->magnify.min_width=MagnifySize;
14987 windows->magnify.min_height=MagnifySize;
14988 windows->magnify.width_inc=MagnifySize;
14989 windows->magnify.height_inc=MagnifySize;
14990 windows->magnify.data=resource_info->magnify;
14991 windows->magnify.attributes.cursor=windows->magnify.cursor;
14992 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14993 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14994 StructureNotifyMask;
14995 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14996 manager_hints->input=MagickTrue;
14997 manager_hints->initial_state=NormalState;
14998 manager_hints->window_group=windows->image.id;
14999 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15000 &windows->magnify);
15001 if (display_image->debug != MagickFalse)
15002 (void) LogMagickEvent(X11Event,GetMagickModule(),
15003 "Window id: 0x%lx (magnify)",windows->magnify.id);
15004 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
15006 Initialize panning window.
15008 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
15009 resource_info,&windows->pan);
15010 (void) CloneString(&windows->pan.name,"Pan Icon");
15011 windows->pan.width=windows->icon.width;
15012 windows->pan.height=windows->icon.height;
15013 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
15014 resource_info->client_name);
15015 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
15016 resource_name,"geometry",(char *) NULL);
15017 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
15018 &windows->pan.width,&windows->pan.height);
15019 windows->pan.flags|=PPosition;
15020 windows->pan.immutable=MagickTrue;
15021 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15022 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15023 StructureNotifyMask;
15024 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15025 manager_hints->input=MagickFalse;
15026 manager_hints->initial_state=NormalState;
15027 manager_hints->window_group=windows->image.id;
15028 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15030 if (display_image->debug != MagickFalse)
15031 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15033 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15034 if (windows->info.mapped != MagickFalse)
15035 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15036 if ((windows->image.mapped == MagickFalse) ||
15037 (windows->backdrop.id != (Window) NULL))
15038 (void) XMapWindow(display,windows->image.id);
15040 Set our progress monitor and warning handlers.
15042 if (warning_handler == (WarningHandler) NULL)
15044 warning_handler=resource_info->display_warnings ?
15045 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15046 warning_handler=resource_info->display_warnings ?
15047 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15050 Initialize Image and Magnify X images.
15052 windows->image.x=0;
15053 windows->image.y=0;
15054 windows->magnify.shape=MagickFalse;
15055 width=(unsigned int) display_image->columns;
15056 height=(unsigned int) display_image->rows;
15057 if ((display_image->columns != width) || (display_image->rows != height))
15058 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15059 display_image->filename);
15060 status=XMakeImage(display,resource_info,&windows->image,display_image,
15061 width,height,exception);
15062 if (status == MagickFalse)
15063 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15064 display_image->filename);
15065 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15066 windows->magnify.width,windows->magnify.height,exception);
15067 if (status == MagickFalse)
15068 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15069 display_image->filename);
15070 if (windows->magnify.mapped != MagickFalse)
15071 (void) XMapRaised(display,windows->magnify.id);
15072 if (windows->pan.mapped != MagickFalse)
15073 (void) XMapRaised(display,windows->pan.id);
15074 windows->image.window_changes.width=(int) display_image->columns;
15075 windows->image.window_changes.height=(int) display_image->rows;
15076 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15077 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15078 (void) XSync(display,MagickFalse);
15082 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15083 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15085 if (resource_info->update != MagickFalse)
15091 Determine when file data was last modified.
15093 status=GetPathAttributes(display_image->filename,&attributes);
15094 if (status != MagickFalse)
15095 update_time=attributes.st_mtime;
15097 *state&=(~FormerImageState);
15098 *state&=(~MontageImageState);
15099 *state&=(~NextImageState);
15103 Handle a window event.
15105 if (windows->image.mapped != MagickFalse)
15106 if ((display_image->delay != 0) || (resource_info->update != 0))
15108 if (timer < time((time_t *) NULL))
15110 if (resource_info->update == MagickFalse)
15111 *state|=NextImageState | ExitState;
15118 Determine if image file was modified.
15120 status=GetPathAttributes(display_image->filename,&attributes);
15121 if (status != MagickFalse)
15122 if (update_time != attributes.st_mtime)
15127 (void) FormatLocaleString(
15128 resource_info->image_info->filename,MaxTextExtent,
15129 "%s:%s",display_image->magick,
15130 display_image->filename);
15131 nexus=ReadImage(resource_info->image_info,exception);
15132 if (nexus != (Image *) NULL)
15134 nexus=DestroyImage(nexus);
15135 *state|=NextImageState | ExitState;
15138 delay=display_image->delay/MagickMax(
15139 display_image->ticks_per_second,1L);
15140 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15143 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15146 Do not block if delay > 0.
15148 XDelay(display,SuspendTime << 2);
15152 timestamp=time((time_t *) NULL);
15153 (void) XNextEvent(display,&event);
15154 if (windows->image.stasis == MagickFalse)
15155 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15156 MagickTrue : MagickFalse;
15157 if (windows->magnify.stasis == MagickFalse)
15158 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15159 MagickTrue : MagickFalse;
15160 if (event.xany.window == windows->command.id)
15163 Select a command from the Command widget.
15165 id=XCommandWidget(display,windows,CommandMenu,&event);
15168 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15169 command_type=CommandMenus[id];
15170 if (id < MagickMenus)
15173 Select a command from a pop-up menu.
15175 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15179 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15180 command_type=Commands[id][entry];
15182 if (command_type != NullCommand)
15183 nexus=XMagickCommand(display,resource_info,windows,command_type,
15184 &display_image,exception);
15187 switch (event.type)
15191 if (display_image->debug != MagickFalse)
15192 (void) LogMagickEvent(X11Event,GetMagickModule(),
15193 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15194 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15195 if ((event.xbutton.button == Button3) &&
15196 (event.xbutton.state & Mod1Mask))
15199 Convert Alt-Button3 to Button2.
15201 event.xbutton.button=Button2;
15202 event.xbutton.state&=(~Mod1Mask);
15204 if (event.xbutton.window == windows->backdrop.id)
15206 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15207 event.xbutton.time);
15210 if (event.xbutton.window == windows->image.id)
15212 switch (event.xbutton.button)
15216 if (resource_info->immutable)
15219 Select a command from the Virtual menu.
15221 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15224 nexus=XMagickCommand(display,resource_info,windows,
15225 VirtualCommands[entry],&display_image,exception);
15229 Map/unmap Command widget.
15231 if (windows->command.mapped != MagickFalse)
15232 (void) XWithdrawWindow(display,windows->command.id,
15233 windows->command.screen);
15236 (void) XCommandWidget(display,windows,CommandMenu,
15238 (void) XMapRaised(display,windows->command.id);
15245 User pressed the image magnify button.
15247 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15248 &display_image,exception);
15249 XMagnifyImage(display,windows,&event,exception);
15254 if (resource_info->immutable)
15257 Select a command from the Virtual menu.
15259 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15262 nexus=XMagickCommand(display,resource_info,windows,
15263 VirtualCommands[entry],&display_image,exception);
15266 if (display_image->montage != (char *) NULL)
15269 Open or delete a tile from a visual image directory.
15271 nexus=XTileImage(display,resource_info,windows,
15272 display_image,&event,exception);
15273 if (nexus != (Image *) NULL)
15274 *state|=MontageImageState | NextImageState | ExitState;
15275 vid_info.x=(short int) windows->image.x;
15276 vid_info.y=(short int) windows->image.y;
15280 Select a command from the Short Cuts menu.
15282 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15285 nexus=XMagickCommand(display,resource_info,windows,
15286 ShortCutsCommands[entry],&display_image,exception);
15294 XTranslateImage(display,windows,*image,XK_Up);
15302 XTranslateImage(display,windows,*image,XK_Down);
15310 if (event.xbutton.window == windows->magnify.id)
15330 MagnifyCommands[] =
15343 Select a magnify factor from the pop-up menu.
15345 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15347 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15351 if (event.xbutton.window == windows->pan.id)
15353 switch (event.xbutton.button)
15360 XTranslateImage(display,windows,*image,XK_Up);
15368 XTranslateImage(display,windows,*image,XK_Down);
15373 XPanImage(display,windows,&event,exception);
15379 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15381 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15384 case ButtonRelease:
15386 if (display_image->debug != MagickFalse)
15387 (void) LogMagickEvent(X11Event,GetMagickModule(),
15388 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15389 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15392 case ClientMessage:
15394 if (display_image->debug != MagickFalse)
15395 (void) LogMagickEvent(X11Event,GetMagickModule(),
15396 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15397 event.xclient.message_type,event.xclient.format,(unsigned long)
15398 event.xclient.data.l[0]);
15399 if (event.xclient.message_type == windows->im_protocols)
15401 if (*event.xclient.data.l == (long) windows->im_update_widget)
15403 (void) CloneString(&windows->command.name,MagickTitle);
15404 windows->command.data=MagickMenus;
15405 (void) XCommandWidget(display,windows,CommandMenu,
15409 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15412 Update graphic context and window colormap.
15414 for (i=0; i < (int) number_windows; i++)
15416 if (magick_windows[i]->id == windows->icon.id)
15418 context_values.background=pixel->background_color.pixel;
15419 context_values.foreground=pixel->foreground_color.pixel;
15420 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15421 context_mask,&context_values);
15422 (void) XChangeGC(display,magick_windows[i]->widget_context,
15423 context_mask,&context_values);
15424 context_values.background=pixel->foreground_color.pixel;
15425 context_values.foreground=pixel->background_color.pixel;
15426 context_values.plane_mask=context_values.background ^
15427 context_values.foreground;
15428 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15429 (size_t) (context_mask | GCPlaneMask),
15431 magick_windows[i]->attributes.background_pixel=
15432 pixel->background_color.pixel;
15433 magick_windows[i]->attributes.border_pixel=
15434 pixel->border_color.pixel;
15435 magick_windows[i]->attributes.colormap=map_info->colormap;
15436 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15437 (unsigned long) magick_windows[i]->mask,
15438 &magick_windows[i]->attributes);
15440 if (windows->pan.mapped != MagickFalse)
15442 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15443 windows->pan.pixmap);
15444 (void) XClearWindow(display,windows->pan.id);
15445 XDrawPanRectangle(display,windows);
15447 if (windows->backdrop.id != (Window) NULL)
15448 (void) XInstallColormap(display,map_info->colormap);
15451 if (*event.xclient.data.l == (long) windows->im_former_image)
15453 *state|=FormerImageState | ExitState;
15456 if (*event.xclient.data.l == (long) windows->im_next_image)
15458 *state|=NextImageState | ExitState;
15461 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15463 *state|=RetainColorsState;
15466 if (*event.xclient.data.l == (long) windows->im_exit)
15473 if (event.xclient.message_type == windows->dnd_protocols)
15491 Display image named by the Drag-and-Drop selection.
15493 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15495 selection=XInternAtom(display,"DndSelection",MagickFalse);
15496 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15497 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15498 &length,&after,&data);
15499 if ((status != Success) || (length == 0))
15501 if (*event.xclient.data.l == 2)
15506 (void) CopyMagickString(resource_info->image_info->filename,
15507 (char *) data,MaxTextExtent);
15514 if (strncmp((char *) data, "file:", 5) != 0)
15516 (void) XFree((void *) data);
15519 (void) CopyMagickString(resource_info->image_info->filename,
15520 ((char *) data)+5,MaxTextExtent);
15522 nexus=ReadImage(resource_info->image_info,exception);
15523 CatchException(exception);
15524 if (nexus != (Image *) NULL)
15525 *state|=NextImageState | ExitState;
15526 (void) XFree((void *) data);
15530 If client window delete message, exit.
15532 if (event.xclient.message_type != windows->wm_protocols)
15534 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15536 (void) XWithdrawWindow(display,event.xclient.window,
15537 visual_info->screen);
15538 if (event.xclient.window == windows->image.id)
15543 if (event.xclient.window == windows->pan.id)
15546 Restore original image size when pan window is deleted.
15548 windows->image.window_changes.width=windows->image.ximage->width;
15549 windows->image.window_changes.height=windows->image.ximage->height;
15550 (void) XConfigureImage(display,resource_info,windows,
15551 display_image,exception);
15555 case ConfigureNotify:
15557 if (display_image->debug != MagickFalse)
15558 (void) LogMagickEvent(X11Event,GetMagickModule(),
15559 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15560 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15561 event.xconfigure.y,event.xconfigure.send_event);
15562 if (event.xconfigure.window == windows->image.id)
15565 Image window has a new configuration.
15567 if (event.xconfigure.send_event != 0)
15573 Position the transient windows relative of the Image window.
15575 if (windows->command.geometry == (char *) NULL)
15576 if (windows->command.mapped == MagickFalse)
15578 windows->command.x=event.xconfigure.x-
15579 windows->command.width-25;
15580 windows->command.y=event.xconfigure.y;
15581 XConstrainWindowPosition(display,&windows->command);
15582 window_changes.x=windows->command.x;
15583 window_changes.y=windows->command.y;
15584 (void) XReconfigureWMWindow(display,windows->command.id,
15585 windows->command.screen,(unsigned int) (CWX | CWY),
15588 if (windows->widget.geometry == (char *) NULL)
15589 if (windows->widget.mapped == MagickFalse)
15591 windows->widget.x=event.xconfigure.x+
15592 event.xconfigure.width/10;
15593 windows->widget.y=event.xconfigure.y+
15594 event.xconfigure.height/10;
15595 XConstrainWindowPosition(display,&windows->widget);
15596 window_changes.x=windows->widget.x;
15597 window_changes.y=windows->widget.y;
15598 (void) XReconfigureWMWindow(display,windows->widget.id,
15599 windows->widget.screen,(unsigned int) (CWX | CWY),
15602 if (windows->magnify.geometry == (char *) NULL)
15603 if (windows->magnify.mapped == MagickFalse)
15605 windows->magnify.x=event.xconfigure.x+
15606 event.xconfigure.width+25;
15607 windows->magnify.y=event.xconfigure.y;
15608 XConstrainWindowPosition(display,&windows->magnify);
15609 window_changes.x=windows->magnify.x;
15610 window_changes.y=windows->magnify.y;
15611 (void) XReconfigureWMWindow(display,windows->magnify.id,
15612 windows->magnify.screen,(unsigned int) (CWX | CWY),
15615 if (windows->pan.geometry == (char *) NULL)
15616 if (windows->pan.mapped == MagickFalse)
15618 windows->pan.x=event.xconfigure.x+
15619 event.xconfigure.width+25;
15620 windows->pan.y=event.xconfigure.y+
15621 windows->magnify.height+50;
15622 XConstrainWindowPosition(display,&windows->pan);
15623 window_changes.x=windows->pan.x;
15624 window_changes.y=windows->pan.y;
15625 (void) XReconfigureWMWindow(display,windows->pan.id,
15626 windows->pan.screen,(unsigned int) (CWX | CWY),
15630 if ((event.xconfigure.width == (int) windows->image.width) &&
15631 (event.xconfigure.height == (int) windows->image.height))
15633 windows->image.width=(unsigned int) event.xconfigure.width;
15634 windows->image.height=(unsigned int) event.xconfigure.height;
15635 windows->image.x=0;
15636 windows->image.y=0;
15637 if (display_image->montage != (char *) NULL)
15639 windows->image.x=vid_info.x;
15640 windows->image.y=vid_info.y;
15642 if ((windows->image.mapped != MagickFalse) &&
15643 (windows->image.stasis != MagickFalse))
15646 Update image window configuration.
15648 windows->image.window_changes.width=event.xconfigure.width;
15649 windows->image.window_changes.height=event.xconfigure.height;
15650 (void) XConfigureImage(display,resource_info,windows,
15651 display_image,exception);
15654 Update pan window configuration.
15656 if ((event.xconfigure.width < windows->image.ximage->width) ||
15657 (event.xconfigure.height < windows->image.ximage->height))
15659 (void) XMapRaised(display,windows->pan.id);
15660 XDrawPanRectangle(display,windows);
15663 if (windows->pan.mapped != MagickFalse)
15664 (void) XWithdrawWindow(display,windows->pan.id,
15665 windows->pan.screen);
15668 if (event.xconfigure.window == windows->magnify.id)
15674 Magnify window has a new configuration.
15676 windows->magnify.width=(unsigned int) event.xconfigure.width;
15677 windows->magnify.height=(unsigned int) event.xconfigure.height;
15678 if (windows->magnify.mapped == MagickFalse)
15681 while ((int) magnify <= event.xconfigure.width)
15683 while ((int) magnify <= event.xconfigure.height)
15686 if (((int) magnify != event.xconfigure.width) ||
15687 ((int) magnify != event.xconfigure.height))
15689 window_changes.width=(int) magnify;
15690 window_changes.height=(int) magnify;
15691 (void) XReconfigureWMWindow(display,windows->magnify.id,
15692 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15696 if ((windows->magnify.mapped != MagickFalse) &&
15697 (windows->magnify.stasis != MagickFalse))
15699 status=XMakeImage(display,resource_info,&windows->magnify,
15700 display_image,windows->magnify.width,windows->magnify.height,
15702 XMakeMagnifyImage(display,windows,exception);
15706 if ((windows->magnify.mapped != MagickFalse) &&
15707 (event.xconfigure.window == windows->pan.id))
15710 Pan icon window has a new configuration.
15712 if (event.xconfigure.send_event != 0)
15714 windows->pan.x=event.xconfigure.x;
15715 windows->pan.y=event.xconfigure.y;
15717 windows->pan.width=(unsigned int) event.xconfigure.width;
15718 windows->pan.height=(unsigned int) event.xconfigure.height;
15721 if (event.xconfigure.window == windows->icon.id)
15724 Icon window has a new configuration.
15726 windows->icon.width=(unsigned int) event.xconfigure.width;
15727 windows->icon.height=(unsigned int) event.xconfigure.height;
15732 case DestroyNotify:
15735 Group leader has exited.
15737 if (display_image->debug != MagickFalse)
15738 (void) LogMagickEvent(X11Event,GetMagickModule(),
15739 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15740 if (event.xdestroywindow.window == windows->group_leader.id)
15750 Selectively install colormap.
15752 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15753 if (event.xcrossing.mode != NotifyUngrab)
15754 XInstallColormap(display,map_info->colormap);
15759 if (display_image->debug != MagickFalse)
15760 (void) LogMagickEvent(X11Event,GetMagickModule(),
15761 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15762 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15765 Refresh windows that are now exposed.
15767 if ((event.xexpose.window == windows->image.id) &&
15768 (windows->image.mapped != MagickFalse))
15770 XRefreshWindow(display,&windows->image,&event);
15771 delay=display_image->delay/MagickMax(
15772 display_image->ticks_per_second,1L);
15773 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15776 if ((event.xexpose.window == windows->magnify.id) &&
15777 (windows->magnify.mapped != MagickFalse))
15779 XMakeMagnifyImage(display,windows,exception);
15782 if (event.xexpose.window == windows->pan.id)
15784 XDrawPanRectangle(display,windows);
15787 if (event.xexpose.window == windows->icon.id)
15789 XRefreshWindow(display,&windows->icon,&event);
15800 Respond to a user key press.
15802 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15803 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15804 *(command+length)='\0';
15805 if (display_image->debug != MagickFalse)
15806 (void) LogMagickEvent(X11Event,GetMagickModule(),
15807 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15808 key_symbol,command);
15809 if (event.xkey.window == windows->image.id)
15811 command_type=XImageWindowCommand(display,resource_info,windows,
15812 event.xkey.state,key_symbol,&display_image,exception);
15813 if (command_type != NullCommand)
15814 nexus=XMagickCommand(display,resource_info,windows,command_type,
15815 &display_image,exception);
15817 if (event.xkey.window == windows->magnify.id)
15818 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15820 if (event.xkey.window == windows->pan.id)
15822 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15823 (void) XWithdrawWindow(display,windows->pan.id,
15824 windows->pan.screen);
15826 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15827 XTextViewWidget(display,resource_info,windows,MagickFalse,
15828 "Help Viewer - Image Pan",ImagePanHelp);
15830 XTranslateImage(display,windows,*image,key_symbol);
15832 delay=display_image->delay/MagickMax(
15833 display_image->ticks_per_second,1L);
15834 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15840 Respond to a user key release.
15842 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15843 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15844 if (display_image->debug != MagickFalse)
15845 (void) LogMagickEvent(X11Event,GetMagickModule(),
15846 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15852 Selectively uninstall colormap.
15854 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15855 if (event.xcrossing.mode != NotifyUngrab)
15856 XUninstallColormap(display,map_info->colormap);
15861 if (display_image->debug != MagickFalse)
15862 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15863 event.xmap.window);
15864 if (event.xmap.window == windows->backdrop.id)
15866 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15868 windows->backdrop.mapped=MagickTrue;
15871 if (event.xmap.window == windows->image.id)
15873 if (windows->backdrop.id != (Window) NULL)
15874 (void) XInstallColormap(display,map_info->colormap);
15875 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15877 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15878 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15880 if (((int) windows->image.width < windows->image.ximage->width) ||
15881 ((int) windows->image.height < windows->image.ximage->height))
15882 (void) XMapRaised(display,windows->pan.id);
15883 windows->image.mapped=MagickTrue;
15886 if (event.xmap.window == windows->magnify.id)
15888 XMakeMagnifyImage(display,windows,exception);
15889 windows->magnify.mapped=MagickTrue;
15890 (void) XWithdrawWindow(display,windows->info.id,
15891 windows->info.screen);
15894 if (event.xmap.window == windows->pan.id)
15896 XMakePanImage(display,resource_info,windows,display_image,
15898 windows->pan.mapped=MagickTrue;
15901 if (event.xmap.window == windows->info.id)
15903 windows->info.mapped=MagickTrue;
15906 if (event.xmap.window == windows->icon.id)
15912 Create an icon image.
15914 taint=display_image->taint;
15915 XMakeStandardColormap(display,icon_visual,icon_resources,
15916 display_image,icon_map,icon_pixel,exception);
15917 (void) XMakeImage(display,icon_resources,&windows->icon,
15918 display_image,windows->icon.width,windows->icon.height,
15920 display_image->taint=taint;
15921 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15922 windows->icon.pixmap);
15923 (void) XClearWindow(display,windows->icon.id);
15924 (void) XWithdrawWindow(display,windows->info.id,
15925 windows->info.screen);
15926 windows->icon.mapped=MagickTrue;
15929 if (event.xmap.window == windows->command.id)
15931 windows->command.mapped=MagickTrue;
15934 if (event.xmap.window == windows->popup.id)
15936 windows->popup.mapped=MagickTrue;
15939 if (event.xmap.window == windows->widget.id)
15941 windows->widget.mapped=MagickTrue;
15946 case MappingNotify:
15948 (void) XRefreshKeyboardMapping(&event.xmapping);
15953 case PropertyNotify:
15969 if (display_image->debug != MagickFalse)
15970 (void) LogMagickEvent(X11Event,GetMagickModule(),
15971 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15972 event.xproperty.atom,event.xproperty.state);
15973 if (event.xproperty.atom != windows->im_remote_command)
15976 Display image named by the remote command protocol.
15978 status=XGetWindowProperty(display,event.xproperty.window,
15979 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15980 AnyPropertyType,&type,&format,&length,&after,&data);
15981 if ((status != Success) || (length == 0))
15983 if (LocaleCompare((char *) data,"-quit") == 0)
15985 XClientMessage(display,windows->image.id,windows->im_protocols,
15986 windows->im_exit,CurrentTime);
15987 (void) XFree((void *) data);
15990 (void) CopyMagickString(resource_info->image_info->filename,
15991 (char *) data,MaxTextExtent);
15992 (void) XFree((void *) data);
15993 nexus=ReadImage(resource_info->image_info,exception);
15994 CatchException(exception);
15995 if (nexus != (Image *) NULL)
15996 *state|=NextImageState | ExitState;
15999 case ReparentNotify:
16001 if (display_image->debug != MagickFalse)
16002 (void) LogMagickEvent(X11Event,GetMagickModule(),
16003 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
16004 event.xreparent.window);
16009 if (display_image->debug != MagickFalse)
16010 (void) LogMagickEvent(X11Event,GetMagickModule(),
16011 "Unmap Notify: 0x%lx",event.xunmap.window);
16012 if (event.xunmap.window == windows->backdrop.id)
16014 windows->backdrop.mapped=MagickFalse;
16017 if (event.xunmap.window == windows->image.id)
16019 windows->image.mapped=MagickFalse;
16022 if (event.xunmap.window == windows->magnify.id)
16024 windows->magnify.mapped=MagickFalse;
16027 if (event.xunmap.window == windows->pan.id)
16029 windows->pan.mapped=MagickFalse;
16032 if (event.xunmap.window == windows->info.id)
16034 windows->info.mapped=MagickFalse;
16037 if (event.xunmap.window == windows->icon.id)
16039 if (map_info->colormap == icon_map->colormap)
16040 XConfigureImageColormap(display,resource_info,windows,
16041 display_image,exception);
16042 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16044 windows->icon.mapped=MagickFalse;
16047 if (event.xunmap.window == windows->command.id)
16049 windows->command.mapped=MagickFalse;
16052 if (event.xunmap.window == windows->popup.id)
16054 if (windows->backdrop.id != (Window) NULL)
16055 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16057 windows->popup.mapped=MagickFalse;
16060 if (event.xunmap.window == windows->widget.id)
16062 if (windows->backdrop.id != (Window) NULL)
16063 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16065 windows->widget.mapped=MagickFalse;
16072 if (display_image->debug != MagickFalse)
16073 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16078 } while (!(*state & ExitState));
16079 if ((*state & ExitState) == 0)
16080 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16081 &display_image,exception);
16083 if (resource_info->confirm_edit != MagickFalse)
16086 Query user if image has changed.
16088 if ((resource_info->immutable == MagickFalse) &&
16089 (display_image->taint != MagickFalse))
16094 status=XConfirmWidget(display,windows,"Your image changed.",
16095 "Do you want to save it");
16097 *state&=(~ExitState);
16100 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16101 &display_image,exception);
16104 if ((windows->visual_info->klass == GrayScale) ||
16105 (windows->visual_info->klass == PseudoColor) ||
16106 (windows->visual_info->klass == DirectColor))
16109 Withdraw pan and Magnify window.
16111 if (windows->info.mapped != MagickFalse)
16112 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16113 if (windows->magnify.mapped != MagickFalse)
16114 (void) XWithdrawWindow(display,windows->magnify.id,
16115 windows->magnify.screen);
16116 if (windows->command.mapped != MagickFalse)
16117 (void) XWithdrawWindow(display,windows->command.id,
16118 windows->command.screen);
16120 if (windows->pan.mapped != MagickFalse)
16121 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16122 if (resource_info->backdrop == MagickFalse)
16123 if (windows->backdrop.mapped)
16125 (void) XWithdrawWindow(display,windows->backdrop.id,
16126 windows->backdrop.screen);
16127 (void) XDestroyWindow(display,windows->backdrop.id);
16128 windows->backdrop.id=(Window) NULL;
16129 (void) XWithdrawWindow(display,windows->image.id,
16130 windows->image.screen);
16131 (void) XDestroyWindow(display,windows->image.id);
16132 windows->image.id=(Window) NULL;
16134 XSetCursorState(display,windows,MagickTrue);
16135 XCheckRefreshWindows(display,windows);
16136 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16137 *state&=(~ExitState);
16138 if (*state & ExitState)
16141 Free Standard Colormap.
16143 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16144 if (resource_info->map_type == (char *) NULL)
16145 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16149 if (resource_info->copy_image != (Image *) NULL)
16151 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16152 resource_info->copy_image=NewImageList();
16154 DestroyXResources();
16156 (void) XSync(display,MagickFalse);
16158 Restore our progress monitor and warning handlers.
16160 (void) SetErrorHandler(warning_handler);
16161 (void) SetWarningHandler(warning_handler);
16163 Change to home directory.
16165 directory=getcwd(working_directory,MaxTextExtent);
16171 status=chdir(resource_info->home_directory);
16173 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16174 "UnableToOpenFile","%s",resource_info->home_directory);
16176 *image=display_image;
16182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16186 + D i s p l a y I m a g e s %
16190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16192 % DisplayImages() displays an image sequence to any X window screen. It
16193 % returns a value other than 0 if successful. Check the exception member
16194 % of image to determine the reason for any failure.
16196 % The format of the DisplayImages method is:
16198 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16199 % Image *images,ExceptionInfo *exception)
16201 % A description of each parameter follows:
16203 % o image_info: the image info.
16205 % o image: the image.
16207 % o exception: return any errors or warnings in this structure.
16210 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16211 Image *image,ExceptionInfo *exception)
16213 assert(image_info != (const ImageInfo *) NULL);
16214 assert(image_info->signature == MagickSignature);
16215 assert(image != (Image *) NULL);
16216 assert(image->signature == MagickSignature);
16217 if (image->debug != MagickFalse)
16218 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16219 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16220 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
16221 return(MagickFalse);
16225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16229 + R e m o t e D i s p l a y C o m m a n d %
16233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16235 % RemoteDisplayCommand() encourages a remote display program to display the
16236 % specified image filename.
16238 % The format of the RemoteDisplayCommand method is:
16240 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16241 % const char *window,const char *filename,ExceptionInfo *exception)
16243 % A description of each parameter follows:
16245 % o image_info: the image info.
16247 % o window: Specifies the name or id of an X window.
16249 % o filename: the name of the image filename to display.
16251 % o exception: return any errors or warnings in this structure.
16254 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16255 const char *window,const char *filename,ExceptionInfo *exception)
16257 assert(image_info != (const ImageInfo *) NULL);
16258 assert(image_info->signature == MagickSignature);
16259 assert(filename != (char *) NULL);
16261 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16262 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16263 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename);
16264 return(MagickFalse);