2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % DDDD IIIII SSSSS PPPP L AAA Y Y %
7 % D D I SS P P L A A Y Y %
8 % D D I SSS PPPP L AAAAA Y %
10 % DDDD IIIII SSSSS P LLLLL A A Y %
13 % MagickCore Methods to Interactively Display and Edit an Image %
20 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/artifact.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/cache-private.h"
47 #include "MagickCore/client.h"
48 #include "MagickCore/color.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/composite.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/decorate.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/display.h"
55 #include "MagickCore/display-private.h"
56 #include "MagickCore/distort.h"
57 #include "MagickCore/draw.h"
58 #include "MagickCore/effect.h"
59 #include "MagickCore/enhance.h"
60 #include "MagickCore/exception.h"
61 #include "MagickCore/exception-private.h"
62 #include "MagickCore/fx.h"
63 #include "MagickCore/geometry.h"
64 #include "MagickCore/image.h"
65 #include "MagickCore/image-private.h"
66 #include "MagickCore/list.h"
67 #include "MagickCore/log.h"
68 #include "MagickCore/magick.h"
69 #include "MagickCore/memory_.h"
70 #include "MagickCore/monitor.h"
71 #include "MagickCore/monitor-private.h"
72 #include "MagickCore/montage.h"
73 #include "MagickCore/option.h"
74 #include "MagickCore/paint.h"
75 #include "MagickCore/pixel.h"
76 #include "MagickCore/pixel-accessor.h"
77 #include "MagickCore/PreRvIcccm.h"
78 #include "MagickCore/property.h"
79 #include "MagickCore/quantum.h"
80 #include "MagickCore/quantum-private.h"
81 #include "MagickCore/resize.h"
82 #include "MagickCore/resource_.h"
83 #include "MagickCore/shear.h"
84 #include "MagickCore/segment.h"
85 #include "MagickCore/statistic.h"
86 #include "MagickCore/string_.h"
87 #include "MagickCore/string-private.h"
88 #include "MagickCore/transform.h"
89 #include "MagickCore/threshold.h"
90 #include "MagickCore/utility.h"
91 #include "MagickCore/utility-private.h"
92 #include "MagickCore/version.h"
93 #include "MagickCore/widget.h"
94 #include "MagickCore/widget-private.h"
95 #include "MagickCore/xwindow.h"
96 #include "MagickCore/xwindow-private.h"
98 #if defined(MAGICKCORE_X11_DELEGATE)
102 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
105 Constant declarations.
107 static const unsigned char
110 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
114 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
142 Help widget declarations.
145 *ImageAnnotateHelp[] =
147 "In annotate mode, the Command widget has these options:",
197 "Choose a font name from the Font Name sub-menu. Additional",
198 "font names can be specified with the font browser. You can",
199 "change the menu names by setting the X resources font1",
202 "Choose a font color from the Font Color sub-menu.",
203 "Additional font colors can be specified with the color",
204 "browser. You can change the menu colors by setting the X",
205 "resources pen1 through pen9.",
207 "If you select the color browser and press Grab, you can",
208 "choose the font color by moving the pointer to the desired",
209 "color on the screen and press any button.",
211 "If you choose to rotate the text, choose Rotate Text from the",
212 "menu and select an angle. Typically you will only want to",
213 "rotate one line of text at a time. Depending on the angle you",
214 "choose, subsequent lines may end up overwriting each other.",
216 "Choosing a font and its color is optional. The default font",
217 "is fixed and the default color is black. However, you must",
218 "choose a location to begin entering text and press button 1.",
219 "An underscore character will appear at the location of the",
220 "pointer. The cursor changes to a pencil to indicate you are",
221 "in text mode. To exit immediately, press Dismiss.",
223 "In text mode, any key presses will display the character at",
224 "the location of the underscore and advance the underscore",
225 "cursor. Enter your text and once completed press Apply to",
226 "finish your image annotation. To correct errors press BACK",
227 "SPACE. To delete an entire line of text, press DELETE. Any",
228 "text that exceeds the boundaries of the image window is",
229 "automagically continued onto the next line.",
231 "The actual color you request for the font is saved in the",
232 "image. However, the color that appears in your image window",
233 "may be different. For example, on a monochrome screen the",
234 "text will appear black or white even if you choose the color",
235 "red as the font color. However, the image saved to a file",
236 "with -write is written with red lettering. To assure the",
237 "correct color text in the final image, any PseudoClass image",
238 "is promoted to DirectClass (see miff(5)). To force a",
239 "PseudoClass image to remain PseudoClass, use -colors.",
244 "In chop mode, the Command widget has these options:",
252 "If the you choose the horizontal direction (this the",
253 "default), the area of the image between the two horizontal",
254 "endpoints of the chop line is removed. Otherwise, the area",
255 "of the image between the two vertical endpoints of the chop",
258 "Select a location within the image window to begin your chop,",
259 "press and hold any button. Next, move the pointer to",
260 "another location in the image. As you move a line will",
261 "connect the initial location and the pointer. When you",
262 "release the button, the area within the image to chop is",
263 "determined by which direction you choose from the Command",
266 "To cancel the image chopping, move the pointer back to the",
267 "starting point of the line and release the button.",
270 *ImageColorEditHelp[] =
272 "In color edit mode, the Command widget has these options:",
313 "Choose a color editing method from the Method sub-menu",
314 "of the Command widget. The point method recolors any pixel",
315 "selected with the pointer until the button is released. The",
316 "replace method recolors any pixel that matches the color of",
317 "the pixel you select with a button press. Floodfill recolors",
318 "any pixel that matches the color of the pixel you select with",
319 "a button press and is a neighbor. Whereas filltoborder recolors",
320 "any neighbor pixel that is not the border color. Finally reset",
321 "changes the entire image to the designated color.",
323 "Next, choose a pixel color from the Pixel Color sub-menu.",
324 "Additional pixel colors can be specified with the color",
325 "browser. You can change the menu colors by setting the X",
326 "resources pen1 through pen9.",
328 "Now press button 1 to select a pixel within the image window",
329 "to change its color. Additional pixels may be recolored as",
330 "prescribed by the method you choose.",
332 "If the Magnify widget is mapped, it can be helpful in positioning",
333 "your pointer within the image (refer to button 2).",
335 "The actual color you request for the pixels is saved in the",
336 "image. However, the color that appears in your image window",
337 "may be different. For example, on a monochrome screen the",
338 "pixel will appear black or white even if you choose the",
339 "color red as the pixel color. However, the image saved to a",
340 "file with -write is written with red pixels. To assure the",
341 "correct color text in the final image, any PseudoClass image",
342 "is promoted to DirectClass (see miff(5)). To force a",
343 "PseudoClass image to remain PseudoClass, use -colors.",
346 *ImageCompositeHelp[] =
348 "First a widget window is displayed requesting you to enter an",
349 "image name. Press Composite, Grab or type a file name.",
350 "Press Cancel if you choose not to create a composite image.",
351 "When you choose Grab, move the pointer to the desired window",
352 "and press any button.",
354 "If the Composite image does not have any matte information,",
355 "you are informed and the file browser is displayed again.",
356 "Enter the name of a mask image. The image is typically",
357 "grayscale and the same size as the composite image. If the",
358 "image is not grayscale, it is converted to grayscale and the",
359 "resulting intensities are used as matte information.",
361 "A small window appears showing the location of the cursor in",
362 "the image window. You are now in composite mode. To exit",
363 "immediately, press Dismiss. In composite mode, the Command",
364 "widget has these options:",
390 "Choose a composite operation from the Operators sub-menu of",
391 "the Command widget. How each operator behaves is described",
392 "below. Image window is the image currently displayed on",
393 "your X server and image is the image obtained with the File",
396 "Over The result is the union of the two image shapes,",
397 " with image obscuring image window in the region of",
400 "In The result is simply image cut by the shape of",
401 " image window. None of the image data of image",
402 " window is in the result.",
404 "Out The resulting image is image with the shape of",
405 " image window cut out.",
407 "Atop The result is the same shape as image image window,",
408 " with image obscuring image window where the image",
409 " shapes overlap. Note this differs from over",
410 " because the portion of image outside image window's",
411 " shape does not appear in the result.",
413 "Xor The result is the image data from both image and",
414 " image window that is outside the overlap region.",
415 " The overlap region is blank.",
417 "Plus The result is just the sum of the image data.",
418 " Output values are cropped to QuantumRange (no overflow).",
420 "Minus The result of image - image window, with underflow",
423 "Add The result of image + image window, with overflow",
424 " wrapping around (mod 256).",
426 "Subtract The result of image - image window, with underflow",
427 " wrapping around (mod 256). The add and subtract",
428 " operators can be used to perform reversible",
432 " The result of abs(image - image window). This",
433 " useful for comparing two very similar images.",
436 " The result of image * image window. This",
437 " useful for the creation of drop-shadows.",
439 "Bumpmap The result of surface normals from image * image",
442 "Copy The resulting image is image window replaced with",
443 " image. Here the matte information is ignored.",
445 "CopyRed The red layer of the image window is replace with",
446 " the red layer of the image. The other layers are",
450 " The green layer of the image window is replace with",
451 " the green layer of the image. The other layers are",
454 "CopyBlue The blue layer of the image window is replace with",
455 " the blue layer of the image. The other layers are",
459 " The matte layer of the image window is replace with",
460 " the matte layer of the image. The other layers are",
463 "The image compositor requires a matte, or alpha channel in",
464 "the image for some operations. This extra channel usually",
465 "defines a mask which represents a sort of a cookie-cutter",
466 "for the image. This the case when matte is opaque (full",
467 "coverage) for pixels inside the shape, zero outside, and",
468 "between 0 and QuantumRange on the boundary. If image does not",
469 "have a matte channel, it is initialized with 0 for any pixel",
470 "matching in color to pixel location (0,0), otherwise QuantumRange.",
472 "If you choose Dissolve, the composite operator becomes Over. The",
473 "image matte channel percent transparency is initialized to factor.",
474 "The image window is initialized to (100-factor). Where factor is the",
475 "value you specify in the Dialog widget.",
477 "Displace shifts the image pixels as defined by a displacement",
478 "map. With this option, image is used as a displacement map.",
479 "Black, within the displacement map, is a maximum positive",
480 "displacement. White is a maximum negative displacement and",
481 "middle gray is neutral. The displacement is scaled to determine",
482 "the pixel shift. By default, the displacement applies in both the",
483 "horizontal and vertical directions. However, if you specify a mask,",
484 "image is the horizontal X displacement and mask the vertical Y",
487 "Note that matte information for image window is not retained",
488 "for colormapped X server visuals (e.g. StaticColor,",
489 "StaticColor, GrayScale, PseudoColor). Correct compositing",
490 "behavior may require a TrueColor or DirectColor visual or a",
491 "Standard Colormap.",
493 "Choosing a composite operator is optional. The default",
494 "operator is replace. However, you must choose a location to",
495 "composite your image and press button 1. Press and hold the",
496 "button before releasing and an outline of the image will",
497 "appear to help you identify your location.",
499 "The actual colors of the composite image is saved. However,",
500 "the color that appears in image window may be different.",
501 "For example, on a monochrome screen image window will appear",
502 "black or white even though your composited image may have",
503 "many colors. If the image is saved to a file it is written",
504 "with the correct colors. To assure the correct colors are",
505 "saved in the final image, any PseudoClass image is promoted",
506 "to DirectClass (see miff(5)). To force a PseudoClass image",
507 "to remain PseudoClass, use -colors.",
512 "In cut mode, the Command widget has these options:",
517 "To define a cut region, press button 1 and drag. The",
518 "cut region is defined by a highlighted rectangle that",
519 "expands or contracts as it follows the pointer. Once you",
520 "are satisfied with the cut region, release the button.",
521 "You are now in rectify mode. In rectify mode, the Command",
522 "widget has these options:",
528 "You can make adjustments by moving the pointer to one of the",
529 "cut rectangle corners, pressing a button, and dragging.",
530 "Finally, press Cut to commit your copy region. To",
531 "exit without cutting the image, press Dismiss.",
536 "In copy mode, the Command widget has these options:",
541 "To define a copy region, press button 1 and drag. The",
542 "copy region is defined by a highlighted rectangle that",
543 "expands or contracts as it follows the pointer. Once you",
544 "are satisfied with the copy region, release the button.",
545 "You are now in rectify mode. In rectify mode, the Command",
546 "widget has these options:",
552 "You can make adjustments by moving the pointer to one of the",
553 "copy rectangle corners, pressing a button, and dragging.",
554 "Finally, press Copy to commit your copy region. To",
555 "exit without copying the image, press Dismiss.",
560 "In crop mode, the Command widget has these options:",
565 "To define a cropping region, press button 1 and drag. The",
566 "cropping region is defined by a highlighted rectangle that",
567 "expands or contracts as it follows the pointer. Once you",
568 "are satisfied with the cropping region, release the button.",
569 "You are now in rectify mode. In rectify mode, the Command",
570 "widget has these options:",
576 "You can make adjustments by moving the pointer to one of the",
577 "cropping rectangle corners, pressing a button, and dragging.",
578 "Finally, press Crop to commit your cropping region. To",
579 "exit without cropping the image, press Dismiss.",
584 "The cursor changes to a crosshair to indicate you are in",
585 "draw mode. To exit immediately, press Dismiss. In draw mode,",
586 "the Command widget has these options:",
631 "Choose a drawing primitive from the Element sub-menu.",
633 "Choose a color from the Color sub-menu. Additional",
634 "colors can be specified with the color browser.",
636 "If you choose the color browser and press Grab, you can",
637 "select the color by moving the pointer to the desired",
638 "color on the screen and press any button. The transparent",
639 "color updates the image matte channel and is useful for",
640 "image compositing.",
642 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
643 "Additional stipples can be specified with the file browser.",
644 "Stipples obtained from the file browser must be on disk in the",
645 "X11 bitmap format.",
647 "Choose a width, if appropriate, from the Width sub-menu. To",
648 "choose a specific width select the Dialog widget.",
650 "Choose a point in the Image window and press button 1 and",
651 "hold. Next, move the pointer to another location in the",
652 "image. As you move, a line connects the initial location and",
653 "the pointer. When you release the button, the image is",
654 "updated with the primitive you just drew. For polygons, the",
655 "image is updated when you press and release the button without",
656 "moving the pointer.",
658 "To cancel image drawing, move the pointer back to the",
659 "starting point of the line and release the button.",
665 " The effects of each button press is described below. Three",
666 " buttons are required. If you have a two button mouse,",
667 " button 1 and 3 are returned. Press ALT and button 3 to",
668 " simulate button 2.",
670 " 1 Press this button to map or unmap the Command widget.",
672 " 2 Press and drag to define a region of the image to",
675 " 3 Press and drag to choose from a select set of commands.",
676 " This button behaves differently if the image being",
677 " displayed is a visual image directory. Here, choose a",
678 " particular tile of the directory and press this button and",
679 " drag to select a command from a pop-up menu. Choose from",
680 " these menu items:",
688 " If you choose Open, the image represented by the tile is",
689 " displayed. To return to the visual image directory, choose",
690 " Next from the Command widget. Next and Former moves to the",
691 " next or former image respectively. Choose Delete to delete",
692 " a particular image tile. Finally, choose Update to",
693 " synchronize all the image tiles with their respective",
697 " The Command widget lists a number of sub-menus and commands.",
709 " Visual Directory...",
743 " Contrast Stretch...",
744 " Sigmoidal Contrast...",
772 " Charcoal Drawing...",
783 " Region of Interest...",
795 " Browse Documentation",
798 " Menu items with a indented triangle have a sub-menu. They",
799 " are represented above as the indented items. To access a",
800 " sub-menu item, move the pointer to the appropriate menu and",
801 " press a button and drag. When you find the desired sub-menu",
802 " item, release the button and the command is executed. Move",
803 " the pointer away from the sub-menu if you decide not to",
804 " execute a particular command.",
806 "KEYBOARD ACCELERATORS",
807 " Accelerators are one or two key presses that effect a",
808 " particular command. The keyboard accelerators that",
809 " display(1) understands is:",
811 " Ctl+O Press to open an image from a file.",
813 " space Press to display the next image.",
815 " If the image is a multi-paged document such as a Postscript",
816 " document, you can skip ahead several pages by preceding",
817 " this command with a number. For example to display the",
818 " third page beyond the current page, press 3<space>.",
820 " backspace Press to display the former image.",
822 " If the image is a multi-paged document such as a Postscript",
823 " document, you can skip behind several pages by preceding",
824 " this command with a number. For example to display the",
825 " third page preceding the current page, press 3<backspace>.",
827 " Ctl+S Press to write the image to a file.",
829 " Ctl+P Press to print the image to a Postscript printer.",
831 " Ctl+D Press to delete an image file.",
833 " Ctl+N Press to create a blank canvas.",
835 " Ctl+Q Press to discard all images and exit program.",
837 " Ctl+Z Press to undo last image transformation.",
839 " Ctl+R Press to redo last image transformation.",
841 " Ctl+X Press to cut a region of the image.",
843 " Ctl+C Press to copy a region of the image.",
845 " Ctl+V Press to paste a region to the image.",
847 " < Press to half the image size.",
849 " - Press to return to the original image size.",
851 " > Press to double the image size.",
853 " % Press to resize the image to a width and height you",
856 "Cmd-A Press to make any image transformations permanent."
858 " By default, any image size transformations are applied",
859 " to the original image to create the image displayed on",
860 " the X server. However, the transformations are not",
861 " permanent (i.e. the original image does not change",
862 " size only the X image does). For example, if you",
863 " press > the X image will appear to double in size,",
864 " but the original image will in fact remain the same size.",
865 " To force the original image to double in size, press >",
866 " followed by Cmd-A.",
868 " @ Press to refresh the image window.",
870 " C Press to cut out a rectangular region of the image.",
872 " [ Press to chop the image.",
874 " H Press to flop image in the horizontal direction.",
876 " V Press to flip image in the vertical direction.",
878 " / Press to rotate the image 90 degrees clockwise.",
880 " \\ Press to rotate the image 90 degrees counter-clockwise.",
882 " * Press to rotate the image the number of degrees you",
885 " S Press to shear the image the number of degrees you",
888 " R Press to roll the image.",
890 " T Press to trim the image edges.",
892 " Shft-H Press to vary the image hue.",
894 " Shft-S Press to vary the color saturation.",
896 " Shft-L Press to vary the color brightness.",
898 " Shft-G Press to gamma correct the image.",
900 " Shft-C Press to sharpen the image contrast.",
902 " Shft-Z Press to dull the image contrast.",
904 " = Press to perform histogram equalization on the image.",
906 " Shft-N Press to perform histogram normalization on the image.",
908 " Shft-~ Press to negate the colors of the image.",
910 " . Press to convert the image colors to gray.",
912 " Shft-# Press to set the maximum number of unique colors in the",
915 " F2 Press to reduce the speckles in an image.",
917 " F3 Press to eliminate peak noise from an image.",
919 " F4 Press to add noise to an image.",
921 " F5 Press to sharpen an image.",
923 " F6 Press to delete an image file.",
925 " F7 Press to threshold the image.",
927 " F8 Press to detect edges within an image.",
929 " F9 Press to emboss an image.",
931 " F10 Press to displace pixels by a random amount.",
933 " F11 Press to negate all pixels above the threshold level.",
935 " F12 Press to shade the image using a distant light source.",
937 " F13 Press to lighten or darken image edges to create a 3-D effect.",
939 " F14 Press to segment the image by color.",
941 " Meta-S Press to swirl image pixels about the center.",
943 " Meta-I Press to implode image pixels about the center.",
945 " Meta-W Press to alter an image along a sine wave.",
947 " Meta-P Press to simulate an oil painting.",
949 " Meta-C Press to simulate a charcoal drawing.",
951 " Alt-A Press to annotate the image with text.",
953 " Alt-D Press to draw on an image.",
955 " Alt-P Press to edit an image pixel color.",
957 " Alt-M Press to edit the image matte information.",
959 " Alt-V Press to composite the image with another.",
961 " Alt-B Press to add a border to the image.",
963 " Alt-F Press to add an ornamental border to the image.",
966 " Press to add an image comment.",
968 " Ctl-A Press to apply image processing techniques to a region",
971 " Shft-? Press to display information about the image.",
973 " Shft-+ Press to map the zoom image window.",
975 " Shft-P Press to preview an image enhancement, effect, or f/x.",
977 " F1 Press to display helpful information about display(1).",
979 " Find Press to browse documentation about ImageMagick.",
981 " 1-9 Press to change the level of magnification.",
983 " Use the arrow keys to move the image one pixel up, down,",
984 " left, or right within the magnify window. Be sure to first",
985 " map the magnify window by pressing button 2.",
987 " Press ALT and one of the arrow keys to trim off one pixel",
988 " from any side of the image.",
991 *ImageMatteEditHelp[] =
993 "Matte information within an image is useful for some",
994 "operations such as image compositing (See IMAGE",
995 "COMPOSITING). This extra channel usually defines a mask",
996 "which represents a sort of a cookie-cutter for the image.",
997 "This the case when matte is opaque (full coverage) for",
998 "pixels inside the shape, zero outside, and between 0 and",
999 "QuantumRange on the boundary.",
1001 "A small window appears showing the location of the cursor in",
1002 "the image window. You are now in matte edit mode. To exit",
1003 "immediately, press Dismiss. In matte edit mode, the Command",
1004 "widget has these options:",
1038 "Choose a matte editing method from the Method sub-menu of",
1039 "the Command widget. The point method changes the matte value",
1040 "of any pixel selected with the pointer until the button is",
1041 "is released. The replace method changes the matte value of",
1042 "any pixel that matches the color of the pixel you select with",
1043 "a button press. Floodfill changes the matte value of any pixel",
1044 "that matches the color of the pixel you select with a button",
1045 "press and is a neighbor. Whereas filltoborder changes the matte",
1046 "value any neighbor pixel that is not the border color. Finally",
1047 "reset changes the entire image to the designated matte value.",
1049 "Choose Matte Value and pick Opaque or Transarent. For other values",
1050 "select the Dialog entry. Here a dialog appears requesting a matte",
1051 "value. The value you select is assigned as the opacity value of the",
1052 "selected pixel or pixels.",
1054 "Now, press any button to select a pixel within the image",
1055 "window to change its matte value.",
1057 "If the Magnify widget is mapped, it can be helpful in positioning",
1058 "your pointer within the image (refer to button 2).",
1060 "Matte information is only valid in a DirectClass image.",
1061 "Therefore, any PseudoClass image is promoted to DirectClass",
1062 "(see miff(5)). Note that matte information for PseudoClass",
1063 "is not retained for colormapped X server visuals (e.g.",
1064 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1065 "immediately save your image to a file (refer to Write).",
1066 "Correct matte editing behavior may require a TrueColor or",
1067 "DirectColor visual or a Standard Colormap.",
1072 "When an image exceeds the width or height of the X server",
1073 "screen, display maps a small panning icon. The rectangle",
1074 "within the panning icon shows the area that is currently",
1075 "displayed in the image window. To pan about the image,",
1076 "press any button and drag the pointer within the panning",
1077 "icon. The pan rectangle moves with the pointer and the",
1078 "image window is updated to reflect the location of the",
1079 "rectangle within the panning icon. When you have selected",
1080 "the area of the image you wish to view, release the button.",
1082 "Use the arrow keys to pan the image one pixel up, down,",
1083 "left, or right within the image window.",
1085 "The panning icon is withdrawn if the image becomes smaller",
1086 "than the dimensions of the X server screen.",
1091 "A small window appears showing the location of the cursor in",
1092 "the image window. You are now in paste mode. To exit",
1093 "immediately, press Dismiss. In paste mode, the Command",
1094 "widget has these options:",
1111 "Choose a composite operation from the Operators sub-menu of",
1112 "the Command widget. How each operator behaves is described",
1113 "below. Image window is the image currently displayed on",
1114 "your X server and image is the image obtained with the File",
1117 "Over The result is the union of the two image shapes,",
1118 " with image obscuring image window in the region of",
1121 "In The result is simply image cut by the shape of",
1122 " image window. None of the image data of image",
1123 " window is in the result.",
1125 "Out The resulting image is image with the shape of",
1126 " image window cut out.",
1128 "Atop The result is the same shape as image image window,",
1129 " with image obscuring image window where the image",
1130 " shapes overlap. Note this differs from over",
1131 " because the portion of image outside image window's",
1132 " shape does not appear in the result.",
1134 "Xor The result is the image data from both image and",
1135 " image window that is outside the overlap region.",
1136 " The overlap region is blank.",
1138 "Plus The result is just the sum of the image data.",
1139 " Output values are cropped to QuantumRange (no overflow).",
1140 " This operation is independent of the matte",
1143 "Minus The result of image - image window, with underflow",
1144 " cropped to zero.",
1146 "Add The result of image + image window, with overflow",
1147 " wrapping around (mod 256).",
1149 "Subtract The result of image - image window, with underflow",
1150 " wrapping around (mod 256). The add and subtract",
1151 " operators can be used to perform reversible",
1152 " transformations.",
1155 " The result of abs(image - image window). This",
1156 " useful for comparing two very similar images.",
1158 "Copy The resulting image is image window replaced with",
1159 " image. Here the matte information is ignored.",
1161 "CopyRed The red layer of the image window is replace with",
1162 " the red layer of the image. The other layers are",
1166 " The green layer of the image window is replace with",
1167 " the green layer of the image. The other layers are",
1170 "CopyBlue The blue layer of the image window is replace with",
1171 " the blue layer of the image. The other layers are",
1175 " The matte layer of the image window is replace with",
1176 " the matte layer of the image. The other layers are",
1179 "The image compositor requires a matte, or alpha channel in",
1180 "the image for some operations. This extra channel usually",
1181 "defines a mask which represents a sort of a cookie-cutter",
1182 "for the image. This the case when matte is opaque (full",
1183 "coverage) for pixels inside the shape, zero outside, and",
1184 "between 0 and QuantumRange on the boundary. If image does not",
1185 "have a matte channel, it is initialized with 0 for any pixel",
1186 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1188 "Note that matte information for image window is not retained",
1189 "for colormapped X server visuals (e.g. StaticColor,",
1190 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1191 "behavior may require a TrueColor or DirectColor visual or a",
1192 "Standard Colormap.",
1194 "Choosing a composite operator is optional. The default",
1195 "operator is replace. However, you must choose a location to",
1196 "paste your image and press button 1. Press and hold the",
1197 "button before releasing and an outline of the image will",
1198 "appear to help you identify your location.",
1200 "The actual colors of the pasted image is saved. However,",
1201 "the color that appears in image window may be different.",
1202 "For example, on a monochrome screen image window will appear",
1203 "black or white even though your pasted image may have",
1204 "many colors. If the image is saved to a file it is written",
1205 "with the correct colors. To assure the correct colors are",
1206 "saved in the final image, any PseudoClass image is promoted",
1207 "to DirectClass (see miff(5)). To force a PseudoClass image",
1208 "to remain PseudoClass, use -colors.",
1213 "In region of interest mode, the Command widget has these",
1219 "To define a region of interest, press button 1 and drag.",
1220 "The region of interest is defined by a highlighted rectangle",
1221 "that expands or contracts as it follows the pointer. Once",
1222 "you are satisfied with the region of interest, release the",
1223 "button. You are now in apply mode. In apply mode the",
1224 "Command widget has these options:",
1244 " Contrast Stretch",
1245 " Sigmoidal Contrast...",
1272 " Charcoal Drawing...",
1282 "You can make adjustments to the region of interest by moving",
1283 "the pointer to one of the rectangle corners, pressing a",
1284 "button, and dragging. Finally, choose an image processing",
1285 "technique from the Command widget. You can choose more than",
1286 "one image processing technique to apply to an area.",
1287 "Alternatively, you can move the region of interest before",
1288 "applying another image processing technique. To exit, press",
1292 *ImageRotateHelp[] =
1294 "In rotate mode, the Command widget has these options:",
1313 "Choose a background color from the Pixel Color sub-menu.",
1314 "Additional background colors can be specified with the color",
1315 "browser. You can change the menu colors by setting the X",
1316 "resources pen1 through pen9.",
1318 "If you choose the color browser and press Grab, you can",
1319 "select the background color by moving the pointer to the",
1320 "desired color on the screen and press any button.",
1322 "Choose a point in the image window and press this button and",
1323 "hold. Next, move the pointer to another location in the",
1324 "image. As you move a line connects the initial location and",
1325 "the pointer. When you release the button, the degree of",
1326 "image rotation is determined by the slope of the line you",
1327 "just drew. The slope is relative to the direction you",
1328 "choose from the Direction sub-menu of the Command widget.",
1330 "To cancel the image rotation, move the pointer back to the",
1331 "starting point of the line and release the button.",
1336 Enumeration declarations.
1355 VisualDirectoryCommand,
1363 OriginalSizeCommand,
1385 ContrastStretchCommand,
1386 SigmoidalContrastCommand,
1412 CharcoalDrawCommand,
1422 RegionofInterestCommand,
1428 ShowHistogramCommand,
1434 BrowseDocumentationCommand,
1436 SaveToUndoBufferCommand,
1443 AnnotateNameCommand,
1444 AnnotateFontColorCommand,
1445 AnnotateBackgroundColorCommand,
1446 AnnotateRotateCommand,
1447 AnnotateHelpCommand,
1448 AnnotateDismissCommand,
1451 ChopDirectionCommand,
1454 HorizontalChopCommand,
1455 VerticalChopCommand,
1456 ColorEditMethodCommand,
1457 ColorEditColorCommand,
1458 ColorEditBorderCommand,
1459 ColorEditFuzzCommand,
1460 ColorEditUndoCommand,
1461 ColorEditHelpCommand,
1462 ColorEditDismissCommand,
1463 CompositeOperatorsCommand,
1464 CompositeDissolveCommand,
1465 CompositeDisplaceCommand,
1466 CompositeHelpCommand,
1467 CompositeDismissCommand,
1472 RectifyDismissCommand,
1481 MatteEditBorderCommand,
1482 MatteEditFuzzCommand,
1483 MatteEditValueCommand,
1484 MatteEditUndoCommand,
1485 MatteEditHelpCommand,
1486 MatteEditDismissCommand,
1487 PasteOperatorsCommand,
1489 PasteDismissCommand,
1491 RotateDirectionCommand,
1493 RotateSharpenCommand,
1495 RotateDismissCommand,
1496 HorizontalRotateCommand,
1497 VerticalRotateCommand,
1508 #define BricksWidth 20
1509 #define BricksHeight 20
1510 #define DiagonalWidth 16
1511 #define DiagonalHeight 16
1512 #define HighlightWidth 8
1513 #define HighlightHeight 8
1514 #define OpaqueWidth 8
1515 #define OpaqueHeight 8
1516 #define ScalesWidth 16
1517 #define ScalesHeight 16
1518 #define ShadowWidth 8
1519 #define ShadowHeight 8
1520 #define VerticalWidth 16
1521 #define VerticalHeight 16
1522 #define WavyWidth 16
1523 #define WavyHeight 16
1526 Constant declaration.
1531 static const unsigned char
1534 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1535 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1536 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1537 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1538 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1542 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1543 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1544 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1548 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1549 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1550 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1554 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1555 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1556 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1560 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1561 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1562 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1566 Function prototypes.
1569 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1570 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1573 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1574 Image **,ExceptionInfo *),
1575 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1576 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1578 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1581 static MagickBooleanType
1582 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1584 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1586 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1588 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1590 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1592 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1594 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1595 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1597 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1599 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1600 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1601 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1603 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1604 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1605 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1608 XDrawPanRectangle(Display *,XWindows *),
1609 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1611 XMagnifyImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1612 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1613 XPanImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1614 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1615 const KeySym,ExceptionInfo *),
1616 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1617 XScreenEvent(Display *,XWindows *,XEvent *,ExceptionInfo *),
1618 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1625 % D i s p l a y I m a g e s %
1629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1631 % DisplayImages() displays an image sequence to any X window screen. It
1632 % returns a value other than 0 if successful. Check the exception member
1633 % of image to determine the reason for any failure.
1635 % The format of the DisplayImages method is:
1637 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1638 % Image *images,ExceptionInfo *exception)
1640 % A description of each parameter follows:
1642 % o image_info: the image info.
1644 % o image: the image.
1646 % o exception: return any errors or warnings in this structure.
1649 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1650 Image *images,ExceptionInfo *exception)
1673 assert(image_info != (const ImageInfo *) NULL);
1674 assert(image_info->signature == MagickSignature);
1675 assert(images != (Image *) NULL);
1676 assert(images->signature == MagickSignature);
1677 if (images->debug != MagickFalse)
1678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1679 display=XOpenDisplay(image_info->server_name);
1680 if (display == (Display *) NULL)
1682 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1683 "UnableToOpenXServer","'%s'",XDisplayName(image_info->server_name));
1684 return(MagickFalse);
1686 if (exception->severity != UndefinedException)
1687 CatchException(exception);
1688 (void) XSetErrorHandler(XError);
1689 resource_database=XGetResourceDatabase(display,GetClientName());
1690 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1691 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1692 if (image_info->page != (char *) NULL)
1693 resource_info.image_geometry=AcquireString(image_info->page);
1694 resource_info.immutable=MagickTrue;
1695 argv[0]=AcquireString(GetClientName());
1697 for (i=0; (state & ExitState) == 0; i++)
1699 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1701 image=GetImageFromList(images,i % GetImageListLength(images));
1702 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1704 (void) SetErrorHandler((ErrorHandler) NULL);
1705 (void) SetWarningHandler((WarningHandler) NULL);
1706 argv[0]=DestroyString(argv[0]);
1707 (void) XCloseDisplay(display);
1708 XDestroyResourceInfo(&resource_info);
1709 if (exception->severity != UndefinedException)
1710 return(MagickFalse);
1715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1719 % R e m o t e D i s p l a y C o m m a n d %
1723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 % RemoteDisplayCommand() encourages a remote display program to display the
1726 % specified image filename.
1728 % The format of the RemoteDisplayCommand method is:
1730 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1731 % const char *window,const char *filename,ExceptionInfo *exception)
1733 % A description of each parameter follows:
1735 % o image_info: the image info.
1737 % o window: Specifies the name or id of an X window.
1739 % o filename: the name of the image filename to display.
1741 % o exception: return any errors or warnings in this structure.
1744 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1745 const char *window,const char *filename,ExceptionInfo *exception)
1753 assert(image_info != (const ImageInfo *) NULL);
1754 assert(image_info->signature == MagickSignature);
1755 assert(filename != (char *) NULL);
1756 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1757 display=XOpenDisplay(image_info->server_name);
1758 if (display == (Display *) NULL)
1760 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1761 "UnableToOpenXServer","'%s'",XDisplayName(image_info->server_name));
1762 return(MagickFalse);
1764 (void) XSetErrorHandler(XError);
1765 status=XRemoteCommand(display,window,filename);
1766 (void) XCloseDisplay(display);
1767 return(status != 0 ? MagickTrue : MagickFalse);
1771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775 + X A n n o t a t e E d i t I m a g e %
1779 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781 % XAnnotateEditImage() annotates the image with text.
1783 % The format of the XAnnotateEditImage method is:
1785 % MagickBooleanType XAnnotateEditImage(Display *display,
1786 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1787 % ExceptionInfo *exception)
1789 % A description of each parameter follows:
1791 % o display: Specifies a connection to an X server; returned from
1794 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1796 % o windows: Specifies a pointer to a XWindows structure.
1798 % o image: the image; returned from ReadImage.
1802 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
1809 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
1816 static MagickBooleanType XAnnotateEditImage(Display *display,
1817 XResourceInfo *resource_info,XWindows *windows,Image *image,
1818 ExceptionInfo *exception)
1838 static const ModeType
1839 AnnotateCommands[] =
1841 AnnotateNameCommand,
1842 AnnotateFontColorCommand,
1843 AnnotateBackgroundColorCommand,
1844 AnnotateRotateCommand,
1845 AnnotateHelpCommand,
1846 AnnotateDismissCommand
1854 static MagickBooleanType
1855 transparent_box = MagickTrue,
1856 transparent_pen = MagickFalse;
1858 static MagickRealType
1862 box_id = MaxNumberPens-2,
1867 command[MaxTextExtent],
1868 text[MaxTextExtent];
1871 *ColorMenu[MaxNumberPens+1];
1919 (void) CloneString(&windows->command.name,"Annotate");
1920 windows->command.data=4;
1921 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1922 (void) XMapRaised(display,windows->command.id);
1923 XClientMessage(display,windows->image.id,windows->im_protocols,
1924 windows->im_update_widget,CurrentTime);
1926 Track pointer until button 1 is pressed.
1928 XQueryPosition(display,windows->image.id,&x,&y);
1929 (void) XSelectInput(display,windows->image.id,
1930 windows->image.attributes.event_mask | PointerMotionMask);
1931 cursor=XCreateFontCursor(display,XC_left_side);
1932 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1936 if (windows->info.mapped != MagickFalse)
1939 Display pointer position.
1941 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
1942 x+windows->image.x,y+windows->image.y);
1943 XInfoWidget(display,windows,text);
1946 Wait for next event.
1948 XScreenEvent(display,windows,&event,exception);
1949 if (event.xany.window == windows->command.id)
1952 Select a command from the Command widget.
1954 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1955 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1958 switch (AnnotateCommands[id])
1960 case AnnotateNameCommand:
1963 *FontMenu[MaxNumberFonts];
1969 Initialize menu selections.
1971 for (i=0; i < MaxNumberFonts; i++)
1972 FontMenu[i]=resource_info->font_name[i];
1973 FontMenu[MaxNumberFonts-2]="Browser...";
1974 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1976 Select a font name from the pop-up menu.
1978 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1979 (const char **) FontMenu,command);
1980 if (font_number < 0)
1982 if (font_number == (MaxNumberFonts-2))
1985 font_name[MaxTextExtent] = "fixed";
1988 Select a font name from a browser.
1990 resource_info->font_name[font_number]=font_name;
1991 XFontBrowserWidget(display,windows,"Select",font_name);
1992 if (*font_name == '\0')
1996 Initialize font info.
1998 font_info=XLoadQueryFont(display,resource_info->font_name[
2000 if (font_info == (XFontStruct *) NULL)
2002 XNoticeWidget(display,windows,"Unable to load font:",
2003 resource_info->font_name[font_number]);
2006 font_id=(unsigned int) font_number;
2007 (void) XFreeFont(display,font_info);
2010 case AnnotateFontColorCommand:
2013 Initialize menu selections.
2015 for (i=0; i < (int) (MaxNumberPens-2); i++)
2016 ColorMenu[i]=resource_info->pen_colors[i];
2017 ColorMenu[MaxNumberPens-2]="transparent";
2018 ColorMenu[MaxNumberPens-1]="Browser...";
2019 ColorMenu[MaxNumberPens]=(const char *) NULL;
2021 Select a pen color from the pop-up menu.
2023 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2024 (const char **) ColorMenu,command);
2027 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2029 if (transparent_pen != MagickFalse)
2031 if (pen_number == (MaxNumberPens-1))
2034 color_name[MaxTextExtent] = "gray";
2037 Select a pen color from a dialog.
2039 resource_info->pen_colors[pen_number]=color_name;
2040 XColorBrowserWidget(display,windows,"Select",color_name);
2041 if (*color_name == '\0')
2047 (void) XParseColor(display,windows->map_info->colormap,
2048 resource_info->pen_colors[pen_number],&color);
2049 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2050 (unsigned int) MaxColors,&color);
2051 windows->pixel_info->pen_colors[pen_number]=color;
2052 pen_id=(unsigned int) pen_number;
2055 case AnnotateBackgroundColorCommand:
2058 Initialize menu selections.
2060 for (i=0; i < (int) (MaxNumberPens-2); i++)
2061 ColorMenu[i]=resource_info->pen_colors[i];
2062 ColorMenu[MaxNumberPens-2]="transparent";
2063 ColorMenu[MaxNumberPens-1]="Browser...";
2064 ColorMenu[MaxNumberPens]=(const char *) NULL;
2066 Select a pen color from the pop-up menu.
2068 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2069 (const char **) ColorMenu,command);
2072 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2074 if (transparent_box != MagickFalse)
2076 if (pen_number == (MaxNumberPens-1))
2079 color_name[MaxTextExtent] = "gray";
2082 Select a pen color from a dialog.
2084 resource_info->pen_colors[pen_number]=color_name;
2085 XColorBrowserWidget(display,windows,"Select",color_name);
2086 if (*color_name == '\0')
2092 (void) XParseColor(display,windows->map_info->colormap,
2093 resource_info->pen_colors[pen_number],&color);
2094 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2095 (unsigned int) MaxColors,&color);
2096 windows->pixel_info->pen_colors[pen_number]=color;
2097 box_id=(unsigned int) pen_number;
2100 case AnnotateRotateCommand:
2106 angle[MaxTextExtent] = "30.0";
2124 Select a command from the pop-up menu.
2126 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2132 degrees=StringToDouble(RotateMenu[entry],(char **) NULL);
2135 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2139 degrees=StringToDouble(angle,(char **) NULL);
2142 case AnnotateHelpCommand:
2144 XTextViewWidget(display,resource_info,windows,MagickFalse,
2145 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2148 case AnnotateDismissCommand:
2166 if (event.xbutton.button != Button1)
2168 if (event.xbutton.window != windows->image.id)
2171 Change to text entering mode.
2184 if (event.xkey.window != windows->image.id)
2187 Respond to a user key press.
2189 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2190 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2191 switch ((int) key_symbol)
2206 XTextViewWidget(display,resource_info,windows,MagickFalse,
2207 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2212 (void) XBell(display,0);
2221 Map and unmap Info widget as cursor crosses its boundaries.
2225 if (windows->info.mapped != MagickFalse)
2227 if ((x < (int) (windows->info.x+windows->info.width)) &&
2228 (y < (int) (windows->info.y+windows->info.height)))
2229 (void) XWithdrawWindow(display,windows->info.id,
2230 windows->info.screen);
2233 if ((x > (int) (windows->info.x+windows->info.width)) ||
2234 (y > (int) (windows->info.y+windows->info.height)))
2235 (void) XMapWindow(display,windows->info.id);
2241 } while ((state & ExitState) == 0);
2242 (void) XSelectInput(display,windows->image.id,
2243 windows->image.attributes.event_mask);
2244 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2245 if ((state & EscapeState) != 0)
2248 Set font info and check boundary conditions.
2250 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2251 if (font_info == (XFontStruct *) NULL)
2253 XNoticeWidget(display,windows,"Unable to load font:",
2254 resource_info->font_name[font_id]);
2255 font_info=windows->font_info;
2257 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2258 x=(int) windows->image.width-font_info->max_bounds.width;
2259 if (y < (int) (font_info->ascent+font_info->descent))
2260 y=(int) font_info->ascent+font_info->descent;
2261 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2262 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2263 return(MagickFalse);
2265 Initialize annotate structure.
2267 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2268 if (annotate_info == (XAnnotateInfo *) NULL)
2269 return(MagickFalse);
2270 XGetAnnotateInfo(annotate_info);
2273 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
2274 annotate_info->stencil=OpaqueStencil;
2276 if (transparent_box == MagickFalse)
2277 annotate_info->stencil=BackgroundStencil;
2279 annotate_info->stencil=ForegroundStencil;
2280 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2281 annotate_info->degrees=degrees;
2282 annotate_info->font_info=font_info;
2283 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2284 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2285 sizeof(*annotate_info->text));
2286 if (annotate_info->text == (char *) NULL)
2287 return(MagickFalse);
2289 Create cursor and set graphic context.
2291 cursor=XCreateFontCursor(display,XC_pencil);
2292 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2293 annotate_context=windows->image.annotate_context;
2294 (void) XSetFont(display,annotate_context,font_info->fid);
2295 (void) XSetBackground(display,annotate_context,
2296 windows->pixel_info->pen_colors[box_id].pixel);
2297 (void) XSetForeground(display,annotate_context,
2298 windows->pixel_info->pen_colors[pen_id].pixel);
2300 Begin annotating the image with text.
2302 (void) CloneString(&windows->command.name,"Text");
2303 windows->command.data=0;
2304 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2306 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2307 text_event.xexpose.width=(int) font_info->max_bounds.width;
2308 text_event.xexpose.height=font_info->max_bounds.ascent+
2309 font_info->max_bounds.descent;
2310 p=annotate_info->text;
2314 Display text cursor.
2317 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2319 Wait for next event.
2321 XScreenEvent(display,windows,&event,exception);
2322 if (event.xany.window == windows->command.id)
2325 Select a command from the Command widget.
2327 (void) XSetBackground(display,annotate_context,
2328 windows->pixel_info->background_color.pixel);
2329 (void) XSetForeground(display,annotate_context,
2330 windows->pixel_info->foreground_color.pixel);
2331 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2332 (void) XSetBackground(display,annotate_context,
2333 windows->pixel_info->pen_colors[box_id].pixel);
2334 (void) XSetForeground(display,annotate_context,
2335 windows->pixel_info->pen_colors[pen_id].pixel);
2338 switch (TextCommands[id])
2340 case TextHelpCommand:
2342 XTextViewWidget(display,resource_info,windows,MagickFalse,
2343 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2344 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2347 case TextApplyCommand:
2350 Finished annotating.
2352 annotate_info->width=(unsigned int) XTextWidth(font_info,
2353 annotate_info->text,(int) strlen(annotate_info->text));
2354 XRefreshWindow(display,&windows->image,&text_event);
2366 text_event.xexpose.x=x;
2367 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2368 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2369 (unsigned int) text_event.xexpose.width,(unsigned int)
2370 text_event.xexpose.height,MagickFalse);
2371 XRefreshWindow(display,&windows->image,&text_event);
2376 if (event.xbutton.window != windows->image.id)
2378 if (event.xbutton.button == Button2)
2381 Request primary selection.
2383 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2384 windows->image.id,CurrentTime);
2391 if (event.xexpose.count == 0)
2397 Refresh Image window.
2399 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2400 text_info=annotate_info;
2401 while (text_info != (XAnnotateInfo *) NULL)
2403 if (annotate_info->stencil == ForegroundStencil)
2404 (void) XDrawString(display,windows->image.id,annotate_context,
2405 text_info->x,text_info->y,text_info->text,
2406 (int) strlen(text_info->text));
2408 (void) XDrawImageString(display,windows->image.id,
2409 annotate_context,text_info->x,text_info->y,text_info->text,
2410 (int) strlen(text_info->text));
2411 text_info=text_info->previous;
2413 (void) XDrawString(display,windows->image.id,annotate_context,
2423 if (event.xkey.window != windows->image.id)
2426 Respond to a user key press.
2428 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2429 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2430 *(command+length)='\0';
2431 if (((event.xkey.state & ControlMask) != 0) ||
2432 ((event.xkey.state & Mod1Mask) != 0))
2433 state|=ModifierState;
2434 if ((state & ModifierState) != 0)
2435 switch ((int) key_symbol)
2440 key_symbol=DeleteCommand;
2446 switch ((int) key_symbol)
2451 Erase one character.
2453 if (p == annotate_info->text)
2455 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2460 Go to end of the previous line of text.
2462 annotate_info=annotate_info->previous;
2463 p=annotate_info->text;
2464 x=annotate_info->x+annotate_info->width;
2466 if (annotate_info->width != 0)
2467 p+=strlen(annotate_info->text);
2472 x-=XTextWidth(font_info,p,1);
2473 text_event.xexpose.x=x;
2474 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2475 XRefreshWindow(display,&windows->image,&text_event);
2478 case XK_bracketleft:
2480 key_symbol=XK_Escape;
2486 Erase the entire line of text.
2488 while (p != annotate_info->text)
2491 x-=XTextWidth(font_info,p,1);
2492 text_event.xexpose.x=x;
2493 XRefreshWindow(display,&windows->image,&text_event);
2501 Finished annotating.
2503 annotate_info->width=(unsigned int) XTextWidth(font_info,
2504 annotate_info->text,(int) strlen(annotate_info->text));
2505 XRefreshWindow(display,&windows->image,&text_event);
2512 Draw a single character on the Image window.
2514 if ((state & ModifierState) != 0)
2516 if (*command == '\0')
2519 if (annotate_info->stencil == ForegroundStencil)
2520 (void) XDrawString(display,windows->image.id,annotate_context,
2523 (void) XDrawImageString(display,windows->image.id,
2524 annotate_context,x,y,p,1);
2525 x+=XTextWidth(font_info,p,1);
2527 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2534 Advance to the next line of text.
2537 annotate_info->width=(unsigned int) XTextWidth(font_info,
2538 annotate_info->text,(int) strlen(annotate_info->text));
2539 if (annotate_info->next != (XAnnotateInfo *) NULL)
2542 Line of text already exists.
2544 annotate_info=annotate_info->next;
2547 p=annotate_info->text;
2550 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2551 sizeof(*annotate_info->next));
2552 if (annotate_info->next == (XAnnotateInfo *) NULL)
2553 return(MagickFalse);
2554 *annotate_info->next=(*annotate_info);
2555 annotate_info->next->previous=annotate_info;
2556 annotate_info=annotate_info->next;
2557 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2558 windows->image.width/MagickMax((ssize_t)
2559 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2560 if (annotate_info->text == (char *) NULL)
2561 return(MagickFalse);
2562 annotate_info->y+=annotate_info->height;
2563 if (annotate_info->y > (int) windows->image.height)
2564 annotate_info->y=(int) annotate_info->height;
2565 annotate_info->next=(XAnnotateInfo *) NULL;
2568 p=annotate_info->text;
2577 Respond to a user key release.
2579 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2580 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2581 state&=(~ModifierState);
2584 case SelectionNotify:
2600 Obtain response from primary selection.
2602 if (event.xselection.property == (Atom) None)
2604 status=XGetWindowProperty(display,event.xselection.requestor,
2605 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2606 &type,&format,&length,&after,&data);
2607 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2611 Annotate Image window with primary selection.
2613 for (i=0; i < (ssize_t) length; i++)
2615 if ((char) data[i] != '\n')
2618 Draw a single character on the Image window.
2621 (void) XDrawString(display,windows->image.id,annotate_context,
2623 x+=XTextWidth(font_info,p,1);
2625 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2629 Advance to the next line of text.
2632 annotate_info->width=(unsigned int) XTextWidth(font_info,
2633 annotate_info->text,(int) strlen(annotate_info->text));
2634 if (annotate_info->next != (XAnnotateInfo *) NULL)
2637 Line of text already exists.
2639 annotate_info=annotate_info->next;
2642 p=annotate_info->text;
2645 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2646 sizeof(*annotate_info->next));
2647 if (annotate_info->next == (XAnnotateInfo *) NULL)
2648 return(MagickFalse);
2649 *annotate_info->next=(*annotate_info);
2650 annotate_info->next->previous=annotate_info;
2651 annotate_info=annotate_info->next;
2652 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2653 windows->image.width/MagickMax((ssize_t)
2654 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2655 if (annotate_info->text == (char *) NULL)
2656 return(MagickFalse);
2657 annotate_info->y+=annotate_info->height;
2658 if (annotate_info->y > (int) windows->image.height)
2659 annotate_info->y=(int) annotate_info->height;
2660 annotate_info->next=(XAnnotateInfo *) NULL;
2663 p=annotate_info->text;
2665 (void) XFree((void *) data);
2671 } while ((state & ExitState) == 0);
2672 (void) XFreeCursor(display,cursor);
2674 Annotation is relative to image configuration.
2676 width=(unsigned int) image->columns;
2677 height=(unsigned int) image->rows;
2680 if (windows->image.crop_geometry != (char *) NULL)
2681 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2683 Initialize annotated image.
2685 XSetCursorState(display,windows,MagickTrue);
2686 XCheckRefreshWindows(display,windows);
2687 while (annotate_info != (XAnnotateInfo *) NULL)
2689 if (annotate_info->width == 0)
2692 No text on this line-- go to the next line of text.
2694 previous_info=annotate_info->previous;
2695 annotate_info->text=(char *)
2696 RelinquishMagickMemory(annotate_info->text);
2697 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2698 annotate_info=previous_info;
2702 Determine pixel index for box and pen color.
2704 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2705 if (windows->pixel_info->colors != 0)
2706 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2707 if (windows->pixel_info->pixels[i] ==
2708 windows->pixel_info->pen_colors[box_id].pixel)
2710 windows->pixel_info->box_index=(unsigned short) i;
2713 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2714 if (windows->pixel_info->colors != 0)
2715 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2716 if (windows->pixel_info->pixels[i] ==
2717 windows->pixel_info->pen_colors[pen_id].pixel)
2719 windows->pixel_info->pen_index=(unsigned short) i;
2723 Define the annotate geometry string.
2725 annotate_info->x=(int)
2726 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2727 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2728 windows->image.y)/windows->image.ximage->height;
2729 (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent,
2730 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2731 height*annotate_info->height/windows->image.ximage->height,
2732 annotate_info->x+x,annotate_info->y+y);
2734 Annotate image with text.
2736 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image,
2739 return(MagickFalse);
2743 previous_info=annotate_info->previous;
2744 annotate_info->text=DestroyString(annotate_info->text);
2745 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2746 annotate_info=previous_info;
2748 (void) XSetForeground(display,annotate_context,
2749 windows->pixel_info->foreground_color.pixel);
2750 (void) XSetBackground(display,annotate_context,
2751 windows->pixel_info->background_color.pixel);
2752 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2753 XSetCursorState(display,windows,MagickFalse);
2754 (void) XFreeFont(display,font_info);
2756 Update image configuration.
2758 XConfigureImageColormap(display,resource_info,windows,image,exception);
2759 (void) XConfigureImage(display,resource_info,windows,image,exception);
2764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2768 + X B a c k g r o u n d I m a g e %
2772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2774 % XBackgroundImage() displays the image in the background of a window.
2776 % The format of the XBackgroundImage method is:
2778 % MagickBooleanType XBackgroundImage(Display *display,
2779 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2780 % ExceptionInfo *exception)
2782 % A description of each parameter follows:
2784 % o display: Specifies a connection to an X server; returned from
2787 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2789 % o windows: Specifies a pointer to a XWindows structure.
2791 % o image: the image.
2793 % o exception: return any errors or warnings in this structure.
2796 static MagickBooleanType XBackgroundImage(Display *display,
2797 XResourceInfo *resource_info,XWindows *windows,Image **image,
2798 ExceptionInfo *exception)
2800 #define BackgroundImageTag "Background/Image"
2806 window_id[MaxTextExtent] = "root";
2809 background_resources;
2812 Put image in background.
2814 status=XDialogWidget(display,windows,"Background",
2815 "Enter window id (id 0x00 selects window with pointer):",window_id);
2816 if (*window_id == '\0')
2817 return(MagickFalse);
2818 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2820 XInfoWidget(display,windows,BackgroundImageTag);
2821 XSetCursorState(display,windows,MagickTrue);
2822 XCheckRefreshWindows(display,windows);
2823 background_resources=(*resource_info);
2824 background_resources.window_id=window_id;
2825 background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse;
2826 status=XDisplayBackgroundImage(display,&background_resources,*image,
2828 if (status != MagickFalse)
2829 XClientMessage(display,windows->image.id,windows->im_protocols,
2830 windows->im_retain_colors,CurrentTime);
2831 XSetCursorState(display,windows,MagickFalse);
2832 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2842 + X C h o p I m a g e %
2846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2848 % XChopImage() chops the X image.
2850 % The format of the XChopImage method is:
2852 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2853 % XWindows *windows,Image **image,ExceptionInfo *exception)
2855 % A description of each parameter follows:
2857 % o display: Specifies a connection to an X server; returned from
2860 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2862 % o windows: Specifies a pointer to a XWindows structure.
2864 % o image: the image.
2866 % o exception: return any errors or warnings in this structure.
2869 static MagickBooleanType XChopImage(Display *display,
2870 XResourceInfo *resource_info,XWindows *windows,Image **image,
2871 ExceptionInfo *exception)
2883 direction = HorizontalChopCommand;
2885 static const ModeType
2888 ChopDirectionCommand,
2892 DirectionCommands[] =
2894 HorizontalChopCommand,
2899 text[MaxTextExtent];
2932 (void) CloneString(&windows->command.name,"Chop");
2933 windows->command.data=1;
2934 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2935 (void) XMapRaised(display,windows->command.id);
2936 XClientMessage(display,windows->image.id,windows->im_protocols,
2937 windows->im_update_widget,CurrentTime);
2939 Track pointer until button 1 is pressed.
2941 XQueryPosition(display,windows->image.id,&x,&y);
2942 (void) XSelectInput(display,windows->image.id,
2943 windows->image.attributes.event_mask | PointerMotionMask);
2947 if (windows->info.mapped != MagickFalse)
2950 Display pointer position.
2952 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
2953 x+windows->image.x,y+windows->image.y);
2954 XInfoWidget(display,windows,text);
2957 Wait for next event.
2959 XScreenEvent(display,windows,&event,exception);
2960 if (event.xany.window == windows->command.id)
2963 Select a command from the Command widget.
2965 id=XCommandWidget(display,windows,ChopMenu,&event);
2968 switch (ChopCommands[id])
2970 case ChopDirectionCommand:
2973 command[MaxTextExtent];
2984 Select a command from the pop-up menu.
2986 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2988 direction=DirectionCommands[id];
2991 case ChopHelpCommand:
2993 XTextViewWidget(display,resource_info,windows,MagickFalse,
2994 "Help Viewer - Image Chop",ImageChopHelp);
2997 case ChopDismissCommand:
3015 if (event.xbutton.button != Button1)
3017 if (event.xbutton.window != windows->image.id)
3020 User has committed to start point of chopping line.
3022 segment_info.x1=(short int) event.xbutton.x;
3023 segment_info.x2=(short int) event.xbutton.x;
3024 segment_info.y1=(short int) event.xbutton.y;
3025 segment_info.y2=(short int) event.xbutton.y;
3036 command[MaxTextExtent];
3041 if (event.xkey.window != windows->image.id)
3044 Respond to a user key press.
3046 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3047 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3048 switch ((int) key_symbol)
3063 (void) XSetFunction(display,windows->image.highlight_context,
3065 XTextViewWidget(display,resource_info,windows,MagickFalse,
3066 "Help Viewer - Image Chop",ImageChopHelp);
3067 (void) XSetFunction(display,windows->image.highlight_context,
3073 (void) XBell(display,0);
3082 Map and unmap Info widget as text cursor crosses its boundaries.
3086 if (windows->info.mapped != MagickFalse)
3088 if ((x < (int) (windows->info.x+windows->info.width)) &&
3089 (y < (int) (windows->info.y+windows->info.height)))
3090 (void) XWithdrawWindow(display,windows->info.id,
3091 windows->info.screen);
3094 if ((x > (int) (windows->info.x+windows->info.width)) ||
3095 (y > (int) (windows->info.y+windows->info.height)))
3096 (void) XMapWindow(display,windows->info.id);
3099 } while ((state & ExitState) == 0);
3100 (void) XSelectInput(display,windows->image.id,
3101 windows->image.attributes.event_mask);
3102 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3103 if ((state & EscapeState) != 0)
3106 Draw line as pointer moves until the mouse button is released.
3113 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3120 Display info and draw chopping line.
3122 if (windows->info.mapped == MagickFalse)
3123 (void) XMapWindow(display,windows->info.id);
3124 (void) FormatLocaleString(text,MaxTextExtent,
3125 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3126 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3127 XInfoWidget(display,windows,text);
3128 XHighlightLine(display,windows->image.id,
3129 windows->image.highlight_context,&segment_info);
3132 if (windows->info.mapped != MagickFalse)
3133 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3135 Wait for next event.
3137 XScreenEvent(display,windows,&event,exception);
3139 XHighlightLine(display,windows->image.id,
3140 windows->image.highlight_context,&segment_info);
3145 segment_info.x2=(short int) event.xmotion.x;
3146 segment_info.y2=(short int) event.xmotion.y;
3152 User has committed to chopping line.
3154 segment_info.x2=(short int) event.xbutton.x;
3155 segment_info.y2=(short int) event.xbutton.y;
3163 segment_info.x2=(short int) event.xmotion.x;
3164 segment_info.y2=(short int) event.xmotion.y;
3170 Check boundary conditions.
3172 if (segment_info.x2 < 0)
3175 if (segment_info.x2 > windows->image.ximage->width)
3176 segment_info.x2=windows->image.ximage->width;
3177 if (segment_info.y2 < 0)
3180 if (segment_info.y2 > windows->image.ximage->height)
3181 segment_info.y2=windows->image.ximage->height;
3182 distance=(unsigned int)
3183 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3184 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3186 Compute chopping geometry.
3188 if (direction == HorizontalChopCommand)
3190 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3191 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3194 if (segment_info.x1 > (int) segment_info.x2)
3196 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3197 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3203 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3205 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3206 if (segment_info.y1 > segment_info.y2)
3208 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3209 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3212 } while ((state & ExitState) == 0);
3213 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3214 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3218 Image chopping is relative to image configuration.
3220 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3222 XSetCursorState(display,windows,MagickTrue);
3223 XCheckRefreshWindows(display,windows);
3224 windows->image.window_changes.width=windows->image.ximage->width-
3225 (unsigned int) chop_info.width;
3226 windows->image.window_changes.height=windows->image.ximage->height-
3227 (unsigned int) chop_info.height;
3228 width=(unsigned int) (*image)->columns;
3229 height=(unsigned int) (*image)->rows;
3232 if (windows->image.crop_geometry != (char *) NULL)
3233 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3234 scale_factor=(MagickRealType) width/windows->image.ximage->width;
3236 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3237 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3238 scale_factor=(MagickRealType) height/windows->image.ximage->height;
3240 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3241 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3245 chop_image=ChopImage(*image,&chop_info,exception);
3246 XSetCursorState(display,windows,MagickFalse);
3247 if (chop_image == (Image *) NULL)
3248 return(MagickFalse);
3249 *image=DestroyImage(*image);
3252 Update image configuration.
3254 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3255 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3264 + X C o l o r E d i t I m a g e %
3268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3270 % XColorEditImage() allows the user to interactively change the color of one
3271 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3273 % The format of the XColorEditImage method is:
3275 % MagickBooleanType XColorEditImage(Display *display,
3276 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3277 % ExceptionInfo *exception)
3279 % A description of each parameter follows:
3281 % o display: Specifies a connection to an X server; returned from
3284 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3286 % o windows: Specifies a pointer to a XWindows structure.
3288 % o image: the image; returned from ReadImage.
3290 % o exception: return any errors or warnings in this structure.
3293 static MagickBooleanType XColorEditImage(Display *display,
3294 XResourceInfo *resource_info,XWindows *windows,Image **image,
3295 ExceptionInfo *exception)
3310 static const ModeType
3311 ColorEditCommands[] =
3313 ColorEditMethodCommand,
3314 ColorEditColorCommand,
3315 ColorEditBorderCommand,
3316 ColorEditFuzzCommand,
3317 ColorEditUndoCommand,
3318 ColorEditHelpCommand,
3319 ColorEditDismissCommand
3323 method = PointMethod;
3329 border_color = { 0, 0, 0, 0, 0, 0 };
3332 command[MaxTextExtent],
3333 text[MaxTextExtent];
3368 (void) CloneString(&windows->command.name,"Color Edit");
3369 windows->command.data=4;
3370 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3371 (void) XMapRaised(display,windows->command.id);
3372 XClientMessage(display,windows->image.id,windows->im_protocols,
3373 windows->im_update_widget,CurrentTime);
3377 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3378 resource_info->background_color,resource_info->foreground_color);
3379 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3381 Track pointer until button 1 is pressed.
3383 XQueryPosition(display,windows->image.id,&x,&y);
3384 (void) XSelectInput(display,windows->image.id,
3385 windows->image.attributes.event_mask | PointerMotionMask);
3389 if (windows->info.mapped != MagickFalse)
3392 Display pointer position.
3394 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
3395 x+windows->image.x,y+windows->image.y);
3396 XInfoWidget(display,windows,text);
3399 Wait for next event.
3401 XScreenEvent(display,windows,&event,exception);
3402 if (event.xany.window == windows->command.id)
3405 Select a command from the Command widget.
3407 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3410 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3413 switch (ColorEditCommands[id])
3415 case ColorEditMethodCommand:
3421 Select a method from the pop-up menu.
3423 methods=(char **) GetCommandOptions(MagickMethodOptions);
3424 if (methods == (char **) NULL)
3426 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3427 (const char **) methods,command);
3429 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3430 MagickFalse,methods[entry]);
3431 methods=DestroyStringList(methods);
3434 case ColorEditColorCommand:
3437 *ColorMenu[MaxNumberPens];
3443 Initialize menu selections.
3445 for (i=0; i < (int) (MaxNumberPens-2); i++)
3446 ColorMenu[i]=resource_info->pen_colors[i];
3447 ColorMenu[MaxNumberPens-2]="Browser...";
3448 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3450 Select a pen color from the pop-up menu.
3452 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3453 (const char **) ColorMenu,command);
3456 if (pen_number == (MaxNumberPens-2))
3459 color_name[MaxTextExtent] = "gray";
3462 Select a pen color from a dialog.
3464 resource_info->pen_colors[pen_number]=color_name;
3465 XColorBrowserWidget(display,windows,"Select",color_name);
3466 if (*color_name == '\0')
3472 (void) XParseColor(display,windows->map_info->colormap,
3473 resource_info->pen_colors[pen_number],&color);
3474 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3475 (unsigned int) MaxColors,&color);
3476 windows->pixel_info->pen_colors[pen_number]=color;
3477 pen_id=(unsigned int) pen_number;
3480 case ColorEditBorderCommand:
3483 *ColorMenu[MaxNumberPens];
3489 Initialize menu selections.
3491 for (i=0; i < (int) (MaxNumberPens-2); i++)
3492 ColorMenu[i]=resource_info->pen_colors[i];
3493 ColorMenu[MaxNumberPens-2]="Browser...";
3494 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3496 Select a pen color from the pop-up menu.
3498 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3499 (const char **) ColorMenu,command);
3502 if (pen_number == (MaxNumberPens-2))
3505 color_name[MaxTextExtent] = "gray";
3508 Select a pen color from a dialog.
3510 resource_info->pen_colors[pen_number]=color_name;
3511 XColorBrowserWidget(display,windows,"Select",color_name);
3512 if (*color_name == '\0')
3518 (void) XParseColor(display,windows->map_info->colormap,
3519 resource_info->pen_colors[pen_number],&border_color);
3522 case ColorEditFuzzCommand:
3525 fuzz[MaxTextExtent];
3540 Select a command from the pop-up menu.
3542 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3548 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
3552 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3553 (void) XDialogWidget(display,windows,"Ok",
3554 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3557 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3558 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
3562 case ColorEditUndoCommand:
3564 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3568 case ColorEditHelpCommand:
3571 XTextViewWidget(display,resource_info,windows,MagickFalse,
3572 "Help Viewer - Image Annotation",ImageColorEditHelp);
3575 case ColorEditDismissCommand:
3585 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3592 if (event.xbutton.button != Button1)
3594 if ((event.xbutton.window != windows->image.id) &&
3595 (event.xbutton.window != windows->magnify.id))
3602 (void) XMagickCommand(display,resource_info,windows,
3603 SaveToUndoBufferCommand,image,exception);
3604 state|=UpdateConfigurationState;
3609 if (event.xbutton.button != Button1)
3611 if ((event.xbutton.window != windows->image.id) &&
3612 (event.xbutton.window != windows->magnify.id))
3615 Update colormap information.
3619 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3620 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3621 XInfoWidget(display,windows,text);
3622 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3623 state&=(~UpdateConfigurationState);
3633 if (event.xkey.window == windows->magnify.id)
3638 window=windows->magnify.id;
3639 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3641 if (event.xkey.window != windows->image.id)
3644 Respond to a user key press.
3646 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3647 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3648 switch ((int) key_symbol)
3662 XTextViewWidget(display,resource_info,windows,MagickFalse,
3663 "Help Viewer - Image Annotation",ImageColorEditHelp);
3668 (void) XBell(display,0);
3677 Map and unmap Info widget as cursor crosses its boundaries.
3681 if (windows->info.mapped != MagickFalse)
3683 if ((x < (int) (windows->info.x+windows->info.width)) &&
3684 (y < (int) (windows->info.y+windows->info.height)))
3685 (void) XWithdrawWindow(display,windows->info.id,
3686 windows->info.screen);
3689 if ((x > (int) (windows->info.x+windows->info.width)) ||
3690 (y > (int) (windows->info.y+windows->info.height)))
3691 (void) XMapWindow(display,windows->info.id);
3697 if (event.xany.window == windows->magnify.id)
3699 x=windows->magnify.x-windows->image.x;
3700 y=windows->magnify.y-windows->image.y;
3704 if ((state & UpdateConfigurationState) != 0)
3714 Pixel edit is relative to image configuration.
3716 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3718 color=windows->pixel_info->pen_colors[pen_id];
3719 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3720 width=(unsigned int) (*image)->columns;
3721 height=(unsigned int) (*image)->rows;
3724 if (windows->image.crop_geometry != (char *) NULL)
3725 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3728 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3730 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3731 if ((x_offset < 0) || (y_offset < 0))
3733 if ((x_offset >= (int) (*image)->columns) ||
3734 (y_offset >= (int) (*image)->rows))
3736 image_view=AcquireAuthenticCacheView(*image,exception);
3743 Update color information using point algorithm.
3745 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3746 return(MagickFalse);
3747 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3748 (ssize_t) y_offset,1,1,exception);
3749 if (q == (Quantum *) NULL)
3751 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3752 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3753 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3754 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3764 Update color information using replace algorithm.
3766 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
3767 x_offset,(ssize_t) y_offset,&target,exception);
3768 if ((*image)->storage_class == DirectClass)
3770 for (y=0; y < (int) (*image)->rows; y++)
3772 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3773 (*image)->columns,1,exception);
3774 if (q == (Quantum *) NULL)
3776 for (x=0; x < (int) (*image)->columns; x++)
3778 GetPixelInfoPixel(*image,q,&pixel);
3779 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3781 SetPixelRed(*image,ScaleShortToQuantum(
3783 SetPixelGreen(*image,ScaleShortToQuantum(
3785 SetPixelBlue(*image,ScaleShortToQuantum(
3788 q+=GetPixelChannels(*image);
3790 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3796 for (i=0; i < (ssize_t) (*image)->colors; i++)
3797 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3799 (*image)->colormap[i].red=(double) ScaleShortToQuantum(
3801 (*image)->colormap[i].green=(double) ScaleShortToQuantum(
3803 (*image)->colormap[i].blue=(double) ScaleShortToQuantum(
3806 (void) SyncImage(*image,exception);
3810 case FloodfillMethod:
3811 case FillToBorderMethod:
3820 Update color information using floodfill algorithm.
3822 (void) GetOneVirtualPixelInfo(*image,
3823 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3824 y_offset,&target,exception);
3825 if (method == FillToBorderMethod)
3827 target.red=(MagickRealType)
3828 ScaleShortToQuantum(border_color.red);
3829 target.green=(MagickRealType)
3830 ScaleShortToQuantum(border_color.green);
3831 target.blue=(MagickRealType)
3832 ScaleShortToQuantum(border_color.blue);
3834 draw_info=CloneDrawInfo(resource_info->image_info,
3836 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3837 AllCompliance,&draw_info->fill,exception);
3838 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
3839 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
3840 MagickFalse : MagickTrue,exception);
3841 draw_info=DestroyDrawInfo(draw_info);
3847 Update color information using reset algorithm.
3849 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3850 return(MagickFalse);
3851 for (y=0; y < (int) (*image)->rows; y++)
3853 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3854 (*image)->columns,1,exception);
3855 if (q == (Quantum *) NULL)
3857 for (x=0; x < (int) (*image)->columns; x++)
3859 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3860 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3861 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3862 q+=GetPixelChannels(*image);
3864 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3870 image_view=DestroyCacheView(image_view);
3871 state&=(~UpdateConfigurationState);
3873 } while ((state & ExitState) == 0);
3874 (void) XSelectInput(display,windows->image.id,
3875 windows->image.attributes.event_mask);
3876 XSetCursorState(display,windows,MagickFalse);
3877 (void) XFreeCursor(display,cursor);
3882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3886 + X C o m p o s i t e I m a g e %
3890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3892 % XCompositeImage() requests an image name from the user, reads the image and
3893 % composites it with the X window image at a location the user chooses with
3896 % The format of the XCompositeImage method is:
3898 % MagickBooleanType XCompositeImage(Display *display,
3899 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3900 % ExceptionInfo *exception)
3902 % A description of each parameter follows:
3904 % o display: Specifies a connection to an X server; returned from
3907 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3909 % o windows: Specifies a pointer to a XWindows structure.
3911 % o image: the image; returned from ReadImage.
3913 % o exception: return any errors or warnings in this structure.
3916 static MagickBooleanType XCompositeImage(Display *display,
3917 XResourceInfo *resource_info,XWindows *windows,Image *image,
3918 ExceptionInfo *exception)
3921 displacement_geometry[MaxTextExtent] = "30x30",
3922 filename[MaxTextExtent] = "\0";
3935 static CompositeOperator
3936 compose = CopyCompositeOp;
3938 static const ModeType
3939 CompositeCommands[] =
3941 CompositeOperatorsCommand,
3942 CompositeDissolveCommand,
3943 CompositeDisplaceCommand,
3944 CompositeHelpCommand,
3945 CompositeDismissCommand
3949 text[MaxTextExtent];
3982 Request image file name from user.
3984 XFileBrowserWidget(display,windows,"Composite",filename);
3985 if (*filename == '\0')
3990 XSetCursorState(display,windows,MagickTrue);
3991 XCheckRefreshWindows(display,windows);
3992 (void) CopyMagickString(resource_info->image_info->filename,filename,
3994 composite_image=ReadImage(resource_info->image_info,exception);
3995 CatchException(exception);
3996 XSetCursorState(display,windows,MagickFalse);
3997 if (composite_image == (Image *) NULL)
3998 return(MagickFalse);
4002 (void) CloneString(&windows->command.name,"Composite");
4003 windows->command.data=1;
4004 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
4005 (void) XMapRaised(display,windows->command.id);
4006 XClientMessage(display,windows->image.id,windows->im_protocols,
4007 windows->im_update_widget,CurrentTime);
4009 Track pointer until button 1 is pressed.
4011 XQueryPosition(display,windows->image.id,&x,&y);
4012 (void) XSelectInput(display,windows->image.id,
4013 windows->image.attributes.event_mask | PointerMotionMask);
4014 composite_info.x=(ssize_t) windows->image.x+x;
4015 composite_info.y=(ssize_t) windows->image.y+y;
4016 composite_info.width=0;
4017 composite_info.height=0;
4018 cursor=XCreateFontCursor(display,XC_ul_angle);
4019 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4024 if (windows->info.mapped != MagickFalse)
4027 Display pointer position.
4029 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4030 (long) composite_info.x,(long) composite_info.y);
4031 XInfoWidget(display,windows,text);
4033 highlight_info=composite_info;
4034 highlight_info.x=composite_info.x-windows->image.x;
4035 highlight_info.y=composite_info.y-windows->image.y;
4036 XHighlightRectangle(display,windows->image.id,
4037 windows->image.highlight_context,&highlight_info);
4039 Wait for next event.
4041 XScreenEvent(display,windows,&event,exception);
4042 XHighlightRectangle(display,windows->image.id,
4043 windows->image.highlight_context,&highlight_info);
4044 if (event.xany.window == windows->command.id)
4047 Select a command from the Command widget.
4049 id=XCommandWidget(display,windows,CompositeMenu,&event);
4052 switch (CompositeCommands[id])
4054 case CompositeOperatorsCommand:
4057 command[MaxTextExtent],
4061 Select a command from the pop-up menu.
4063 operators=GetCommandOptions(MagickComposeOptions);
4064 if (operators == (char **) NULL)
4066 entry=XMenuWidget(display,windows,CompositeMenu[id],
4067 (const char **) operators,command);
4069 compose=(CompositeOperator) ParseCommandOption(
4070 MagickComposeOptions,MagickFalse,operators[entry]);
4071 operators=DestroyStringList(operators);
4074 case CompositeDissolveCommand:
4077 factor[MaxTextExtent] = "20.0";
4080 Dissolve the two images a given percent.
4082 (void) XSetFunction(display,windows->image.highlight_context,
4084 (void) XDialogWidget(display,windows,"Dissolve",
4085 "Enter the blend factor (0.0 - 99.9%):",factor);
4086 (void) XSetFunction(display,windows->image.highlight_context,
4088 if (*factor == '\0')
4090 blend=StringToDouble(factor,(char **) NULL);
4091 compose=DissolveCompositeOp;
4094 case CompositeDisplaceCommand:
4097 Get horizontal and vertical scale displacement geometry.
4099 (void) XSetFunction(display,windows->image.highlight_context,
4101 (void) XDialogWidget(display,windows,"Displace",
4102 "Enter the horizontal and vertical scale:",displacement_geometry);
4103 (void) XSetFunction(display,windows->image.highlight_context,
4105 if (*displacement_geometry == '\0')
4107 compose=DisplaceCompositeOp;
4110 case CompositeHelpCommand:
4112 (void) XSetFunction(display,windows->image.highlight_context,
4114 XTextViewWidget(display,resource_info,windows,MagickFalse,
4115 "Help Viewer - Image Composite",ImageCompositeHelp);
4116 (void) XSetFunction(display,windows->image.highlight_context,
4120 case CompositeDismissCommand:
4138 if (image->debug != MagickFalse)
4139 (void) LogMagickEvent(X11Event,GetMagickModule(),
4140 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4141 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4142 if (event.xbutton.button != Button1)
4144 if (event.xbutton.window != windows->image.id)
4149 composite_info.width=composite_image->columns;
4150 composite_info.height=composite_image->rows;
4151 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4152 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4153 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4158 if (image->debug != MagickFalse)
4159 (void) LogMagickEvent(X11Event,GetMagickModule(),
4160 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4161 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4162 if (event.xbutton.button != Button1)
4164 if (event.xbutton.window != windows->image.id)
4166 if ((composite_info.width != 0) && (composite_info.height != 0))
4169 User has selected the location of the composite image.
4171 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4172 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4182 command[MaxTextExtent];
4190 if (event.xkey.window != windows->image.id)
4193 Respond to a user key press.
4195 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4196 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4197 *(command+length)='\0';
4198 if (image->debug != MagickFalse)
4199 (void) LogMagickEvent(X11Event,GetMagickModule(),
4200 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4201 switch ((int) key_symbol)
4209 composite_image=DestroyImage(composite_image);
4217 (void) XSetFunction(display,windows->image.highlight_context,
4219 XTextViewWidget(display,resource_info,windows,MagickFalse,
4220 "Help Viewer - Image Composite",ImageCompositeHelp);
4221 (void) XSetFunction(display,windows->image.highlight_context,
4227 (void) XBell(display,0);
4236 Map and unmap Info widget as text cursor crosses its boundaries.
4240 if (windows->info.mapped != MagickFalse)
4242 if ((x < (int) (windows->info.x+windows->info.width)) &&
4243 (y < (int) (windows->info.y+windows->info.height)))
4244 (void) XWithdrawWindow(display,windows->info.id,
4245 windows->info.screen);
4248 if ((x > (int) (windows->info.x+windows->info.width)) ||
4249 (y > (int) (windows->info.y+windows->info.height)))
4250 (void) XMapWindow(display,windows->info.id);
4251 composite_info.x=(ssize_t) windows->image.x+x;
4252 composite_info.y=(ssize_t) windows->image.y+y;
4257 if (image->debug != MagickFalse)
4258 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4263 } while ((state & ExitState) == 0);
4264 (void) XSelectInput(display,windows->image.id,
4265 windows->image.attributes.event_mask);
4266 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4267 XSetCursorState(display,windows,MagickFalse);
4268 (void) XFreeCursor(display,cursor);
4269 if ((state & EscapeState) != 0)
4272 Image compositing is relative to image configuration.
4274 XSetCursorState(display,windows,MagickTrue);
4275 XCheckRefreshWindows(display,windows);
4276 width=(unsigned int) image->columns;
4277 height=(unsigned int) image->rows;
4280 if (windows->image.crop_geometry != (char *) NULL)
4281 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4282 scale_factor=(MagickRealType) width/windows->image.ximage->width;
4283 composite_info.x+=x;
4284 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4285 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4286 scale_factor=(MagickRealType) height/windows->image.ximage->height;
4287 composite_info.y+=y;
4288 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4289 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4290 if ((composite_info.width != composite_image->columns) ||
4291 (composite_info.height != composite_image->rows))
4297 Scale composite image.
4299 resize_image=ResizeImage(composite_image,composite_info.width,
4300 composite_info.height,composite_image->filter,exception);
4301 composite_image=DestroyImage(composite_image);
4302 if (resize_image == (Image *) NULL)
4304 XSetCursorState(display,windows,MagickFalse);
4305 return(MagickFalse);
4307 composite_image=resize_image;
4309 if (compose == DisplaceCompositeOp)
4310 (void) SetImageArtifact(composite_image,"compose:args",
4311 displacement_geometry);
4330 Create mattes for blending.
4332 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4333 opacity=(Quantum) (ScaleQuantumToChar(QuantumRange)-
4334 ((ssize_t) ScaleQuantumToChar(QuantumRange)*blend)/100);
4335 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4336 return(MagickFalse);
4337 image->matte=MagickTrue;
4338 image_view=AcquireAuthenticCacheView(image,exception);
4339 for (y=0; y < (int) image->rows; y++)
4341 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4343 if (q == (Quantum *) NULL)
4345 for (x=0; x < (int) image->columns; x++)
4347 SetPixelAlpha(image,opacity,q);
4348 q+=GetPixelChannels(image);
4350 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4353 image_view=DestroyCacheView(image_view);
4356 Composite image with X Image window.
4358 (void) CompositeImage(image,composite_image,compose,MagickTrue,
4359 composite_info.x,composite_info.y,exception);
4360 composite_image=DestroyImage(composite_image);
4361 XSetCursorState(display,windows,MagickFalse);
4363 Update image configuration.
4365 XConfigureImageColormap(display,resource_info,windows,image,exception);
4366 (void) XConfigureImage(display,resource_info,windows,image,exception);
4371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4375 + X C o n f i g u r e I m a g e %
4379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4381 % XConfigureImage() creates a new X image. It also notifies the window
4382 % manager of the new image size and configures the transient widows.
4384 % The format of the XConfigureImage method is:
4386 % MagickBooleanType XConfigureImage(Display *display,
4387 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4388 % ExceptionInfo *exception)
4390 % A description of each parameter follows:
4392 % o display: Specifies a connection to an X server; returned from
4395 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4397 % o windows: Specifies a pointer to a XWindows structure.
4399 % o image: the image.
4401 % o exception: return any errors or warnings in this structure.
4403 % o exception: return any errors or warnings in this structure.
4406 static MagickBooleanType XConfigureImage(Display *display,
4407 XResourceInfo *resource_info,XWindows *windows,Image *image,
4408 ExceptionInfo *exception)
4411 geometry[MaxTextExtent];
4432 Dismiss if window dimensions are zero.
4434 width=(unsigned int) windows->image.window_changes.width;
4435 height=(unsigned int) windows->image.window_changes.height;
4436 if (image->debug != MagickFalse)
4437 (void) LogMagickEvent(X11Event,GetMagickModule(),
4438 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4439 windows->image.ximage->height,(double) width,(double) height);
4440 if ((width*height) == 0)
4445 Resize image to fit Image window dimensions.
4447 XSetCursorState(display,windows,MagickTrue);
4448 (void) XFlush(display);
4449 if (((int) width != windows->image.ximage->width) ||
4450 ((int) height != windows->image.ximage->height))
4451 image->taint=MagickTrue;
4452 windows->magnify.x=(int)
4453 width*windows->magnify.x/windows->image.ximage->width;
4454 windows->magnify.y=(int)
4455 height*windows->magnify.y/windows->image.ximage->height;
4456 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4457 windows->image.y=(int)
4458 (height*windows->image.y/windows->image.ximage->height);
4459 status=XMakeImage(display,resource_info,&windows->image,image,
4460 (unsigned int) width,(unsigned int) height,exception);
4461 if (status == MagickFalse)
4462 XNoticeWidget(display,windows,"Unable to configure X image:",
4463 windows->image.name);
4465 Notify window manager of the new configuration.
4467 if (resource_info->image_geometry != (char *) NULL)
4468 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4469 resource_info->image_geometry);
4471 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4472 XDisplayWidth(display,windows->image.screen),
4473 XDisplayHeight(display,windows->image.screen));
4474 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4475 window_changes.width=(int) width;
4476 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4477 window_changes.width=XDisplayWidth(display,windows->image.screen);
4478 window_changes.height=(int) height;
4479 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4480 window_changes.height=XDisplayHeight(display,windows->image.screen);
4481 mask=(size_t) (CWWidth | CWHeight);
4482 if (resource_info->backdrop)
4485 window_changes.x=(int)
4486 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4487 window_changes.y=(int)
4488 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4490 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4491 (unsigned int) mask,&window_changes);
4492 (void) XClearWindow(display,windows->image.id);
4493 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4495 Update Magnify window configuration.
4497 if (windows->magnify.mapped != MagickFalse)
4498 XMakeMagnifyImage(display,windows,exception);
4499 windows->pan.crop_geometry=windows->image.crop_geometry;
4500 XBestIconSize(display,&windows->pan,image);
4501 while (((windows->pan.width << 1) < MaxIconSize) &&
4502 ((windows->pan.height << 1) < MaxIconSize))
4504 windows->pan.width<<=1;
4505 windows->pan.height<<=1;
4507 if (windows->pan.geometry != (char *) NULL)
4508 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4509 &windows->pan.width,&windows->pan.height);
4510 window_changes.width=(int) windows->pan.width;
4511 window_changes.height=(int) windows->pan.height;
4512 size_hints=XAllocSizeHints();
4513 if (size_hints != (XSizeHints *) NULL)
4518 size_hints->flags=PSize | PMinSize | PMaxSize;
4519 size_hints->width=window_changes.width;
4520 size_hints->height=window_changes.height;
4521 size_hints->min_width=size_hints->width;
4522 size_hints->min_height=size_hints->height;
4523 size_hints->max_width=size_hints->width;
4524 size_hints->max_height=size_hints->height;
4525 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4526 (void) XFree((void *) size_hints);
4528 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4529 (unsigned int) (CWWidth | CWHeight),&window_changes);
4531 Update icon window configuration.
4533 windows->icon.crop_geometry=windows->image.crop_geometry;
4534 XBestIconSize(display,&windows->icon,image);
4535 window_changes.width=(int) windows->icon.width;
4536 window_changes.height=(int) windows->icon.height;
4537 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4538 (unsigned int) (CWWidth | CWHeight),&window_changes);
4539 XSetCursorState(display,windows,MagickFalse);
4540 return(status != 0 ? MagickTrue : MagickFalse);
4544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4548 + X C r o p I m a g e %
4552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4554 % XCropImage() allows the user to select a region of the image and crop, copy,
4555 % or cut it. For copy or cut, the image can subsequently be composited onto
4556 % the image with XPasteImage.
4558 % The format of the XCropImage method is:
4560 % MagickBooleanType XCropImage(Display *display,
4561 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4562 % const ClipboardMode mode,ExceptionInfo *exception)
4564 % A description of each parameter follows:
4566 % o display: Specifies a connection to an X server; returned from
4569 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4571 % o windows: Specifies a pointer to a XWindows structure.
4573 % o image: the image; returned from ReadImage.
4575 % o mode: This unsigned value specified whether the image should be
4576 % cropped, copied, or cut.
4578 % o exception: return any errors or warnings in this structure.
4581 static MagickBooleanType XCropImage(Display *display,
4582 XResourceInfo *resource_info,XWindows *windows,Image *image,
4583 const ClipboardMode mode,ExceptionInfo *exception)
4592 *RectifyModeMenu[] =
4600 static const ModeType
4610 RectifyDismissCommand
4617 command[MaxTextExtent],
4618 text[MaxTextExtent];
4661 (void) CloneString(&windows->command.name,"Copy");
4666 (void) CloneString(&windows->command.name,"Crop");
4671 (void) CloneString(&windows->command.name,"Cut");
4675 RectifyModeMenu[0]=windows->command.name;
4676 windows->command.data=0;
4677 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4678 (void) XMapRaised(display,windows->command.id);
4679 XClientMessage(display,windows->image.id,windows->im_protocols,
4680 windows->im_update_widget,CurrentTime);
4682 Track pointer until button 1 is pressed.
4684 XQueryPosition(display,windows->image.id,&x,&y);
4685 (void) XSelectInput(display,windows->image.id,
4686 windows->image.attributes.event_mask | PointerMotionMask);
4687 crop_info.x=(ssize_t) windows->image.x+x;
4688 crop_info.y=(ssize_t) windows->image.y+y;
4691 cursor=XCreateFontCursor(display,XC_fleur);
4695 if (windows->info.mapped != MagickFalse)
4698 Display pointer position.
4700 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4701 (long) crop_info.x,(long) crop_info.y);
4702 XInfoWidget(display,windows,text);
4705 Wait for next event.
4707 XScreenEvent(display,windows,&event,exception);
4708 if (event.xany.window == windows->command.id)
4711 Select a command from the Command widget.
4713 id=XCommandWidget(display,windows,CropModeMenu,&event);
4716 switch (CropCommands[id])
4718 case CropHelpCommand:
4724 XTextViewWidget(display,resource_info,windows,MagickFalse,
4725 "Help Viewer - Image Copy",ImageCopyHelp);
4730 XTextViewWidget(display,resource_info,windows,MagickFalse,
4731 "Help Viewer - Image Crop",ImageCropHelp);
4736 XTextViewWidget(display,resource_info,windows,MagickFalse,
4737 "Help Viewer - Image Cut",ImageCutHelp);
4743 case CropDismissCommand:
4761 if (event.xbutton.button != Button1)
4763 if (event.xbutton.window != windows->image.id)
4766 Note first corner of cropping rectangle-- exit loop.
4768 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4769 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4770 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4780 if (event.xkey.window != windows->image.id)
4783 Respond to a user key press.
4785 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4786 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4787 switch ((int) key_symbol)
4806 XTextViewWidget(display,resource_info,windows,MagickFalse,
4807 "Help Viewer - Image Copy",ImageCopyHelp);
4812 XTextViewWidget(display,resource_info,windows,MagickFalse,
4813 "Help Viewer - Image Crop",ImageCropHelp);
4818 XTextViewWidget(display,resource_info,windows,MagickFalse,
4819 "Help Viewer - Image Cut",ImageCutHelp);
4827 (void) XBell(display,0);
4835 if (event.xmotion.window != windows->image.id)
4838 Map and unmap Info widget as text cursor crosses its boundaries.
4842 if (windows->info.mapped != MagickFalse)
4844 if ((x < (int) (windows->info.x+windows->info.width)) &&
4845 (y < (int) (windows->info.y+windows->info.height)))
4846 (void) XWithdrawWindow(display,windows->info.id,
4847 windows->info.screen);
4850 if ((x > (int) (windows->info.x+windows->info.width)) ||
4851 (y > (int) (windows->info.y+windows->info.height)))
4852 (void) XMapWindow(display,windows->info.id);
4853 crop_info.x=(ssize_t) windows->image.x+x;
4854 crop_info.y=(ssize_t) windows->image.y+y;
4860 } while ((state & ExitState) == 0);
4861 (void) XSelectInput(display,windows->image.id,
4862 windows->image.attributes.event_mask);
4863 if ((state & EscapeState) != 0)
4866 User want to exit without cropping.
4868 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4869 (void) XFreeCursor(display,cursor);
4872 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4876 Size rectangle as pointer moves until the mouse button is released.
4878 x=(int) crop_info.x;
4879 y=(int) crop_info.y;
4885 highlight_info=crop_info;
4886 highlight_info.x=crop_info.x-windows->image.x;
4887 highlight_info.y=crop_info.y-windows->image.y;
4888 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4891 Display info and draw cropping rectangle.
4893 if (windows->info.mapped == MagickFalse)
4894 (void) XMapWindow(display,windows->info.id);
4895 (void) FormatLocaleString(text,MaxTextExtent,
4896 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4897 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4898 XInfoWidget(display,windows,text);
4899 XHighlightRectangle(display,windows->image.id,
4900 windows->image.highlight_context,&highlight_info);
4903 if (windows->info.mapped != MagickFalse)
4904 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4906 Wait for next event.
4908 XScreenEvent(display,windows,&event,exception);
4909 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4910 XHighlightRectangle(display,windows->image.id,
4911 windows->image.highlight_context,&highlight_info);
4916 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4917 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4923 User has committed to cropping rectangle.
4925 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4926 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4927 XSetCursorState(display,windows,MagickFalse);
4929 windows->command.data=0;
4930 (void) XCommandWidget(display,windows,RectifyModeMenu,
4938 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4939 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4944 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4945 ((state & ExitState) != 0))
4948 Check boundary conditions.
4950 if (crop_info.x < 0)
4953 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4954 crop_info.x=(ssize_t) windows->image.ximage->width;
4955 if ((int) crop_info.x < x)
4956 crop_info.width=(unsigned int) (x-crop_info.x);
4959 crop_info.width=(unsigned int) (crop_info.x-x);
4960 crop_info.x=(ssize_t) x;
4962 if (crop_info.y < 0)
4965 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4966 crop_info.y=(ssize_t) windows->image.ximage->height;
4967 if ((int) crop_info.y < y)
4968 crop_info.height=(unsigned int) (y-crop_info.y);
4971 crop_info.height=(unsigned int) (crop_info.y-y);
4972 crop_info.y=(ssize_t) y;
4975 } while ((state & ExitState) == 0);
4977 Wait for user to grab a corner of the rectangle or press return.
4980 (void) XMapWindow(display,windows->info.id);
4983 if (windows->info.mapped != MagickFalse)
4986 Display pointer position.
4988 (void) FormatLocaleString(text,MaxTextExtent,
4989 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4990 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4991 XInfoWidget(display,windows,text);
4993 highlight_info=crop_info;
4994 highlight_info.x=crop_info.x-windows->image.x;
4995 highlight_info.y=crop_info.y-windows->image.y;
4996 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
5002 XHighlightRectangle(display,windows->image.id,
5003 windows->image.highlight_context,&highlight_info);
5004 XScreenEvent(display,windows,&event,exception);
5005 if (event.xany.window == windows->command.id)
5008 Select a command from the Command widget.
5010 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5011 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5012 (void) XSetFunction(display,windows->image.highlight_context,
5014 XHighlightRectangle(display,windows->image.id,
5015 windows->image.highlight_context,&highlight_info);
5017 switch (RectifyCommands[id])
5019 case RectifyCopyCommand:
5024 case RectifyHelpCommand:
5026 (void) XSetFunction(display,windows->image.highlight_context,
5032 XTextViewWidget(display,resource_info,windows,MagickFalse,
5033 "Help Viewer - Image Copy",ImageCopyHelp);
5038 XTextViewWidget(display,resource_info,windows,MagickFalse,
5039 "Help Viewer - Image Crop",ImageCropHelp);
5044 XTextViewWidget(display,resource_info,windows,MagickFalse,
5045 "Help Viewer - Image Cut",ImageCutHelp);
5049 (void) XSetFunction(display,windows->image.highlight_context,
5053 case RectifyDismissCommand:
5067 XHighlightRectangle(display,windows->image.id,
5068 windows->image.highlight_context,&highlight_info);
5073 if (event.xbutton.button != Button1)
5075 if (event.xbutton.window != windows->image.id)
5077 x=windows->image.x+event.xbutton.x;
5078 y=windows->image.y+event.xbutton.y;
5079 if ((x < (int) (crop_info.x+RoiDelta)) &&
5080 (x > (int) (crop_info.x-RoiDelta)) &&
5081 (y < (int) (crop_info.y+RoiDelta)) &&
5082 (y > (int) (crop_info.y-RoiDelta)))
5084 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5085 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5086 state|=UpdateConfigurationState;
5089 if ((x < (int) (crop_info.x+RoiDelta)) &&
5090 (x > (int) (crop_info.x-RoiDelta)) &&
5091 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5092 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5094 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5095 state|=UpdateConfigurationState;
5098 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5099 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5100 (y < (int) (crop_info.y+RoiDelta)) &&
5101 (y > (int) (crop_info.y-RoiDelta)))
5103 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5104 state|=UpdateConfigurationState;
5107 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5108 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5109 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5110 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5112 state|=UpdateConfigurationState;
5118 if (event.xbutton.window == windows->pan.id)
5119 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5120 (highlight_info.y != crop_info.y-windows->image.y))
5121 XHighlightRectangle(display,windows->image.id,
5122 windows->image.highlight_context,&highlight_info);
5123 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5124 event.xbutton.time);
5129 if (event.xexpose.window == windows->image.id)
5130 if (event.xexpose.count == 0)
5132 event.xexpose.x=(int) highlight_info.x;
5133 event.xexpose.y=(int) highlight_info.y;
5134 event.xexpose.width=(int) highlight_info.width;
5135 event.xexpose.height=(int) highlight_info.height;
5136 XRefreshWindow(display,&windows->image,&event);
5138 if (event.xexpose.window == windows->info.id)
5139 if (event.xexpose.count == 0)
5140 XInfoWidget(display,windows,text);
5145 if (event.xkey.window != windows->image.id)
5148 Respond to a user key press.
5150 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5151 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5152 switch ((int) key_symbol)
5165 crop_info.x=(ssize_t) (windows->image.width/2L-
5166 crop_info.width/2L);
5167 crop_info.y=(ssize_t) (windows->image.height/2L-
5168 crop_info.height/2L);
5200 (void) XSetFunction(display,windows->image.highlight_context,
5206 XTextViewWidget(display,resource_info,windows,MagickFalse,
5207 "Help Viewer - Image Copy",ImageCopyHelp);
5212 XTextViewWidget(display,resource_info,windows,MagickFalse,
5213 "Help Viewer - Image Cropg",ImageCropHelp);
5218 XTextViewWidget(display,resource_info,windows,MagickFalse,
5219 "Help Viewer - Image Cutg",ImageCutHelp);
5223 (void) XSetFunction(display,windows->image.highlight_context,
5229 (void) XBell(display,0);
5233 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5241 if (event.xmotion.window != windows->image.id)
5244 Map and unmap Info widget as text cursor crosses its boundaries.
5248 if (windows->info.mapped != MagickFalse)
5250 if ((x < (int) (windows->info.x+windows->info.width)) &&
5251 (y < (int) (windows->info.y+windows->info.height)))
5252 (void) XWithdrawWindow(display,windows->info.id,
5253 windows->info.screen);
5256 if ((x > (int) (windows->info.x+windows->info.width)) ||
5257 (y > (int) (windows->info.y+windows->info.height)))
5258 (void) XMapWindow(display,windows->info.id);
5259 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5260 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5263 case SelectionRequest:
5268 XSelectionRequestEvent
5272 Set primary selection.
5274 (void) FormatLocaleString(text,MaxTextExtent,
5275 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5276 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5277 request=(&(event.xselectionrequest));
5278 (void) XChangeProperty(request->display,request->requestor,
5279 request->property,request->target,8,PropModeReplace,
5280 (unsigned char *) text,(int) strlen(text));
5281 notify.type=SelectionNotify;
5282 notify.display=request->display;
5283 notify.requestor=request->requestor;
5284 notify.selection=request->selection;
5285 notify.target=request->target;
5286 notify.time=request->time;
5287 if (request->property == None)
5288 notify.property=request->target;
5290 notify.property=request->property;
5291 (void) XSendEvent(request->display,request->requestor,False,0,
5292 (XEvent *) ¬ify);
5297 if ((state & UpdateConfigurationState) != 0)
5299 (void) XPutBackEvent(display,&event);
5300 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5303 } while ((state & ExitState) == 0);
5304 } while ((state & ExitState) == 0);
5305 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5306 XSetCursorState(display,windows,MagickFalse);
5307 if ((state & EscapeState) != 0)
5309 if (mode == CropMode)
5310 if (((int) crop_info.width != windows->image.ximage->width) ||
5311 ((int) crop_info.height != windows->image.ximage->height))
5314 Reconfigure Image window as defined by cropping rectangle.
5316 XSetCropGeometry(display,windows,&crop_info,image);
5317 windows->image.window_changes.width=(int) crop_info.width;
5318 windows->image.window_changes.height=(int) crop_info.height;
5319 (void) XConfigureImage(display,resource_info,windows,image,exception);
5323 Copy image before applying image transforms.
5325 XSetCursorState(display,windows,MagickTrue);
5326 XCheckRefreshWindows(display,windows);
5327 width=(unsigned int) image->columns;
5328 height=(unsigned int) image->rows;
5331 if (windows->image.crop_geometry != (char *) NULL)
5332 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5333 scale_factor=(MagickRealType) width/windows->image.ximage->width;
5335 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5336 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5337 scale_factor=(MagickRealType) height/windows->image.ximage->height;
5339 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5340 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5341 crop_image=CropImage(image,&crop_info,exception);
5342 XSetCursorState(display,windows,MagickFalse);
5343 if (crop_image == (Image *) NULL)
5344 return(MagickFalse);
5345 if (resource_info->copy_image != (Image *) NULL)
5346 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5347 resource_info->copy_image=crop_image;
5348 if (mode == CopyMode)
5350 (void) XConfigureImage(display,resource_info,windows,image,exception);
5356 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
5357 return(MagickFalse);
5358 image->matte=MagickTrue;
5359 image_view=AcquireAuthenticCacheView(image,exception);
5360 for (y=0; y < (int) crop_info.height; y++)
5362 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5363 crop_info.width,1,exception);
5364 if (q == (Quantum *) NULL)
5366 for (x=0; x < (int) crop_info.width; x++)
5368 SetPixelAlpha(image,TransparentAlpha,q);
5369 q+=GetPixelChannels(image);
5371 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
5374 image_view=DestroyCacheView(image_view);
5376 Update image configuration.
5378 XConfigureImageColormap(display,resource_info,windows,image,exception);
5379 (void) XConfigureImage(display,resource_info,windows,image,exception);
5384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5388 + X D r a w I m a g e %
5392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5394 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5397 % The format of the XDrawEditImage method is:
5399 % MagickBooleanType XDrawEditImage(Display *display,
5400 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5401 % ExceptionInfo *exception)
5403 % A description of each parameter follows:
5405 % o display: Specifies a connection to an X server; returned from
5408 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5410 % o windows: Specifies a pointer to a XWindows structure.
5412 % o image: the image.
5414 % o exception: return any errors or warnings in this structure.
5417 static MagickBooleanType XDrawEditImage(Display *display,
5418 XResourceInfo *resource_info,XWindows *windows,Image **image,
5419 ExceptionInfo *exception)
5435 element = PointElement;
5437 static const ModeType
5450 stipple = (Pixmap) NULL;
5457 command[MaxTextExtent],
5458 text[MaxTextExtent];
5507 Allocate polygon info.
5509 max_coordinates=2048;
5510 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5511 sizeof(*coordinate_info));
5512 if (coordinate_info == (XPoint *) NULL)
5514 (void) ThrowMagickException(exception,GetMagickModule(),
5515 ResourceLimitError,"MemoryAllocationFailed","'%s'","...");
5516 return(MagickFalse);
5521 (void) CloneString(&windows->command.name,"Draw");
5522 windows->command.data=4;
5523 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5524 (void) XMapRaised(display,windows->command.id);
5525 XClientMessage(display,windows->image.id,windows->im_protocols,
5526 windows->im_update_widget,CurrentTime);
5528 Wait for first button press.
5530 root_window=XRootWindow(display,XDefaultScreen(display));
5531 draw_info.stencil=OpaqueStencil;
5533 cursor=XCreateFontCursor(display,XC_tcross);
5536 XQueryPosition(display,windows->image.id,&x,&y);
5537 (void) XSelectInput(display,windows->image.id,
5538 windows->image.attributes.event_mask | PointerMotionMask);
5539 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5543 if (windows->info.mapped != MagickFalse)
5546 Display pointer position.
5548 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5549 x+windows->image.x,y+windows->image.y);
5550 XInfoWidget(display,windows,text);
5553 Wait for next event.
5555 XScreenEvent(display,windows,&event,exception);
5556 if (event.xany.window == windows->command.id)
5559 Select a command from the Command widget.
5561 id=XCommandWidget(display,windows,DrawMenu,&event);
5564 switch (DrawCommands[id])
5566 case DrawElementCommand:
5585 Select a command from the pop-up menu.
5587 element=(ElementType) (XMenuWidget(display,windows,
5588 DrawMenu[id],Elements,command)+1);
5591 case DrawColorCommand:
5594 *ColorMenu[MaxNumberPens+1];
5606 Initialize menu selections.
5608 for (i=0; i < (int) (MaxNumberPens-2); i++)
5609 ColorMenu[i]=resource_info->pen_colors[i];
5610 ColorMenu[MaxNumberPens-2]="transparent";
5611 ColorMenu[MaxNumberPens-1]="Browser...";
5612 ColorMenu[MaxNumberPens]=(char *) NULL;
5614 Select a pen color from the pop-up menu.
5616 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5617 (const char **) ColorMenu,command);
5620 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5622 if (transparent != MagickFalse)
5624 draw_info.stencil=TransparentStencil;
5627 if (pen_number == (MaxNumberPens-1))
5630 color_name[MaxTextExtent] = "gray";
5633 Select a pen color from a dialog.
5635 resource_info->pen_colors[pen_number]=color_name;
5636 XColorBrowserWidget(display,windows,"Select",color_name);
5637 if (*color_name == '\0')
5643 (void) XParseColor(display,windows->map_info->colormap,
5644 resource_info->pen_colors[pen_number],&color);
5645 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5646 (unsigned int) MaxColors,&color);
5647 windows->pixel_info->pen_colors[pen_number]=color;
5648 pen_id=(unsigned int) pen_number;
5649 draw_info.stencil=OpaqueStencil;
5652 case DrawStippleCommand:
5664 filename[MaxTextExtent] = "\0";
5681 Select a command from the pop-up menu.
5683 StipplesMenu[7]="Open...";
5684 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5688 if (stipple != (Pixmap) NULL)
5689 (void) XFreePixmap(display,stipple);
5690 stipple=(Pixmap) NULL;
5697 stipple=XCreateBitmapFromData(display,root_window,
5698 (char *) BricksBitmap,BricksWidth,BricksHeight);
5703 stipple=XCreateBitmapFromData(display,root_window,
5704 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5709 stipple=XCreateBitmapFromData(display,root_window,
5710 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5715 stipple=XCreateBitmapFromData(display,root_window,
5716 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5721 stipple=XCreateBitmapFromData(display,root_window,
5722 (char *) WavyBitmap,WavyWidth,WavyHeight);
5727 stipple=XCreateBitmapFromData(display,root_window,
5728 (char *) HighlightBitmap,HighlightWidth,
5735 stipple=XCreateBitmapFromData(display,root_window,
5736 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5742 XFileBrowserWidget(display,windows,"Stipple",filename);
5743 if (*filename == '\0')
5748 XSetCursorState(display,windows,MagickTrue);
5749 XCheckRefreshWindows(display,windows);
5750 image_info=AcquireImageInfo();
5751 (void) CopyMagickString(image_info->filename,filename,
5753 stipple_image=ReadImage(image_info,exception);
5754 CatchException(exception);
5755 XSetCursorState(display,windows,MagickFalse);
5756 if (stipple_image == (Image *) NULL)
5758 (void) AcquireUniqueFileResource(filename);
5759 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5761 (void) WriteImage(image_info,stipple_image,exception);
5762 stipple_image=DestroyImage(stipple_image);
5763 image_info=DestroyImageInfo(image_info);
5764 status=XReadBitmapFile(display,root_window,filename,&width,
5765 &height,&stipple,&x,&y);
5766 (void) RelinquishUniqueFileResource(filename);
5767 if ((status != BitmapSuccess) != 0)
5768 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5772 case DrawWidthCommand:
5775 width[MaxTextExtent] = "0";
5790 Select a command from the pop-up menu.
5792 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5798 line_width=(unsigned int) StringToUnsignedLong(
5802 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5806 line_width=(unsigned int) StringToUnsignedLong(width);
5809 case DrawUndoCommand:
5811 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5815 case DrawHelpCommand:
5817 XTextViewWidget(display,resource_info,windows,MagickFalse,
5818 "Help Viewer - Image Rotation",ImageDrawHelp);
5819 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5822 case DrawDismissCommand:
5834 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5841 if (event.xbutton.button != Button1)
5843 if (event.xbutton.window != windows->image.id)
5862 if (event.xkey.window != windows->image.id)
5865 Respond to a user key press.
5867 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5868 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5869 switch ((int) key_symbol)
5884 XTextViewWidget(display,resource_info,windows,MagickFalse,
5885 "Help Viewer - Image Rotation",ImageDrawHelp);
5890 (void) XBell(display,0);
5899 Map and unmap Info widget as text cursor crosses its boundaries.
5903 if (windows->info.mapped != MagickFalse)
5905 if ((x < (int) (windows->info.x+windows->info.width)) &&
5906 (y < (int) (windows->info.y+windows->info.height)))
5907 (void) XWithdrawWindow(display,windows->info.id,
5908 windows->info.screen);
5911 if ((x > (int) (windows->info.x+windows->info.width)) ||
5912 (y > (int) (windows->info.y+windows->info.height)))
5913 (void) XMapWindow(display,windows->info.id);
5917 } while ((state & ExitState) == 0);
5918 (void) XSelectInput(display,windows->image.id,
5919 windows->image.attributes.event_mask);
5920 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5921 if ((state & EscapeState) != 0)
5924 Draw element as pointer moves until the button is released.
5932 rectangle_info.x=(ssize_t) x;
5933 rectangle_info.y=(ssize_t) y;
5934 rectangle_info.width=0;
5935 rectangle_info.height=0;
5936 number_coordinates=1;
5937 coordinate_info->x=x;
5938 coordinate_info->y=y;
5939 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5948 if (number_coordinates > 1)
5950 (void) XDrawLines(display,windows->image.id,
5951 windows->image.highlight_context,coordinate_info,
5952 number_coordinates,CoordModeOrigin);
5953 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5954 coordinate_info[number_coordinates-1].x,
5955 coordinate_info[number_coordinates-1].y);
5956 XInfoWidget(display,windows,text);
5965 Display angle of the line.
5967 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5968 line_info.y1),(double) (line_info.x2-line_info.x1)));
5969 (void) FormatLocaleString(text,MaxTextExtent," %g",
5971 XInfoWidget(display,windows,text);
5972 XHighlightLine(display,windows->image.id,
5973 windows->image.highlight_context,&line_info);
5976 if (windows->info.mapped != MagickFalse)
5977 (void) XWithdrawWindow(display,windows->info.id,
5978 windows->info.screen);
5981 case RectangleElement:
5982 case FillRectangleElement:
5984 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5987 Display info and draw drawing rectangle.
5989 (void) FormatLocaleString(text,MaxTextExtent,
5990 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5991 (double) rectangle_info.height,(double) rectangle_info.x,
5992 (double) rectangle_info.y);
5993 XInfoWidget(display,windows,text);
5994 XHighlightRectangle(display,windows->image.id,
5995 windows->image.highlight_context,&rectangle_info);
5998 if (windows->info.mapped != MagickFalse)
5999 (void) XWithdrawWindow(display,windows->info.id,
6000 windows->info.screen);
6004 case FillCircleElement:
6005 case EllipseElement:
6006 case FillEllipseElement:
6008 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6011 Display info and draw drawing rectangle.
6013 (void) FormatLocaleString(text,MaxTextExtent,
6014 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6015 (double) rectangle_info.height,(double) rectangle_info.x,
6016 (double) rectangle_info.y);
6017 XInfoWidget(display,windows,text);
6018 XHighlightEllipse(display,windows->image.id,
6019 windows->image.highlight_context,&rectangle_info);
6022 if (windows->info.mapped != MagickFalse)
6023 (void) XWithdrawWindow(display,windows->info.id,
6024 windows->info.screen);
6027 case PolygonElement:
6028 case FillPolygonElement:
6030 if (number_coordinates > 1)
6031 (void) XDrawLines(display,windows->image.id,
6032 windows->image.highlight_context,coordinate_info,
6033 number_coordinates,CoordModeOrigin);
6037 Display angle of the line.
6039 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6040 line_info.y1),(double) (line_info.x2-line_info.x1)));
6041 (void) FormatLocaleString(text,MaxTextExtent," %g",
6043 XInfoWidget(display,windows,text);
6044 XHighlightLine(display,windows->image.id,
6045 windows->image.highlight_context,&line_info);
6048 if (windows->info.mapped != MagickFalse)
6049 (void) XWithdrawWindow(display,windows->info.id,
6050 windows->info.screen);
6055 Wait for next event.
6057 XScreenEvent(display,windows,&event,exception);
6063 if (number_coordinates > 1)
6064 (void) XDrawLines(display,windows->image.id,
6065 windows->image.highlight_context,coordinate_info,
6066 number_coordinates,CoordModeOrigin);
6072 XHighlightLine(display,windows->image.id,
6073 windows->image.highlight_context,&line_info);
6076 case RectangleElement:
6077 case FillRectangleElement:
6079 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6080 XHighlightRectangle(display,windows->image.id,
6081 windows->image.highlight_context,&rectangle_info);
6085 case FillCircleElement:
6086 case EllipseElement:
6087 case FillEllipseElement:
6089 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6090 XHighlightEllipse(display,windows->image.id,
6091 windows->image.highlight_context,&rectangle_info);
6094 case PolygonElement:
6095 case FillPolygonElement:
6097 if (number_coordinates > 1)
6098 (void) XDrawLines(display,windows->image.id,
6099 windows->image.highlight_context,coordinate_info,
6100 number_coordinates,CoordModeOrigin);
6102 XHighlightLine(display,windows->image.id,
6103 windows->image.highlight_context,&line_info);
6114 User has committed to element.
6116 line_info.x2=event.xbutton.x;
6117 line_info.y2=event.xbutton.y;
6118 rectangle_info.x=(ssize_t) event.xbutton.x;
6119 rectangle_info.y=(ssize_t) event.xbutton.y;
6120 coordinate_info[number_coordinates].x=event.xbutton.x;
6121 coordinate_info[number_coordinates].y=event.xbutton.y;
6122 if (((element != PolygonElement) &&
6123 (element != FillPolygonElement)) || (distance <= 9))
6128 number_coordinates++;
6129 if (number_coordinates < (int) max_coordinates)
6131 line_info.x1=event.xbutton.x;
6132 line_info.y1=event.xbutton.y;
6135 max_coordinates<<=1;
6136 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6137 max_coordinates,sizeof(*coordinate_info));
6138 if (coordinate_info == (XPoint *) NULL)
6139 (void) ThrowMagickException(exception,GetMagickModule(),
6140 ResourceLimitError,"MemoryAllocationFailed","'%s'","...");
6147 if (event.xmotion.window != windows->image.id)
6149 if (element != PointElement)
6151 line_info.x2=event.xmotion.x;
6152 line_info.y2=event.xmotion.y;
6153 rectangle_info.x=(ssize_t) event.xmotion.x;
6154 rectangle_info.y=(ssize_t) event.xmotion.y;
6157 coordinate_info[number_coordinates].x=event.xbutton.x;
6158 coordinate_info[number_coordinates].y=event.xbutton.y;
6159 number_coordinates++;
6160 if (number_coordinates < (int) max_coordinates)
6162 max_coordinates<<=1;
6163 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6164 max_coordinates,sizeof(*coordinate_info));
6165 if (coordinate_info == (XPoint *) NULL)
6166 (void) ThrowMagickException(exception,GetMagickModule(),
6167 ResourceLimitError,"MemoryAllocationFailed","'%s'","...");
6174 Check boundary conditions.
6176 if (line_info.x2 < 0)
6179 if (line_info.x2 > (int) windows->image.width)
6180 line_info.x2=(short) windows->image.width;
6181 if (line_info.y2 < 0)
6184 if (line_info.y2 > (int) windows->image.height)
6185 line_info.y2=(short) windows->image.height;
6186 distance=(unsigned int)
6187 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6188 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6189 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6190 ((state & ExitState) != 0))
6192 if (rectangle_info.x < 0)
6195 if (rectangle_info.x > (ssize_t) windows->image.width)
6196 rectangle_info.x=(ssize_t) windows->image.width;
6197 if ((int) rectangle_info.x < x)
6198 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6201 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6202 rectangle_info.x=(ssize_t) x;
6204 if (rectangle_info.y < 0)
6207 if (rectangle_info.y > (ssize_t) windows->image.height)
6208 rectangle_info.y=(ssize_t) windows->image.height;
6209 if ((int) rectangle_info.y < y)
6210 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6213 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6214 rectangle_info.y=(ssize_t) y;
6217 } while ((state & ExitState) == 0);
6218 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6219 if ((element == PointElement) || (element == PolygonElement) ||
6220 (element == FillPolygonElement))
6223 Determine polygon bounding box.
6225 rectangle_info.x=(ssize_t) coordinate_info->x;
6226 rectangle_info.y=(ssize_t) coordinate_info->y;
6227 x=coordinate_info->x;
6228 y=coordinate_info->y;
6229 for (i=1; i < number_coordinates; i++)
6231 if (coordinate_info[i].x > x)
6232 x=coordinate_info[i].x;
6233 if (coordinate_info[i].y > y)
6234 y=coordinate_info[i].y;
6235 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6236 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6237 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6238 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6240 rectangle_info.width=(size_t) (x-rectangle_info.x);
6241 rectangle_info.height=(size_t) (y-rectangle_info.y);
6242 for (i=0; i < number_coordinates; i++)
6244 coordinate_info[i].x-=rectangle_info.x;
6245 coordinate_info[i].y-=rectangle_info.y;
6252 if ((element == RectangleElement) ||
6253 (element == CircleElement) || (element == EllipseElement))
6255 rectangle_info.width--;
6256 rectangle_info.height--;
6259 Drawing is relative to image configuration.
6261 draw_info.x=(int) rectangle_info.x;
6262 draw_info.y=(int) rectangle_info.y;
6263 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6265 width=(unsigned int) (*image)->columns;
6266 height=(unsigned int) (*image)->rows;
6269 if (windows->image.crop_geometry != (char *) NULL)
6270 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6271 draw_info.x+=windows->image.x-(line_width/2);
6272 if (draw_info.x < 0)
6274 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6275 draw_info.y+=windows->image.y-(line_width/2);
6276 if (draw_info.y < 0)
6278 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6279 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6280 if (draw_info.width > (unsigned int) (*image)->columns)
6281 draw_info.width=(unsigned int) (*image)->columns;
6282 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6283 if (draw_info.height > (unsigned int) (*image)->rows)
6284 draw_info.height=(unsigned int) (*image)->rows;
6285 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6286 width*draw_info.width/windows->image.ximage->width,
6287 height*draw_info.height/windows->image.ximage->height,
6288 draw_info.x+x,draw_info.y+y);
6290 Initialize drawing attributes.
6292 draw_info.degrees=0.0;
6293 draw_info.element=element;
6294 draw_info.stipple=stipple;
6295 draw_info.line_width=line_width;
6296 draw_info.line_info=line_info;
6297 if (line_info.x1 > (int) (line_width/2))
6298 draw_info.line_info.x1=(short) line_width/2;
6299 if (line_info.y1 > (int) (line_width/2))
6300 draw_info.line_info.y1=(short) line_width/2;
6301 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6302 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6303 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6305 draw_info.line_info.x2=(-draw_info.line_info.x2);
6306 draw_info.line_info.y2=(-draw_info.line_info.y2);
6308 if (draw_info.line_info.x2 < 0)
6310 draw_info.line_info.x2=(-draw_info.line_info.x2);
6311 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6313 if (draw_info.line_info.y2 < 0)
6315 draw_info.line_info.y2=(-draw_info.line_info.y2);
6316 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6318 draw_info.rectangle_info=rectangle_info;
6319 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6320 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6321 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6322 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6323 draw_info.number_coordinates=(unsigned int) number_coordinates;
6324 draw_info.coordinate_info=coordinate_info;
6325 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6327 Draw element on image.
6329 XSetCursorState(display,windows,MagickTrue);
6330 XCheckRefreshWindows(display,windows);
6331 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6332 XSetCursorState(display,windows,MagickFalse);
6334 Update image colormap and return to image drawing.
6336 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6337 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6339 XSetCursorState(display,windows,MagickFalse);
6340 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6341 return(status != 0 ? MagickTrue : MagickFalse);
6345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6349 + X D r a w P a n R e c t a n g l e %
6353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6355 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6356 % displays a zoom image and the rectangle shows which portion of the image is
6357 % displayed in the Image window.
6359 % The format of the XDrawPanRectangle method is:
6361 % XDrawPanRectangle(Display *display,XWindows *windows)
6363 % A description of each parameter follows:
6365 % o display: Specifies a connection to an X server; returned from
6368 % o windows: Specifies a pointer to a XWindows structure.
6371 static void XDrawPanRectangle(Display *display,XWindows *windows)
6380 Determine dimensions of the panning rectangle.
6382 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
6383 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6384 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6385 scale_factor=(MagickRealType)
6386 windows->pan.height/windows->image.ximage->height;
6387 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6388 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6390 Display the panning rectangle.
6392 (void) XClearWindow(display,windows->pan.id);
6393 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6402 + X I m a g e C a c h e %
6406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6408 % XImageCache() handles the creation, manipulation, and destruction of the
6409 % image cache (undo and redo buffers).
6411 % The format of the XImageCache method is:
6413 % void XImageCache(Display *display,XResourceInfo *resource_info,
6414 % XWindows *windows,const CommandType command,Image **image,
6415 % ExceptionInfo *exception)
6417 % A description of each parameter follows:
6419 % o display: Specifies a connection to an X server; returned from
6422 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6424 % o windows: Specifies a pointer to a XWindows structure.
6426 % o command: Specifies a command to perform.
6428 % o image: the image; XImageCache may transform the image and return a new
6431 % o exception: return any errors or warnings in this structure.
6434 static void XImageCache(Display *display,XResourceInfo *resource_info,
6435 XWindows *windows,const CommandType command,Image **image,
6436 ExceptionInfo *exception)
6442 *redo_image = (Image *) NULL,
6443 *undo_image = (Image *) NULL;
6447 case FreeBuffersCommand:
6450 Free memory from the undo and redo cache.
6452 while (undo_image != (Image *) NULL)
6454 cache_image=undo_image;
6455 undo_image=GetPreviousImageInList(undo_image);
6456 cache_image->list=DestroyImage(cache_image->list);
6457 cache_image=DestroyImage(cache_image);
6459 undo_image=NewImageList();
6460 if (redo_image != (Image *) NULL)
6461 redo_image=DestroyImage(redo_image);
6462 redo_image=NewImageList();
6468 image_geometry[MaxTextExtent];
6471 Undo the last image transformation.
6473 if (undo_image == (Image *) NULL)
6475 (void) XBell(display,0);
6478 cache_image=undo_image;
6479 undo_image=GetPreviousImageInList(undo_image);
6480 windows->image.window_changes.width=(int) cache_image->columns;
6481 windows->image.window_changes.height=(int) cache_image->rows;
6482 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6483 windows->image.ximage->width,windows->image.ximage->height);
6484 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6486 if (windows->image.crop_geometry != (char *) NULL)
6487 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6488 windows->image.crop_geometry);
6489 windows->image.crop_geometry=cache_image->geometry;
6490 if (redo_image != (Image *) NULL)
6491 redo_image=DestroyImage(redo_image);
6492 redo_image=(*image);
6493 *image=cache_image->list;
6494 cache_image=DestroyImage(cache_image);
6495 if (windows->image.orphan != MagickFalse)
6497 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6498 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6504 case HalfSizeCommand:
6505 case OriginalSizeCommand:
6506 case DoubleSizeCommand:
6513 case RotateRightCommand:
6514 case RotateLeftCommand:
6519 case ContrastStretchCommand:
6520 case SigmoidalContrastCommand:
6521 case NormalizeCommand:
6522 case EqualizeCommand:
6524 case SaturationCommand:
6525 case BrightnessCommand:
6529 case GrayscaleCommand:
6531 case QuantizeCommand:
6532 case DespeckleCommand:
6534 case ReduceNoiseCommand:
6535 case AddNoiseCommand:
6536 case SharpenCommand:
6538 case ThresholdCommand:
6539 case EdgeDetectCommand:
6543 case SegmentCommand:
6544 case SolarizeCommand:
6545 case SepiaToneCommand:
6547 case ImplodeCommand:
6548 case VignetteCommand:
6550 case OilPaintCommand:
6551 case CharcoalDrawCommand:
6552 case AnnotateCommand:
6553 case AddBorderCommand:
6554 case AddFrameCommand:
6555 case CompositeCommand:
6556 case CommentCommand:
6558 case RegionofInterestCommand:
6559 case SaveToUndoBufferCommand:
6568 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6569 if (undo_image != (Image *) NULL)
6572 Ensure the undo cache has enough memory available.
6574 previous_image=undo_image;
6575 while (previous_image != (Image *) NULL)
6577 bytes+=previous_image->list->columns*previous_image->list->rows*
6579 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6581 previous_image=GetPreviousImageInList(previous_image);
6584 bytes-=previous_image->list->columns*previous_image->list->rows*
6586 if (previous_image == undo_image)
6587 undo_image=NewImageList();
6589 previous_image->next->previous=NewImageList();
6592 while (previous_image != (Image *) NULL)
6595 Delete any excess memory from undo cache.
6597 cache_image=previous_image;
6598 previous_image=GetPreviousImageInList(previous_image);
6599 cache_image->list=DestroyImage(cache_image->list);
6600 cache_image=DestroyImage(cache_image);
6603 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6606 Save image before transformations are applied.
6608 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6609 if (cache_image == (Image *) NULL)
6611 XSetCursorState(display,windows,MagickTrue);
6612 XCheckRefreshWindows(display,windows);
6613 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6614 XSetCursorState(display,windows,MagickFalse);
6615 if (cache_image->list == (Image *) NULL)
6617 cache_image=DestroyImage(cache_image);
6620 cache_image->columns=(size_t) windows->image.ximage->width;
6621 cache_image->rows=(size_t) windows->image.ximage->height;
6622 cache_image->geometry=windows->image.crop_geometry;
6623 if (windows->image.crop_geometry != (char *) NULL)
6625 cache_image->geometry=AcquireString((char *) NULL);
6626 (void) CopyMagickString(cache_image->geometry,
6627 windows->image.crop_geometry,MaxTextExtent);
6629 if (undo_image == (Image *) NULL)
6631 undo_image=cache_image;
6634 undo_image->next=cache_image;
6635 undo_image->next->previous=undo_image;
6636 undo_image=undo_image->next;
6642 if (command == RedoCommand)
6645 Redo the last image transformation.
6647 if (redo_image == (Image *) NULL)
6649 (void) XBell(display,0);
6652 windows->image.window_changes.width=(int) redo_image->columns;
6653 windows->image.window_changes.height=(int) redo_image->rows;
6654 if (windows->image.crop_geometry != (char *) NULL)
6655 windows->image.crop_geometry=(char *)
6656 RelinquishMagickMemory(windows->image.crop_geometry);
6657 windows->image.crop_geometry=redo_image->geometry;
6658 *image=DestroyImage(*image);
6660 redo_image=NewImageList();
6661 if (windows->image.orphan != MagickFalse)
6663 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6664 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6667 if (command != InfoCommand)
6672 XSetCursorState(display,windows,MagickTrue);
6673 XCheckRefreshWindows(display,windows);
6674 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6675 XSetCursorState(display,windows,MagickFalse);
6679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6683 + X I m a g e W i n d o w C o m m a n d %
6687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6689 % XImageWindowCommand() makes a transform to the image or Image window as
6690 % specified by a user menu button or keyboard command.
6692 % The format of the XImageWindowCommand method is:
6694 % CommandType XImageWindowCommand(Display *display,
6695 % XResourceInfo *resource_info,XWindows *windows,
6696 % const MagickStatusType state,KeySym key_symbol,Image **image,
6697 % ExceptionInfo *exception)
6699 % A description of each parameter follows:
6701 % o nexus: Method XImageWindowCommand returns an image when the
6702 % user chooses 'Open Image' from the command menu. Otherwise a null
6703 % image is returned.
6705 % o display: Specifies a connection to an X server; returned from
6708 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6710 % o windows: Specifies a pointer to a XWindows structure.
6712 % o state: key mask.
6714 % o key_symbol: Specifies a command to perform.
6716 % o image: the image; XImageWIndowCommand may transform the image and
6717 % return a new image pointer.
6719 % o exception: return any errors or warnings in this structure.
6722 static CommandType XImageWindowCommand(Display *display,
6723 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6724 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6727 delta[MaxTextExtent] = "";
6730 Digits[] = "01234567890";
6735 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6737 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6740 resource_info->quantum=1;
6742 last_symbol=key_symbol;
6743 delta[strlen(delta)+1]='\0';
6744 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6745 resource_info->quantum=StringToLong(delta);
6746 return(NullCommand);
6748 last_symbol=key_symbol;
6749 if (resource_info->immutable)
6752 Virtual image window has a restricted command set.
6757 return(InfoCommand);
6760 return(PrintCommand);
6762 return(NextCommand);
6765 return(QuitCommand);
6769 return(NullCommand);
6771 switch ((int) key_symbol)
6775 if ((state & ControlMask) == 0)
6777 return(OpenCommand);
6780 return(NextCommand);
6782 return(FormerCommand);
6785 if ((state & Mod1Mask) != 0)
6786 return(SwirlCommand);
6787 if ((state & ControlMask) == 0)
6788 return(ShearCommand);
6789 return(SaveCommand);
6794 if ((state & Mod1Mask) != 0)
6795 return(OilPaintCommand);
6796 if ((state & Mod4Mask) != 0)
6797 return(ColorCommand);
6798 if ((state & ControlMask) == 0)
6799 return(NullCommand);
6800 return(PrintCommand);
6804 if ((state & Mod4Mask) != 0)
6805 return(DrawCommand);
6806 if ((state & ControlMask) == 0)
6807 return(NullCommand);
6808 return(DeleteCommand);
6812 if ((state & ControlMask) == 0)
6813 return(NullCommand);
6814 return(SelectCommand);
6818 if ((state & ControlMask) == 0)
6819 return(NullCommand);
6824 return(QuitCommand);
6828 if ((state & ControlMask) == 0)
6829 return(NullCommand);
6830 return(UndoCommand);
6835 if ((state & ControlMask) == 0)
6836 return(RollCommand);
6837 return(RedoCommand);
6841 if ((state & ControlMask) == 0)
6842 return(NullCommand);
6847 if ((state & Mod1Mask) != 0)
6848 return(CharcoalDrawCommand);
6849 if ((state & ControlMask) == 0)
6850 return(CropCommand);
6851 return(CopyCommand);
6856 if ((state & Mod4Mask) != 0)
6857 return(CompositeCommand);
6858 if ((state & ControlMask) == 0)
6859 return(FlipCommand);
6860 return(PasteCommand);
6863 return(HalfSizeCommand);
6865 return(OriginalSizeCommand);
6867 return(DoubleSizeCommand);
6869 return(ResizeCommand);
6871 return(RefreshCommand);
6872 case XK_bracketleft:
6873 return(ChopCommand);
6875 return(FlopCommand);
6877 return(RotateRightCommand);
6879 return(RotateLeftCommand);
6881 return(RotateCommand);
6883 return(TrimCommand);
6887 return(SaturationCommand);
6889 return(BrightnessCommand);
6891 return(GammaCommand);
6893 return(SpiffCommand);
6895 return(DullCommand);
6897 return(NormalizeCommand);
6899 return(EqualizeCommand);
6901 return(NegateCommand);
6903 return(GrayscaleCommand);
6905 return(QuantizeCommand);
6907 return(DespeckleCommand);
6909 return(EmbossCommand);
6911 return(ReduceNoiseCommand);
6913 return(AddNoiseCommand);
6915 return(SharpenCommand);
6917 return(BlurCommand);
6919 return(ThresholdCommand);
6921 return(EdgeDetectCommand);
6923 return(SpreadCommand);
6925 return(ShadeCommand);
6927 return(RaiseCommand);
6929 return(SegmentCommand);
6932 if ((state & Mod1Mask) == 0)
6933 return(NullCommand);
6934 return(ImplodeCommand);
6938 if ((state & Mod1Mask) == 0)
6939 return(NullCommand);
6940 return(WaveCommand);
6944 if ((state & Mod4Mask) == 0)
6945 return(NullCommand);
6946 return(MatteCommand);
6950 if ((state & Mod4Mask) == 0)
6951 return(NullCommand);
6952 return(AddBorderCommand);
6956 if ((state & Mod4Mask) == 0)
6957 return(NullCommand);
6958 return(AddFrameCommand);
6962 if ((state & Mod4Mask) == 0)
6963 return(NullCommand);
6964 return(CommentCommand);
6968 if ((state & Mod1Mask) != 0)
6969 return(ApplyCommand);
6970 if ((state & Mod4Mask) != 0)
6971 return(AnnotateCommand);
6972 if ((state & ControlMask) == 0)
6973 return(NullCommand);
6974 return(RegionofInterestCommand);
6977 return(InfoCommand);
6979 return(ZoomCommand);
6982 if ((state & ShiftMask) == 0)
6983 return(NullCommand);
6984 return(ShowPreviewCommand);
6987 return(LaunchCommand);
6989 return(HelpCommand);
6991 return(BrowseDocumentationCommand);
6994 (void) XMapRaised(display,windows->command.id);
6995 return(NullCommand);
7002 XTranslateImage(display,windows,*image,key_symbol);
7003 return(NullCommand);
7014 if ((state & Mod1Mask) != 0)
7020 Trim one pixel from edge of image.
7024 crop_info.width=(size_t) windows->image.ximage->width;
7025 crop_info.height=(size_t) windows->image.ximage->height;
7026 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7028 if (resource_info->quantum >= (int) crop_info.height)
7029 resource_info->quantum=(int) crop_info.height-1;
7030 crop_info.height-=resource_info->quantum;
7032 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7034 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7035 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7036 crop_info.y+=resource_info->quantum;
7037 crop_info.height-=resource_info->quantum;
7039 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7041 if (resource_info->quantum >= (int) crop_info.width)
7042 resource_info->quantum=(int) crop_info.width-1;
7043 crop_info.width-=resource_info->quantum;
7045 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7047 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7048 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7049 crop_info.x+=resource_info->quantum;
7050 crop_info.width-=resource_info->quantum;
7052 if ((int) (windows->image.x+windows->image.width) >
7053 (int) crop_info.width)
7054 windows->image.x=(int) (crop_info.width-windows->image.width);
7055 if ((int) (windows->image.y+windows->image.height) >
7056 (int) crop_info.height)
7057 windows->image.y=(int) (crop_info.height-windows->image.height);
7058 XSetCropGeometry(display,windows,&crop_info,*image);
7059 windows->image.window_changes.width=(int) crop_info.width;
7060 windows->image.window_changes.height=(int) crop_info.height;
7061 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7062 (void) XConfigureImage(display,resource_info,windows,*image,
7064 return(NullCommand);
7066 XTranslateImage(display,windows,*image,key_symbol);
7067 return(NullCommand);
7070 return(NullCommand);
7072 return(NullCommand);
7076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7080 + X M a g i c k C o m m a n d %
7084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7086 % XMagickCommand() makes a transform to the image or Image window as
7087 % specified by a user menu button or keyboard command.
7089 % The format of the XMagickCommand method is:
7091 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7092 % XWindows *windows,const CommandType command,Image **image,
7093 % ExceptionInfo *exception)
7095 % A description of each parameter follows:
7097 % o display: Specifies a connection to an X server; returned from
7100 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7102 % o windows: Specifies a pointer to a XWindows structure.
7104 % o command: Specifies a command to perform.
7106 % o image: the image; XMagickCommand may transform the image and return a
7107 % new image pointer.
7109 % o exception: return any errors or warnings in this structure.
7112 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7113 XWindows *windows,const CommandType command,Image **image,
7114 ExceptionInfo *exception)
7117 filename[MaxTextExtent],
7118 geometry[MaxTextExtent],
7119 modulate_factors[MaxTextExtent];
7148 color[MaxTextExtent] = "gray";
7155 Process user command.
7157 XCheckRefreshWindows(display,windows);
7158 XImageCache(display,resource_info,windows,command,image,exception);
7159 nexus=NewImageList();
7160 windows->image.window_changes.width=windows->image.ximage->width;
7161 windows->image.window_changes.height=windows->image.ximage->height;
7162 image_info=CloneImageInfo(resource_info->image_info);
7163 SetGeometryInfo(&geometry_info);
7164 GetQuantizeInfo(&quantize_info);
7172 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7180 for (i=0; i < resource_info->quantum; i++)
7181 XClientMessage(display,windows->image.id,windows->im_protocols,
7182 windows->im_next_image,CurrentTime);
7188 Display former image.
7190 for (i=0; i < resource_info->quantum; i++)
7191 XClientMessage(display,windows->image.id,windows->im_protocols,
7192 windows->im_former_image,CurrentTime);
7203 status=chdir(resource_info->home_directory);
7205 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7206 "UnableToOpenFile","%s",resource_info->home_directory);
7207 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7215 status=XSaveImage(display,resource_info,windows,*image,exception);
7216 if (status == MagickFalse)
7219 message[MaxTextExtent];
7221 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7222 exception->reason != (char *) NULL ? exception->reason : "",
7223 exception->description != (char *) NULL ? exception->description :
7225 XNoticeWidget(display,windows,"Unable to save file:",message);
7235 status=XPrintImage(display,resource_info,windows,*image,exception);
7236 if (status == MagickFalse)
7239 message[MaxTextExtent];
7241 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7242 exception->reason != (char *) NULL ? exception->reason : "",
7243 exception->description != (char *) NULL ? exception->description :
7245 XNoticeWidget(display,windows,"Unable to print file:",message);
7253 filename[MaxTextExtent] = "\0";
7258 XFileBrowserWidget(display,windows,"Delete",filename);
7259 if (*filename == '\0')
7261 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
7262 if (status != MagickFalse)
7263 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7272 color[MaxTextExtent] = "gray",
7273 geometry[MaxTextExtent] = "640x480";
7276 *format = "gradient";
7279 Query user for canvas geometry.
7281 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7283 if (*geometry == '\0')
7287 XColorBrowserWidget(display,windows,"Select",color);
7293 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7294 "%s:%s",format,color);
7295 (void) CloneString(&image_info->size,geometry);
7296 nexus=ReadImage(image_info,exception);
7297 CatchException(exception);
7298 XClientMessage(display,windows->image.id,windows->im_protocols,
7299 windows->im_next_image,CurrentTime);
7302 case VisualDirectoryCommand:
7305 Visual Image directory.
7307 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7315 if (resource_info->confirm_exit == MagickFalse)
7316 XClientMessage(display,windows->image.id,windows->im_protocols,
7317 windows->im_exit,CurrentTime);
7324 Confirm program exit.
7326 status=XConfirmWidget(display,windows,"Do you really want to exit",
7327 resource_info->client_name);
7329 XClientMessage(display,windows->image.id,windows->im_protocols,
7330 windows->im_exit,CurrentTime);
7339 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7347 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7356 status=XPasteImage(display,resource_info,windows,*image,exception);
7357 if (status == MagickFalse)
7359 XNoticeWidget(display,windows,"Unable to paste X image",
7360 (*image)->filename);
7365 case HalfSizeCommand:
7370 windows->image.window_changes.width=windows->image.ximage->width/2;
7371 windows->image.window_changes.height=windows->image.ximage->height/2;
7372 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7375 case OriginalSizeCommand:
7378 Original image size.
7380 windows->image.window_changes.width=(int) (*image)->columns;
7381 windows->image.window_changes.height=(int) (*image)->rows;
7382 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7385 case DoubleSizeCommand:
7388 Double the image size.
7390 windows->image.window_changes.width=windows->image.ximage->width << 1;
7391 windows->image.window_changes.height=windows->image.ximage->height << 1;
7392 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7411 width=(size_t) windows->image.ximage->width;
7412 height=(size_t) windows->image.ximage->height;
7415 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7416 (double) width,(double) height);
7417 status=XDialogWidget(display,windows,"Resize",
7418 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7419 if (*geometry == '\0')
7422 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7423 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7424 windows->image.window_changes.width=(int) width;
7425 windows->image.window_changes.height=(int) height;
7426 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7432 image_geometry[MaxTextExtent];
7434 if ((windows->image.crop_geometry == (char *) NULL) &&
7435 ((int) (*image)->columns == windows->image.ximage->width) &&
7436 ((int) (*image)->rows == windows->image.ximage->height))
7439 Apply size transforms to image.
7441 XSetCursorState(display,windows,MagickTrue);
7442 XCheckRefreshWindows(display,windows);
7444 Crop and/or scale displayed image.
7446 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7447 windows->image.ximage->width,windows->image.ximage->height);
7448 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7450 if (windows->image.crop_geometry != (char *) NULL)
7451 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7452 windows->image.crop_geometry);
7455 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7456 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7459 case RefreshCommand:
7461 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7464 case RestoreCommand:
7467 Restore Image window to its original size.
7469 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7470 (windows->image.height == (unsigned int) (*image)->rows) &&
7471 (windows->image.crop_geometry == (char *) NULL))
7473 (void) XBell(display,0);
7476 windows->image.window_changes.width=(int) (*image)->columns;
7477 windows->image.window_changes.height=(int) (*image)->rows;
7478 if (windows->image.crop_geometry != (char *) NULL)
7480 windows->image.crop_geometry=(char *)
7481 RelinquishMagickMemory(windows->image.crop_geometry);
7482 windows->image.crop_geometry=(char *) NULL;
7486 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7487 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7495 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7504 status=XChopImage(display,resource_info,windows,image,exception);
7505 if (status == MagickFalse)
7507 XNoticeWidget(display,windows,"Unable to cut X image",
7508 (*image)->filename);
7519 Flop image scanlines.
7521 XSetCursorState(display,windows,MagickTrue);
7522 XCheckRefreshWindows(display,windows);
7523 flop_image=FlopImage(*image,exception);
7524 if (flop_image != (Image *) NULL)
7526 *image=DestroyImage(*image);
7529 CatchException(exception);
7530 XSetCursorState(display,windows,MagickFalse);
7531 if (windows->image.crop_geometry != (char *) NULL)
7536 width=(unsigned int) (*image)->columns;
7537 height=(unsigned int) (*image)->rows;
7538 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7540 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7541 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7543 if (windows->image.orphan != MagickFalse)
7545 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7554 Flip image scanlines.
7556 XSetCursorState(display,windows,MagickTrue);
7557 XCheckRefreshWindows(display,windows);
7558 flip_image=FlipImage(*image,exception);
7559 if (flip_image != (Image *) NULL)
7561 *image=DestroyImage(*image);
7564 CatchException(exception);
7565 XSetCursorState(display,windows,MagickFalse);
7566 if (windows->image.crop_geometry != (char *) NULL)
7571 width=(unsigned int) (*image)->columns;
7572 height=(unsigned int) (*image)->rows;
7573 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7575 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7576 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7578 if (windows->image.orphan != MagickFalse)
7580 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7583 case RotateRightCommand:
7586 Rotate image 90 degrees clockwise.
7588 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7589 if (status == MagickFalse)
7591 XNoticeWidget(display,windows,"Unable to rotate X image",
7592 (*image)->filename);
7597 case RotateLeftCommand:
7600 Rotate image 90 degrees counter-clockwise.
7602 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7603 if (status == MagickFalse)
7605 XNoticeWidget(display,windows,"Unable to rotate X image",
7606 (*image)->filename);
7616 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7617 if (status == MagickFalse)
7619 XNoticeWidget(display,windows,"Unable to rotate X image",
7620 (*image)->filename);
7631 geometry[MaxTextExtent] = "45.0x45.0";
7634 Query user for shear color and geometry.
7636 XColorBrowserWidget(display,windows,"Select",color);
7639 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7641 if (*geometry == '\0')
7646 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7648 XSetCursorState(display,windows,MagickTrue);
7649 XCheckRefreshWindows(display,windows);
7650 (void) QueryColorCompliance(color,AllCompliance,
7651 &(*image)->background_color,exception);
7652 flags=ParseGeometry(geometry,&geometry_info);
7653 if ((flags & SigmaValue) == 0)
7654 geometry_info.sigma=geometry_info.rho;
7655 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7657 if (shear_image != (Image *) NULL)
7659 *image=DestroyImage(*image);
7662 CatchException(exception);
7663 XSetCursorState(display,windows,MagickFalse);
7664 if (windows->image.orphan != MagickFalse)
7666 windows->image.window_changes.width=(int) (*image)->columns;
7667 windows->image.window_changes.height=(int) (*image)->rows;
7668 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7669 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7678 geometry[MaxTextExtent] = "+2+2";
7681 Query user for the roll geometry.
7683 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7685 if (*geometry == '\0')
7690 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7692 XSetCursorState(display,windows,MagickTrue);
7693 XCheckRefreshWindows(display,windows);
7694 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7696 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7698 if (roll_image != (Image *) NULL)
7700 *image=DestroyImage(*image);
7703 CatchException(exception);
7704 XSetCursorState(display,windows,MagickFalse);
7705 if (windows->image.orphan != MagickFalse)
7707 windows->image.window_changes.width=(int) (*image)->columns;
7708 windows->image.window_changes.height=(int) (*image)->rows;
7709 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7710 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7716 fuzz[MaxTextExtent];
7719 Query user for the fuzz factor.
7721 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7722 (*image)->fuzz/(QuantumRange+1.0));
7723 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7726 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+1.0);
7730 status=XTrimImage(display,resource_info,windows,*image,exception);
7731 if (status == MagickFalse)
7733 XNoticeWidget(display,windows,"Unable to trim X image",
7734 (*image)->filename);
7742 hue_percent[MaxTextExtent] = "110";
7745 Query user for percent hue change.
7747 (void) XDialogWidget(display,windows,"Apply",
7748 "Enter percent change in image hue (0-200):",hue_percent);
7749 if (*hue_percent == '\0')
7754 XSetCursorState(display,windows,MagickTrue);
7755 XCheckRefreshWindows(display,windows);
7756 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7757 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7759 (void) ModulateImage(*image,modulate_factors,exception);
7760 XSetCursorState(display,windows,MagickFalse);
7761 if (windows->image.orphan != MagickFalse)
7763 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7764 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7767 case SaturationCommand:
7770 saturation_percent[MaxTextExtent] = "110";
7773 Query user for percent saturation change.
7775 (void) XDialogWidget(display,windows,"Apply",
7776 "Enter percent change in color saturation (0-200):",saturation_percent);
7777 if (*saturation_percent == '\0')
7780 Vary color saturation.
7782 XSetCursorState(display,windows,MagickTrue);
7783 XCheckRefreshWindows(display,windows);
7784 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7785 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7787 (void) ModulateImage(*image,modulate_factors,exception);
7788 XSetCursorState(display,windows,MagickFalse);
7789 if (windows->image.orphan != MagickFalse)
7791 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7792 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7795 case BrightnessCommand:
7798 brightness_percent[MaxTextExtent] = "110";
7801 Query user for percent brightness change.
7803 (void) XDialogWidget(display,windows,"Apply",
7804 "Enter percent change in color brightness (0-200):",brightness_percent);
7805 if (*brightness_percent == '\0')
7808 Vary the color brightness.
7810 XSetCursorState(display,windows,MagickTrue);
7811 XCheckRefreshWindows(display,windows);
7812 (void) CopyMagickString(modulate_factors,brightness_percent,
7814 (void) ModulateImage(*image,modulate_factors,exception);
7815 XSetCursorState(display,windows,MagickFalse);
7816 if (windows->image.orphan != MagickFalse)
7818 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7819 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7825 factor[MaxTextExtent] = "1.6";
7828 Query user for gamma value.
7830 (void) XDialogWidget(display,windows,"Gamma",
7831 "Enter gamma value (e.g. 1.2):",factor);
7832 if (*factor == '\0')
7835 Gamma correct image.
7837 XSetCursorState(display,windows,MagickTrue);
7838 XCheckRefreshWindows(display,windows);
7839 (void) GammaImage(*image,atof(factor),exception);
7840 XSetCursorState(display,windows,MagickFalse);
7841 if (windows->image.orphan != MagickFalse)
7843 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7844 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7850 Sharpen the image contrast.
7852 XSetCursorState(display,windows,MagickTrue);
7853 XCheckRefreshWindows(display,windows);
7854 (void) ContrastImage(*image,MagickTrue,exception);
7855 XSetCursorState(display,windows,MagickFalse);
7856 if (windows->image.orphan != MagickFalse)
7858 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7859 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7865 Dull the image contrast.
7867 XSetCursorState(display,windows,MagickTrue);
7868 XCheckRefreshWindows(display,windows);
7869 (void) ContrastImage(*image,MagickFalse,exception);
7870 XSetCursorState(display,windows,MagickFalse);
7871 if (windows->image.orphan != MagickFalse)
7873 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7874 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7877 case ContrastStretchCommand:
7884 levels[MaxTextExtent] = "1%";
7887 Query user for gamma value.
7889 (void) XDialogWidget(display,windows,"Contrast Stretch",
7890 "Enter black and white points:",levels);
7891 if (*levels == '\0')
7894 Contrast stretch image.
7896 XSetCursorState(display,windows,MagickTrue);
7897 XCheckRefreshWindows(display,windows);
7898 flags=ParseGeometry(levels,&geometry_info);
7899 black_point=geometry_info.rho;
7900 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7901 if ((flags & PercentValue) != 0)
7903 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7904 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7906 white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point;
7907 (void) ContrastStretchImage(*image,black_point,white_point,
7909 XSetCursorState(display,windows,MagickFalse);
7910 if (windows->image.orphan != MagickFalse)
7912 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7913 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7916 case SigmoidalContrastCommand:
7925 levels[MaxTextExtent] = "3x50%";
7928 Query user for gamma value.
7930 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7931 "Enter contrast and midpoint:",levels);
7932 if (*levels == '\0')
7935 Contrast stretch image.
7937 XSetCursorState(display,windows,MagickTrue);
7938 XCheckRefreshWindows(display,windows);
7939 flags=ParseGeometry(levels,&geometry_info);
7940 if ((flags & SigmaValue) == 0)
7941 geometry_info.sigma=1.0*QuantumRange/2.0;
7942 if ((flags & PercentValue) != 0)
7943 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7944 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7945 geometry_info.sigma,exception);
7946 XSetCursorState(display,windows,MagickFalse);
7947 if (windows->image.orphan != MagickFalse)
7949 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7950 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7953 case NormalizeCommand:
7956 Perform histogram normalization on the image.
7958 XSetCursorState(display,windows,MagickTrue);
7959 XCheckRefreshWindows(display,windows);
7960 (void) NormalizeImage(*image,exception);
7961 XSetCursorState(display,windows,MagickFalse);
7962 if (windows->image.orphan != MagickFalse)
7964 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7965 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7968 case EqualizeCommand:
7971 Perform histogram equalization on the image.
7973 XSetCursorState(display,windows,MagickTrue);
7974 XCheckRefreshWindows(display,windows);
7975 (void) EqualizeImage(*image,exception);
7976 XSetCursorState(display,windows,MagickFalse);
7977 if (windows->image.orphan != MagickFalse)
7979 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7980 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7986 Negate colors in image.
7988 XSetCursorState(display,windows,MagickTrue);
7989 XCheckRefreshWindows(display,windows);
7990 (void) NegateImage(*image,MagickFalse,exception);
7991 XSetCursorState(display,windows,MagickFalse);
7992 if (windows->image.orphan != MagickFalse)
7994 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7995 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7998 case GrayscaleCommand:
8001 Convert image to grayscale.
8003 XSetCursorState(display,windows,MagickTrue);
8004 XCheckRefreshWindows(display,windows);
8005 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
8006 GrayscaleType : GrayscaleMatteType,exception);
8007 XSetCursorState(display,windows,MagickFalse);
8008 if (windows->image.orphan != MagickFalse)
8010 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8011 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8020 filename[MaxTextExtent] = "\0";
8023 Request image file name from user.
8025 XFileBrowserWidget(display,windows,"Map",filename);
8026 if (*filename == '\0')
8031 XSetCursorState(display,windows,MagickTrue);
8032 XCheckRefreshWindows(display,windows);
8033 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8034 affinity_image=ReadImage(image_info,exception);
8035 if (affinity_image != (Image *) NULL)
8037 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8038 affinity_image=DestroyImage(affinity_image);
8040 CatchException(exception);
8041 XSetCursorState(display,windows,MagickFalse);
8042 if (windows->image.orphan != MagickFalse)
8044 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8045 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8048 case QuantizeCommand:
8054 colors[MaxTextExtent] = "256";
8057 Query user for maximum number of colors.
8059 status=XDialogWidget(display,windows,"Quantize",
8060 "Maximum number of colors:",colors);
8061 if (*colors == '\0')
8064 Color reduce the image.
8066 XSetCursorState(display,windows,MagickTrue);
8067 XCheckRefreshWindows(display,windows);
8068 quantize_info.number_colors=StringToUnsignedLong(colors);
8069 quantize_info.dither_method=status != 0 ? RiemersmaDitherMethod :
8071 (void) QuantizeImage(&quantize_info,*image,exception);
8072 XSetCursorState(display,windows,MagickFalse);
8073 if (windows->image.orphan != MagickFalse)
8075 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8076 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8079 case DespeckleCommand:
8087 XSetCursorState(display,windows,MagickTrue);
8088 XCheckRefreshWindows(display,windows);
8089 despeckle_image=DespeckleImage(*image,exception);
8090 if (despeckle_image != (Image *) NULL)
8092 *image=DestroyImage(*image);
8093 *image=despeckle_image;
8095 CatchException(exception);
8096 XSetCursorState(display,windows,MagickFalse);
8097 if (windows->image.orphan != MagickFalse)
8099 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8100 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8109 radius[MaxTextExtent] = "0.0x1.0";
8112 Query user for emboss radius.
8114 (void) XDialogWidget(display,windows,"Emboss",
8115 "Enter the emboss radius and standard deviation:",radius);
8116 if (*radius == '\0')
8119 Reduce noise in the image.
8121 XSetCursorState(display,windows,MagickTrue);
8122 XCheckRefreshWindows(display,windows);
8123 flags=ParseGeometry(radius,&geometry_info);
8124 if ((flags & SigmaValue) == 0)
8125 geometry_info.sigma=1.0;
8126 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8128 if (emboss_image != (Image *) NULL)
8130 *image=DestroyImage(*image);
8131 *image=emboss_image;
8133 CatchException(exception);
8134 XSetCursorState(display,windows,MagickFalse);
8135 if (windows->image.orphan != MagickFalse)
8137 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8138 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8141 case ReduceNoiseCommand:
8147 radius[MaxTextExtent] = "0";
8150 Query user for noise radius.
8152 (void) XDialogWidget(display,windows,"Reduce Noise",
8153 "Enter the noise radius:",radius);
8154 if (*radius == '\0')
8157 Reduce noise in the image.
8159 XSetCursorState(display,windows,MagickTrue);
8160 XCheckRefreshWindows(display,windows);
8161 flags=ParseGeometry(radius,&geometry_info);
8162 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8163 geometry_info.rho,(size_t) geometry_info.rho,exception);
8164 if (noise_image != (Image *) NULL)
8166 *image=DestroyImage(*image);
8169 CatchException(exception);
8170 XSetCursorState(display,windows,MagickFalse);
8171 if (windows->image.orphan != MagickFalse)
8173 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8174 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8177 case AddNoiseCommand:
8186 noise_type[MaxTextExtent] = "Gaussian";
8189 Add noise to the image.
8191 noises=GetCommandOptions(MagickNoiseOptions);
8192 if (noises == (char **) NULL)
8194 XListBrowserWidget(display,windows,&windows->widget,
8195 (const char **) noises,"Add Noise",
8196 "Select a type of noise to add to your image:",noise_type);
8197 noises=DestroyStringList(noises);
8198 if (*noise_type == '\0')
8200 XSetCursorState(display,windows,MagickTrue);
8201 XCheckRefreshWindows(display,windows);
8202 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8203 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8204 if (noise_image != (Image *) NULL)
8206 *image=DestroyImage(*image);
8209 CatchException(exception);
8210 XSetCursorState(display,windows,MagickFalse);
8211 if (windows->image.orphan != MagickFalse)
8213 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8214 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8217 case SharpenCommand:
8223 radius[MaxTextExtent] = "0.0x1.0";
8226 Query user for sharpen radius.
8228 (void) XDialogWidget(display,windows,"Sharpen",
8229 "Enter the sharpen radius and standard deviation:",radius);
8230 if (*radius == '\0')
8233 Sharpen image scanlines.
8235 XSetCursorState(display,windows,MagickTrue);
8236 XCheckRefreshWindows(display,windows);
8237 flags=ParseGeometry(radius,&geometry_info);
8238 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8240 if (sharp_image != (Image *) NULL)
8242 *image=DestroyImage(*image);
8245 CatchException(exception);
8246 XSetCursorState(display,windows,MagickFalse);
8247 if (windows->image.orphan != MagickFalse)
8249 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8250 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8259 radius[MaxTextExtent] = "0.0x1.0";
8262 Query user for blur radius.
8264 (void) XDialogWidget(display,windows,"Blur",
8265 "Enter the blur radius and standard deviation:",radius);
8266 if (*radius == '\0')
8271 XSetCursorState(display,windows,MagickTrue);
8272 XCheckRefreshWindows(display,windows);
8273 flags=ParseGeometry(radius,&geometry_info);
8274 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8276 if (blur_image != (Image *) NULL)
8278 *image=DestroyImage(*image);
8281 CatchException(exception);
8282 XSetCursorState(display,windows,MagickFalse);
8283 if (windows->image.orphan != MagickFalse)
8285 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8286 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8289 case ThresholdCommand:
8295 factor[MaxTextExtent] = "128";
8298 Query user for threshold value.
8300 (void) XDialogWidget(display,windows,"Threshold",
8301 "Enter threshold value:",factor);
8302 if (*factor == '\0')
8305 Gamma correct image.
8307 XSetCursorState(display,windows,MagickTrue);
8308 XCheckRefreshWindows(display,windows);
8309 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8310 (void) BilevelImage(*image,threshold,exception);
8311 XSetCursorState(display,windows,MagickFalse);
8312 if (windows->image.orphan != MagickFalse)
8314 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8315 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8318 case EdgeDetectCommand:
8324 radius[MaxTextExtent] = "0";
8327 Query user for edge factor.
8329 (void) XDialogWidget(display,windows,"Detect Edges",
8330 "Enter the edge detect radius:",radius);
8331 if (*radius == '\0')
8334 Detect edge in image.
8336 XSetCursorState(display,windows,MagickTrue);
8337 XCheckRefreshWindows(display,windows);
8338 flags=ParseGeometry(radius,&geometry_info);
8339 edge_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8341 if (edge_image != (Image *) NULL)
8343 *image=DestroyImage(*image);
8346 CatchException(exception);
8347 XSetCursorState(display,windows,MagickFalse);
8348 if (windows->image.orphan != MagickFalse)
8350 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8351 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8360 amount[MaxTextExtent] = "2";
8363 Query user for spread amount.
8365 (void) XDialogWidget(display,windows,"Spread",
8366 "Enter the displacement amount:",amount);
8367 if (*amount == '\0')
8370 Displace image pixels by a random amount.
8372 XSetCursorState(display,windows,MagickTrue);
8373 XCheckRefreshWindows(display,windows);
8374 flags=ParseGeometry(amount,&geometry_info);
8375 spread_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8377 if (spread_image != (Image *) NULL)
8379 *image=DestroyImage(*image);
8380 *image=spread_image;
8382 CatchException(exception);
8383 XSetCursorState(display,windows,MagickFalse);
8384 if (windows->image.orphan != MagickFalse)
8386 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8387 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8399 geometry[MaxTextExtent] = "30x30";
8402 Query user for the shade geometry.
8404 status=XDialogWidget(display,windows,"Shade",
8405 "Enter the azimuth and elevation of the light source:",geometry);
8406 if (*geometry == '\0')
8411 XSetCursorState(display,windows,MagickTrue);
8412 XCheckRefreshWindows(display,windows);
8413 flags=ParseGeometry(geometry,&geometry_info);
8414 if ((flags & SigmaValue) == 0)
8415 geometry_info.sigma=1.0;
8416 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
8417 geometry_info.rho,geometry_info.sigma,exception);
8418 if (shade_image != (Image *) NULL)
8420 *image=DestroyImage(*image);
8423 CatchException(exception);
8424 XSetCursorState(display,windows,MagickFalse);
8425 if (windows->image.orphan != MagickFalse)
8427 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8428 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8434 bevel_width[MaxTextExtent] = "10";
8437 Query user for bevel width.
8439 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8440 if (*bevel_width == '\0')
8445 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8447 XSetCursorState(display,windows,MagickTrue);
8448 XCheckRefreshWindows(display,windows);
8449 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8451 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8452 XSetCursorState(display,windows,MagickFalse);
8453 if (windows->image.orphan != MagickFalse)
8455 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8456 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8459 case SegmentCommand:
8462 threshold[MaxTextExtent] = "1.0x1.5";
8465 Query user for smoothing threshold.
8467 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8469 if (*threshold == '\0')
8474 XSetCursorState(display,windows,MagickTrue);
8475 XCheckRefreshWindows(display,windows);
8476 flags=ParseGeometry(threshold,&geometry_info);
8477 if ((flags & SigmaValue) == 0)
8478 geometry_info.sigma=1.0;
8479 (void) SegmentImage(*image,sRGBColorspace,MagickFalse,geometry_info.rho,
8480 geometry_info.sigma,exception);
8481 XSetCursorState(display,windows,MagickFalse);
8482 if (windows->image.orphan != MagickFalse)
8484 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8485 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8488 case SepiaToneCommand:
8497 factor[MaxTextExtent] = "80%";
8500 Query user for sepia-tone factor.
8502 (void) XDialogWidget(display,windows,"Sepia Tone",
8503 "Enter the sepia tone factor (0 - 99.9%):",factor);
8504 if (*factor == '\0')
8507 Sepia tone image pixels.
8509 XSetCursorState(display,windows,MagickTrue);
8510 XCheckRefreshWindows(display,windows);
8511 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8512 sepia_image=SepiaToneImage(*image,threshold,exception);
8513 if (sepia_image != (Image *) NULL)
8515 *image=DestroyImage(*image);
8518 CatchException(exception);
8519 XSetCursorState(display,windows,MagickFalse);
8520 if (windows->image.orphan != MagickFalse)
8522 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8523 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8526 case SolarizeCommand:
8532 factor[MaxTextExtent] = "60%";
8535 Query user for solarize factor.
8537 (void) XDialogWidget(display,windows,"Solarize",
8538 "Enter the solarize factor (0 - 99.9%):",factor);
8539 if (*factor == '\0')
8542 Solarize image pixels.
8544 XSetCursorState(display,windows,MagickTrue);
8545 XCheckRefreshWindows(display,windows);
8546 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8547 (void) SolarizeImage(*image,threshold,exception);
8548 XSetCursorState(display,windows,MagickFalse);
8549 if (windows->image.orphan != MagickFalse)
8551 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8552 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8561 degrees[MaxTextExtent] = "60";
8564 Query user for swirl angle.
8566 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8568 if (*degrees == '\0')
8571 Swirl image pixels about the center.
8573 XSetCursorState(display,windows,MagickTrue);
8574 XCheckRefreshWindows(display,windows);
8575 flags=ParseGeometry(degrees,&geometry_info);
8576 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8578 if (swirl_image != (Image *) NULL)
8580 *image=DestroyImage(*image);
8583 CatchException(exception);
8584 XSetCursorState(display,windows,MagickFalse);
8585 if (windows->image.orphan != MagickFalse)
8587 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8588 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8591 case ImplodeCommand:
8597 factor[MaxTextExtent] = "0.3";
8600 Query user for implode factor.
8602 (void) XDialogWidget(display,windows,"Implode",
8603 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8604 if (*factor == '\0')
8607 Implode image pixels about the center.
8609 XSetCursorState(display,windows,MagickTrue);
8610 XCheckRefreshWindows(display,windows);
8611 flags=ParseGeometry(factor,&geometry_info);
8612 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8614 if (implode_image != (Image *) NULL)
8616 *image=DestroyImage(*image);
8617 *image=implode_image;
8619 CatchException(exception);
8620 XSetCursorState(display,windows,MagickFalse);
8621 if (windows->image.orphan != MagickFalse)
8623 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8624 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8627 case VignetteCommand:
8633 geometry[MaxTextExtent] = "0x20";
8636 Query user for the vignette geometry.
8638 (void) XDialogWidget(display,windows,"Vignette",
8639 "Enter the radius, sigma, and x and y offsets:",geometry);
8640 if (*geometry == '\0')
8643 Soften the edges of the image in vignette style
8645 XSetCursorState(display,windows,MagickTrue);
8646 XCheckRefreshWindows(display,windows);
8647 flags=ParseGeometry(geometry,&geometry_info);
8648 if ((flags & SigmaValue) == 0)
8649 geometry_info.sigma=1.0;
8650 if ((flags & XiValue) == 0)
8651 geometry_info.xi=0.1*(*image)->columns;
8652 if ((flags & PsiValue) == 0)
8653 geometry_info.psi=0.1*(*image)->rows;
8654 vignette_image=VignetteImage(*image,geometry_info.rho,0.0,(ssize_t)
8655 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
8657 if (vignette_image != (Image *) NULL)
8659 *image=DestroyImage(*image);
8660 *image=vignette_image;
8662 CatchException(exception);
8663 XSetCursorState(display,windows,MagickFalse);
8664 if (windows->image.orphan != MagickFalse)
8666 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8667 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8676 geometry[MaxTextExtent] = "25x150";
8679 Query user for the wave geometry.
8681 (void) XDialogWidget(display,windows,"Wave",
8682 "Enter the amplitude and length of the wave:",geometry);
8683 if (*geometry == '\0')
8686 Alter an image along a sine wave.
8688 XSetCursorState(display,windows,MagickTrue);
8689 XCheckRefreshWindows(display,windows);
8690 flags=ParseGeometry(geometry,&geometry_info);
8691 if ((flags & SigmaValue) == 0)
8692 geometry_info.sigma=1.0;
8693 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8694 (*image)->interpolate,exception);
8695 if (wave_image != (Image *) NULL)
8697 *image=DestroyImage(*image);
8700 CatchException(exception);
8701 XSetCursorState(display,windows,MagickFalse);
8702 if (windows->image.orphan != MagickFalse)
8704 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8705 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8708 case OilPaintCommand:
8714 radius[MaxTextExtent] = "0";
8717 Query user for circular neighborhood radius.
8719 (void) XDialogWidget(display,windows,"Oil Paint",
8720 "Enter the mask radius:",radius);
8721 if (*radius == '\0')
8724 OilPaint image scanlines.
8726 XSetCursorState(display,windows,MagickTrue);
8727 XCheckRefreshWindows(display,windows);
8728 flags=ParseGeometry(radius,&geometry_info);
8729 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8731 if (paint_image != (Image *) NULL)
8733 *image=DestroyImage(*image);
8736 CatchException(exception);
8737 XSetCursorState(display,windows,MagickFalse);
8738 if (windows->image.orphan != MagickFalse)
8740 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8741 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8744 case CharcoalDrawCommand:
8750 radius[MaxTextExtent] = "0x1";
8753 Query user for charcoal radius.
8755 (void) XDialogWidget(display,windows,"Charcoal Draw",
8756 "Enter the charcoal radius and sigma:",radius);
8757 if (*radius == '\0')
8762 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8764 XSetCursorState(display,windows,MagickTrue);
8765 XCheckRefreshWindows(display,windows);
8766 flags=ParseGeometry(radius,&geometry_info);
8767 if ((flags & SigmaValue) == 0)
8768 geometry_info.sigma=geometry_info.rho;
8769 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8771 if (charcoal_image != (Image *) NULL)
8773 *image=DestroyImage(*image);
8774 *image=charcoal_image;
8776 CatchException(exception);
8777 XSetCursorState(display,windows,MagickFalse);
8778 if (windows->image.orphan != MagickFalse)
8780 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8781 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8784 case AnnotateCommand:
8787 Annotate the image with text.
8789 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8790 if (status == MagickFalse)
8792 XNoticeWidget(display,windows,"Unable to annotate X image",
8793 (*image)->filename);
8803 status=XDrawEditImage(display,resource_info,windows,image,exception);
8804 if (status == MagickFalse)
8806 XNoticeWidget(display,windows,"Unable to draw on the X image",
8807 (*image)->filename);
8817 status=XColorEditImage(display,resource_info,windows,image,exception);
8818 if (status == MagickFalse)
8820 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8821 (*image)->filename);
8831 status=XMatteEditImage(display,resource_info,windows,image,exception);
8832 if (status == MagickFalse)
8834 XNoticeWidget(display,windows,"Unable to matte edit X image",
8835 (*image)->filename);
8840 case CompositeCommand:
8845 status=XCompositeImage(display,resource_info,windows,*image,
8847 if (status == MagickFalse)
8849 XNoticeWidget(display,windows,"Unable to composite X image",
8850 (*image)->filename);
8855 case AddBorderCommand:
8861 geometry[MaxTextExtent] = "6x6";
8864 Query user for border color and geometry.
8866 XColorBrowserWidget(display,windows,"Select",color);
8869 (void) XDialogWidget(display,windows,"Add Border",
8870 "Enter border geometry:",geometry);
8871 if (*geometry == '\0')
8874 Add a border to the image.
8876 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8878 XSetCursorState(display,windows,MagickTrue);
8879 XCheckRefreshWindows(display,windows);
8880 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8882 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8884 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8886 if (border_image != (Image *) NULL)
8888 *image=DestroyImage(*image);
8889 *image=border_image;
8891 CatchException(exception);
8892 XSetCursorState(display,windows,MagickFalse);
8893 if (windows->image.orphan != MagickFalse)
8895 windows->image.window_changes.width=(int) (*image)->columns;
8896 windows->image.window_changes.height=(int) (*image)->rows;
8897 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8898 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8901 case AddFrameCommand:
8910 geometry[MaxTextExtent] = "6x6";
8913 Query user for frame color and geometry.
8915 XColorBrowserWidget(display,windows,"Select",color);
8918 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8920 if (*geometry == '\0')
8923 Surround image with an ornamental border.
8925 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8927 XSetCursorState(display,windows,MagickTrue);
8928 XCheckRefreshWindows(display,windows);
8929 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8931 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8933 frame_info.width=page_geometry.width;
8934 frame_info.height=page_geometry.height;
8935 frame_info.outer_bevel=page_geometry.x;
8936 frame_info.inner_bevel=page_geometry.y;
8937 frame_info.x=(ssize_t) frame_info.width;
8938 frame_info.y=(ssize_t) frame_info.height;
8939 frame_info.width=(*image)->columns+2*frame_info.width;
8940 frame_info.height=(*image)->rows+2*frame_info.height;
8941 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8942 if (frame_image != (Image *) NULL)
8944 *image=DestroyImage(*image);
8947 CatchException(exception);
8948 XSetCursorState(display,windows,MagickFalse);
8949 if (windows->image.orphan != MagickFalse)
8951 windows->image.window_changes.width=(int) (*image)->columns;
8952 windows->image.window_changes.height=(int) (*image)->rows;
8953 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8954 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8957 case CommentCommand:
8971 unique_file=AcquireUniqueFileResource(image_info->filename);
8972 if (unique_file == -1)
8973 XNoticeWidget(display,windows,"Unable to edit image comment",
8974 image_info->filename);
8975 value=GetImageProperty(*image,"comment",exception);
8976 if (value == (char *) NULL)
8977 unique_file=close(unique_file)-1;
8983 file=fdopen(unique_file,"w");
8984 if (file == (FILE *) NULL)
8986 XNoticeWidget(display,windows,"Unable to edit image comment",
8987 image_info->filename);
8990 for (p=value; *p != '\0'; p++)
8991 (void) fputc((int) *p,file);
8992 (void) fputc('\n',file);
8993 (void) fclose(file);
8995 XSetCursorState(display,windows,MagickTrue);
8996 XCheckRefreshWindows(display,windows);
8997 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
8999 if (status == MagickFalse)
9000 XNoticeWidget(display,windows,"Unable to edit image comment",
9007 comment=FileToString(image_info->filename,~0UL,exception);
9008 if (comment != (char *) NULL)
9010 (void) SetImageProperty(*image,"comment",comment,exception);
9011 (*image)->taint=MagickTrue;
9014 (void) RelinquishUniqueFileResource(image_info->filename);
9015 XSetCursorState(display,windows,MagickFalse);
9023 XSetCursorState(display,windows,MagickTrue);
9024 XCheckRefreshWindows(display,windows);
9025 (void) AcquireUniqueFilename(filename);
9026 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9028 status=WriteImage(image_info,*image,exception);
9029 if (status == MagickFalse)
9030 XNoticeWidget(display,windows,"Unable to launch image editor",
9034 nexus=ReadImage(resource_info->image_info,exception);
9035 CatchException(exception);
9036 XClientMessage(display,windows->image.id,windows->im_protocols,
9037 windows->im_next_image,CurrentTime);
9039 (void) RelinquishUniqueFileResource(filename);
9040 XSetCursorState(display,windows,MagickFalse);
9043 case RegionofInterestCommand:
9046 Apply an image processing technique to a region of interest.
9048 (void) XROIImage(display,resource_info,windows,image,exception);
9058 if (windows->magnify.mapped != MagickFalse)
9059 (void) XRaiseWindow(display,windows->magnify.id);
9065 XSetCursorState(display,windows,MagickTrue);
9066 (void) XMapRaised(display,windows->magnify.id);
9067 XSetCursorState(display,windows,MagickFalse);
9071 case ShowPreviewCommand:
9080 preview_type[MaxTextExtent] = "Gamma";
9083 Select preview type from menu.
9085 previews=GetCommandOptions(MagickPreviewOptions);
9086 if (previews == (char **) NULL)
9088 XListBrowserWidget(display,windows,&windows->widget,
9089 (const char **) previews,"Preview",
9090 "Select an enhancement, effect, or F/X:",preview_type);
9091 previews=DestroyStringList(previews);
9092 if (*preview_type == '\0')
9097 XSetCursorState(display,windows,MagickTrue);
9098 XCheckRefreshWindows(display,windows);
9099 image_info->preview_type=(PreviewType)
9100 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9101 image_info->group=(ssize_t) windows->image.id;
9102 (void) DeleteImageProperty(*image,"label");
9103 (void) SetImageProperty(*image,"label","Preview",exception);
9104 (void) AcquireUniqueFilename(filename);
9105 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9107 status=WriteImage(image_info,*image,exception);
9108 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9109 preview_image=ReadImage(image_info,exception);
9110 (void) RelinquishUniqueFileResource(filename);
9111 if (preview_image == (Image *) NULL)
9113 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9115 status=WriteImage(image_info,preview_image,exception);
9116 preview_image=DestroyImage(preview_image);
9117 if (status == MagickFalse)
9118 XNoticeWidget(display,windows,"Unable to show image preview",
9119 (*image)->filename);
9120 XDelay(display,1500);
9121 XSetCursorState(display,windows,MagickFalse);
9124 case ShowHistogramCommand:
9130 Show image histogram.
9132 XSetCursorState(display,windows,MagickTrue);
9133 XCheckRefreshWindows(display,windows);
9134 image_info->group=(ssize_t) windows->image.id;
9135 (void) DeleteImageProperty(*image,"label");
9136 (void) SetImageProperty(*image,"label","Histogram",exception);
9137 (void) AcquireUniqueFilename(filename);
9138 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9140 status=WriteImage(image_info,*image,exception);
9141 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9142 histogram_image=ReadImage(image_info,exception);
9143 (void) RelinquishUniqueFileResource(filename);
9144 if (histogram_image == (Image *) NULL)
9146 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9147 "show:%s",filename);
9148 status=WriteImage(image_info,histogram_image,exception);
9149 histogram_image=DestroyImage(histogram_image);
9150 if (status == MagickFalse)
9151 XNoticeWidget(display,windows,"Unable to show histogram",
9152 (*image)->filename);
9153 XDelay(display,1500);
9154 XSetCursorState(display,windows,MagickFalse);
9157 case ShowMatteCommand:
9162 if ((*image)->matte == MagickFalse)
9164 XNoticeWidget(display,windows,
9165 "Image does not have any matte information",(*image)->filename);
9171 XSetCursorState(display,windows,MagickTrue);
9172 XCheckRefreshWindows(display,windows);
9173 image_info->group=(ssize_t) windows->image.id;
9174 (void) DeleteImageProperty(*image,"label");
9175 (void) SetImageProperty(*image,"label","Matte",exception);
9176 (void) AcquireUniqueFilename(filename);
9177 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9179 status=WriteImage(image_info,*image,exception);
9180 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9181 matte_image=ReadImage(image_info,exception);
9182 (void) RelinquishUniqueFileResource(filename);
9183 if (matte_image == (Image *) NULL)
9185 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9187 status=WriteImage(image_info,matte_image,exception);
9188 matte_image=DestroyImage(matte_image);
9189 if (status == MagickFalse)
9190 XNoticeWidget(display,windows,"Unable to show matte",
9191 (*image)->filename);
9192 XDelay(display,1500);
9193 XSetCursorState(display,windows,MagickFalse);
9196 case BackgroundCommand:
9201 status=XBackgroundImage(display,resource_info,windows,image,exception);
9202 if (status == MagickFalse)
9204 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9205 if (nexus != (Image *) NULL)
9206 XClientMessage(display,windows->image.id,windows->im_protocols,
9207 windows->im_next_image,CurrentTime);
9210 case SlideShowCommand:
9213 delay[MaxTextExtent] = "5";
9216 Display next image after pausing.
9218 (void) XDialogWidget(display,windows,"Slide Show",
9219 "Pause how many 1/100ths of a second between images:",delay);
9222 resource_info->delay=StringToUnsignedLong(delay);
9223 XClientMessage(display,windows->image.id,windows->im_protocols,
9224 windows->im_next_image,CurrentTime);
9227 case PreferencesCommand:
9230 Set user preferences.
9232 status=XPreferencesWidget(display,resource_info,windows);
9233 if (status == MagickFalse)
9235 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9236 if (nexus != (Image *) NULL)
9237 XClientMessage(display,windows->image.id,windows->im_protocols,
9238 windows->im_next_image,CurrentTime);
9244 User requested help.
9246 XTextViewWidget(display,resource_info,windows,MagickFalse,
9247 "Help Viewer - Display",DisplayHelp);
9250 case BrowseDocumentationCommand:
9260 Browse the ImageMagick documentation.
9262 root_window=XRootWindow(display,XDefaultScreen(display));
9263 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9264 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9265 if (mozilla_window != (Window) NULL)
9268 command[MaxTextExtent],
9272 Display documentation using Netscape remote control.
9274 url=GetMagickHomeURL();
9275 (void) FormatLocaleString(command,MaxTextExtent,
9276 "openurl(%s,new-tab)",url);
9277 url=DestroyString(url);
9278 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9279 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9280 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9281 XSetCursorState(display,windows,MagickFalse);
9284 XSetCursorState(display,windows,MagickTrue);
9285 XCheckRefreshWindows(display,windows);
9286 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9288 if (status == MagickFalse)
9289 XNoticeWidget(display,windows,"Unable to browse documentation",
9291 XDelay(display,1500);
9292 XSetCursorState(display,windows,MagickFalse);
9295 case VersionCommand:
9297 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9298 GetMagickCopyright());
9301 case SaveToUndoBufferCommand:
9305 (void) XBell(display,0);
9309 image_info=DestroyImageInfo(image_info);
9314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9318 + X M a g n i f y I m a g e %
9322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9324 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9325 % The magnified portion is displayed in a separate window.
9327 % The format of the XMagnifyImage method is:
9329 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9330 % ExceptionInfo *exception)
9332 % A description of each parameter follows:
9334 % o display: Specifies a connection to an X server; returned from
9337 % o windows: Specifies a pointer to a XWindows structure.
9339 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9340 % the entire image is refreshed.
9342 % o exception: return any errors or warnings in this structure.
9345 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9346 ExceptionInfo *exception)
9349 text[MaxTextExtent];
9359 Update magnified image until the mouse button is released.
9361 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9365 windows->magnify.x=(int) windows->image.x+x;
9366 windows->magnify.y=(int) windows->image.y+y;
9370 Map and unmap Info widget as text cursor crosses its boundaries.
9372 if (windows->info.mapped != MagickFalse)
9374 if ((x < (int) (windows->info.x+windows->info.width)) &&
9375 (y < (int) (windows->info.y+windows->info.height)))
9376 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9379 if ((x > (int) (windows->info.x+windows->info.width)) ||
9380 (y > (int) (windows->info.y+windows->info.height)))
9381 (void) XMapWindow(display,windows->info.id);
9382 if (windows->info.mapped != MagickFalse)
9385 Display pointer position.
9387 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9388 windows->magnify.x,windows->magnify.y);
9389 XInfoWidget(display,windows,text);
9392 Wait for next event.
9394 XScreenEvent(display,windows,event,exception);
9395 switch (event->type)
9402 User has finished magnifying image.
9421 Check boundary conditions.
9426 if (x >= (int) windows->image.width)
9427 x=(int) windows->image.width-1;
9431 if (y >= (int) windows->image.height)
9432 y=(int) windows->image.height-1;
9433 } while ((state & ExitState) == 0);
9435 Display magnified image.
9437 XSetCursorState(display,windows,MagickFalse);
9441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9445 + X M a g n i f y W i n d o w C o m m a n d %
9449 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9451 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9452 % pixel as specified by the key symbol.
9454 % The format of the XMagnifyWindowCommand method is:
9456 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9457 % const MagickStatusType state,const KeySym key_symbol,
9458 % ExceptionInfo *exception)
9460 % A description of each parameter follows:
9462 % o display: Specifies a connection to an X server; returned from
9465 % o windows: Specifies a pointer to a XWindows structure.
9467 % o state: key mask.
9469 % o key_symbol: Specifies a KeySym which indicates which side of the image
9472 % o exception: return any errors or warnings in this structure.
9475 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9476 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9482 User specified a magnify factor or position.
9485 if ((state & Mod1Mask) != 0)
9487 switch ((int) key_symbol)
9491 (void) XWithdrawWindow(display,windows->magnify.id,
9492 windows->magnify.screen);
9498 windows->magnify.x=(int) windows->image.width/2;
9499 windows->magnify.y=(int) windows->image.height/2;
9505 if (windows->magnify.x > 0)
9506 windows->magnify.x-=quantum;
9512 if (windows->magnify.y > 0)
9513 windows->magnify.y-=quantum;
9519 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9520 windows->magnify.x+=quantum;
9526 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9527 windows->magnify.y+=quantum;
9541 windows->magnify.data=(key_symbol-XK_0);
9555 windows->magnify.data=(key_symbol-XK_KP_0);
9561 XMakeMagnifyImage(display,windows,exception);
9565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9569 + X M a k e P a n I m a g e %
9573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9575 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9578 % The format of the XMakePanImage method is:
9580 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9581 % XWindows *windows,Image *image,ExceptionInfo *exception)
9583 % A description of each parameter follows:
9585 % o display: Specifies a connection to an X server; returned from
9588 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9590 % o windows: Specifies a pointer to a XWindows structure.
9592 % o image: the image.
9594 % o exception: return any errors or warnings in this structure.
9597 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9598 XWindows *windows,Image *image,ExceptionInfo *exception)
9604 Create and display image for panning icon.
9606 XSetCursorState(display,windows,MagickTrue);
9607 XCheckRefreshWindows(display,windows);
9608 windows->pan.x=(int) windows->image.x;
9609 windows->pan.y=(int) windows->image.y;
9610 status=XMakeImage(display,resource_info,&windows->pan,image,
9611 windows->pan.width,windows->pan.height,exception);
9612 if (status == MagickFalse)
9613 ThrowXWindowFatalException(ResourceLimitError,
9614 "MemoryAllocationFailed",image->filename);
9615 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9616 windows->pan.pixmap);
9617 (void) XClearWindow(display,windows->pan.id);
9618 XDrawPanRectangle(display,windows);
9619 XSetCursorState(display,windows,MagickFalse);
9623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9627 + X M a t t a E d i t I m a g e %
9631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9633 % XMatteEditImage() allows the user to interactively change the Matte channel
9634 % of an image. If the image is PseudoClass it is promoted to DirectClass
9635 % before the matte information is stored.
9637 % The format of the XMatteEditImage method is:
9639 % MagickBooleanType XMatteEditImage(Display *display,
9640 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9641 % ExceptionInfo *exception)
9643 % A description of each parameter follows:
9645 % o display: Specifies a connection to an X server; returned from
9648 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9650 % o windows: Specifies a pointer to a XWindows structure.
9652 % o image: the image; returned from ReadImage.
9654 % o exception: return any errors or warnings in this structure.
9657 static MagickBooleanType XMatteEditImage(Display *display,
9658 XResourceInfo *resource_info,XWindows *windows,Image **image,
9659 ExceptionInfo *exception)
9662 matte[MaxTextExtent] = "0";
9677 static const ModeType
9678 MatteEditCommands[] =
9681 MatteEditBorderCommand,
9682 MatteEditFuzzCommand,
9683 MatteEditValueCommand,
9684 MatteEditUndoCommand,
9685 MatteEditHelpCommand,
9686 MatteEditDismissCommand
9690 method = PointMethod;
9693 border_color = { 0, 0, 0, 0, 0, 0 };
9696 command[MaxTextExtent],
9697 text[MaxTextExtent];
9729 (void) CloneString(&windows->command.name,"Matte Edit");
9730 windows->command.data=4;
9731 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9732 (void) XMapRaised(display,windows->command.id);
9733 XClientMessage(display,windows->image.id,windows->im_protocols,
9734 windows->im_update_widget,CurrentTime);
9738 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9739 resource_info->background_color,resource_info->foreground_color);
9740 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9742 Track pointer until button 1 is pressed.
9744 XQueryPosition(display,windows->image.id,&x,&y);
9745 (void) XSelectInput(display,windows->image.id,
9746 windows->image.attributes.event_mask | PointerMotionMask);
9750 if (windows->info.mapped != MagickFalse)
9753 Display pointer position.
9755 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9756 x+windows->image.x,y+windows->image.y);
9757 XInfoWidget(display,windows,text);
9760 Wait for next event.
9762 XScreenEvent(display,windows,&event,exception);
9763 if (event.xany.window == windows->command.id)
9766 Select a command from the Command widget.
9768 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9771 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9774 switch (MatteEditCommands[id])
9776 case MatteEditMethod:
9782 Select a method from the pop-up menu.
9784 methods=GetCommandOptions(MagickMethodOptions);
9785 if (methods == (char **) NULL)
9787 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9788 (const char **) methods,command);
9790 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9791 MagickFalse,methods[entry]);
9792 methods=DestroyStringList(methods);
9795 case MatteEditBorderCommand:
9798 *ColorMenu[MaxNumberPens];
9804 Initialize menu selections.
9806 for (i=0; i < (int) (MaxNumberPens-2); i++)
9807 ColorMenu[i]=resource_info->pen_colors[i];
9808 ColorMenu[MaxNumberPens-2]="Browser...";
9809 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9811 Select a pen color from the pop-up menu.
9813 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9814 (const char **) ColorMenu,command);
9817 if (pen_number == (MaxNumberPens-2))
9820 color_name[MaxTextExtent] = "gray";
9823 Select a pen color from a dialog.
9825 resource_info->pen_colors[pen_number]=color_name;
9826 XColorBrowserWidget(display,windows,"Select",color_name);
9827 if (*color_name == '\0')
9833 (void) XParseColor(display,windows->map_info->colormap,
9834 resource_info->pen_colors[pen_number],&border_color);
9837 case MatteEditFuzzCommand:
9840 fuzz[MaxTextExtent];
9855 Select a command from the pop-up menu.
9857 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9863 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9867 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9868 (void) XDialogWidget(display,windows,"Ok",
9869 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9872 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9873 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9877 case MatteEditValueCommand:
9880 message[MaxTextExtent];
9892 Select a command from the pop-up menu.
9894 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9900 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9902 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9903 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9904 (Quantum) TransparentAlpha);
9907 (void) FormatLocaleString(message,MaxTextExtent,
9908 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9910 (void) XDialogWidget(display,windows,"Matte",message,matte);
9915 case MatteEditUndoCommand:
9917 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9921 case MatteEditHelpCommand:
9923 XTextViewWidget(display,resource_info,windows,MagickFalse,
9924 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9927 case MatteEditDismissCommand:
9939 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9946 if (event.xbutton.button != Button1)
9948 if ((event.xbutton.window != windows->image.id) &&
9949 (event.xbutton.window != windows->magnify.id))
9956 (void) XMagickCommand(display,resource_info,windows,
9957 SaveToUndoBufferCommand,image,exception);
9958 state|=UpdateConfigurationState;
9963 if (event.xbutton.button != Button1)
9965 if ((event.xbutton.window != windows->image.id) &&
9966 (event.xbutton.window != windows->magnify.id))
9969 Update colormap information.
9973 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9974 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9975 XInfoWidget(display,windows,text);
9976 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9977 state&=(~UpdateConfigurationState);
9985 command[MaxTextExtent];
9990 if (event.xkey.window == windows->magnify.id)
9995 window=windows->magnify.id;
9996 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
9998 if (event.xkey.window != windows->image.id)
10001 Respond to a user key press.
10003 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10004 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10005 switch ((int) key_symbol)
10019 XTextViewWidget(display,resource_info,windows,MagickFalse,
10020 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10025 (void) XBell(display,0);
10034 Map and unmap Info widget as cursor crosses its boundaries.
10038 if (windows->info.mapped != MagickFalse)
10040 if ((x < (int) (windows->info.x+windows->info.width)) &&
10041 (y < (int) (windows->info.y+windows->info.height)))
10042 (void) XWithdrawWindow(display,windows->info.id,
10043 windows->info.screen);
10046 if ((x > (int) (windows->info.x+windows->info.width)) ||
10047 (y > (int) (windows->info.y+windows->info.height)))
10048 (void) XMapWindow(display,windows->info.id);
10054 if (event.xany.window == windows->magnify.id)
10056 x=windows->magnify.x-windows->image.x;
10057 y=windows->magnify.y-windows->image.y;
10061 if ((state & UpdateConfigurationState) != 0)
10071 Matte edit is relative to image configuration.
10073 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10075 XPutPixel(windows->image.ximage,x_offset,y_offset,
10076 windows->pixel_info->background_color.pixel);
10077 width=(unsigned int) (*image)->columns;
10078 height=(unsigned int) (*image)->rows;
10081 if (windows->image.crop_geometry != (char *) NULL)
10082 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10084 x_offset=(int) (width*(windows->image.x+x_offset)/
10085 windows->image.ximage->width+x);
10086 y_offset=(int) (height*(windows->image.y+y_offset)/
10087 windows->image.ximage->height+y);
10088 if ((x_offset < 0) || (y_offset < 0))
10090 if ((x_offset >= (int) (*image)->columns) ||
10091 (y_offset >= (int) (*image)->rows))
10093 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10094 return(MagickFalse);
10095 if ((*image)->matte == MagickFalse)
10096 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10097 image_view=AcquireAuthenticCacheView(*image,exception);
10104 Update matte information using point algorithm.
10106 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10107 (ssize_t) y_offset,1,1,exception);
10108 if (q == (Quantum *) NULL)
10110 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10111 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10114 case ReplaceMethod:
10121 Update matte information using replace algorithm.
10123 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
10124 x_offset,(ssize_t) y_offset,&target,exception);
10125 for (y=0; y < (int) (*image)->rows; y++)
10127 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10128 (*image)->columns,1,exception);
10129 if (q == (Quantum *) NULL)
10131 for (x=0; x < (int) (*image)->columns; x++)
10133 GetPixelInfoPixel(*image,q,&pixel);
10134 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10135 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10136 q+=GetPixelChannels(*image);
10138 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10143 case FloodfillMethod:
10144 case FillToBorderMethod:
10156 Update matte information using floodfill algorithm.
10158 (void) GetOneVirtualPixelInfo(*image,
10159 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10160 y_offset,&target,exception);
10161 if (method == FillToBorderMethod)
10163 target.red=(MagickRealType) ScaleShortToQuantum(
10165 target.green=(MagickRealType) ScaleShortToQuantum(
10166 border_color.green);
10167 target.blue=(MagickRealType) ScaleShortToQuantum(
10168 border_color.blue);
10170 draw_info=CloneDrawInfo(resource_info->image_info,
10171 (DrawInfo *) NULL);
10172 draw_info->fill.alpha=(MagickRealType) ClampToQuantum(
10173 StringToDouble(matte,(char **) NULL));
10174 channel_mask=SetPixelChannelMask(*image,AlphaChannel);
10175 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10176 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
10177 MagickFalse : MagickTrue,exception);
10178 (void) SetPixelChannelMapMask(*image,channel_mask);
10179 draw_info=DestroyDrawInfo(draw_info);
10185 Update matte information using reset algorithm.
10187 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10188 return(MagickFalse);
10189 for (y=0; y < (int) (*image)->rows; y++)
10191 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10192 (*image)->columns,1,exception);
10193 if (q == (Quantum *) NULL)
10195 for (x=0; x < (int) (*image)->columns; x++)
10197 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10198 q+=GetPixelChannels(*image);
10200 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10203 if (StringToLong(matte) == (long) OpaqueAlpha)
10204 (*image)->matte=MagickFalse;
10208 image_view=DestroyCacheView(image_view);
10209 state&=(~UpdateConfigurationState);
10211 } while ((state & ExitState) == 0);
10212 (void) XSelectInput(display,windows->image.id,
10213 windows->image.attributes.event_mask);
10214 XSetCursorState(display,windows,MagickFalse);
10215 (void) XFreeCursor(display,cursor);
10216 return(MagickTrue);
10220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10224 + X O p e n I m a g e %
10228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10230 % XOpenImage() loads an image from a file.
10232 % The format of the XOpenImage method is:
10234 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10235 % XWindows *windows,const unsigned int command)
10237 % A description of each parameter follows:
10239 % o display: Specifies a connection to an X server; returned from
10242 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10244 % o windows: Specifies a pointer to a XWindows structure.
10246 % o command: A value other than zero indicates that the file is selected
10247 % from the command line argument list.
10250 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10251 XWindows *windows,const MagickBooleanType command)
10266 filename[MaxTextExtent] = "\0";
10269 Request file name from user.
10271 if (command == MagickFalse)
10272 XFileBrowserWidget(display,windows,"Open",filename);
10288 Select next image from the command line.
10290 status=XGetCommand(display,windows->image.id,&files,&count);
10293 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10294 return((Image *) NULL);
10296 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10297 if (filelist == (char **) NULL)
10299 ThrowXWindowFatalException(ResourceLimitError,
10300 "MemoryAllocationFailed","...");
10301 (void) XFreeStringList(files);
10302 return((Image *) NULL);
10305 for (i=1; i < count; i++)
10306 if (*files[i] != '-')
10307 filelist[j++]=files[i];
10308 filelist[j]=(char *) NULL;
10309 XListBrowserWidget(display,windows,&windows->widget,
10310 (const char **) filelist,"Load","Select Image to Load:",filename);
10311 filelist=(char **) RelinquishMagickMemory(filelist);
10312 (void) XFreeStringList(files);
10314 if (*filename == '\0')
10315 return((Image *) NULL);
10316 image_info=CloneImageInfo(resource_info->image_info);
10317 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10319 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10320 exception=AcquireExceptionInfo();
10321 (void) SetImageInfo(image_info,0,exception);
10322 if (LocaleCompare(image_info->magick,"X") == 0)
10325 seconds[MaxTextExtent];
10328 User may want to delay the X server screen grab.
10330 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10331 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10333 if (*seconds == '\0')
10334 return((Image *) NULL);
10335 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10337 magick_info=GetMagickInfo(image_info->magick,exception);
10338 if ((magick_info != (const MagickInfo *) NULL) &&
10339 (magick_info->raw != MagickFalse))
10342 geometry[MaxTextExtent];
10345 Request image size from the user.
10347 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10348 if (image_info->size != (char *) NULL)
10349 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10350 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10352 (void) CloneString(&image_info->size,geometry);
10357 XSetCursorState(display,windows,MagickTrue);
10358 XCheckRefreshWindows(display,windows);
10359 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10360 nexus=ReadImage(image_info,exception);
10361 CatchException(exception);
10362 XSetCursorState(display,windows,MagickFalse);
10363 if (nexus != (Image *) NULL)
10364 XClientMessage(display,windows->image.id,windows->im_protocols,
10365 windows->im_next_image,CurrentTime);
10373 Unknown image format.
10375 text=FileToString(filename,~0,exception);
10376 if (text == (char *) NULL)
10377 return((Image *) NULL);
10378 textlist=StringToList(text);
10379 if (textlist != (char **) NULL)
10382 title[MaxTextExtent];
10387 (void) FormatLocaleString(title,MaxTextExtent,
10388 "Unknown format: %s",filename);
10389 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10390 (const char **) textlist);
10391 for (i=0; textlist[i] != (char *) NULL; i++)
10392 textlist[i]=DestroyString(textlist[i]);
10393 textlist=(char **) RelinquishMagickMemory(textlist);
10395 text=DestroyString(text);
10397 exception=DestroyExceptionInfo(exception);
10398 image_info=DestroyImageInfo(image_info);
10403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10407 + X P a n I m a g e %
10411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10413 % XPanImage() pans the image until the mouse button is released.
10415 % The format of the XPanImage method is:
10417 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10418 % ExceptionInfo *exception)
10420 % A description of each parameter follows:
10422 % o display: Specifies a connection to an X server; returned from
10425 % o windows: Specifies a pointer to a XWindows structure.
10427 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10428 % the entire image is refreshed.
10430 % o exception: return any errors or warnings in this structure.
10433 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10434 ExceptionInfo *exception)
10437 text[MaxTextExtent];
10455 if ((windows->image.ximage->width > (int) windows->image.width) &&
10456 (windows->image.ximage->height > (int) windows->image.height))
10457 cursor=XCreateFontCursor(display,XC_fleur);
10459 if (windows->image.ximage->width > (int) windows->image.width)
10460 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10462 if (windows->image.ximage->height > (int) windows->image.height)
10463 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10465 cursor=XCreateFontCursor(display,XC_arrow);
10466 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10468 Pan image as pointer moves until the mouse button is released.
10470 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10471 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10472 pan_info.width=windows->pan.width*windows->image.width/
10473 windows->image.ximage->width;
10474 pan_info.height=windows->pan.height*windows->image.height/
10475 windows->image.ximage->height;
10478 state=UpdateConfigurationState;
10481 switch (event->type)
10486 User choose an initial pan location.
10488 pan_info.x=(ssize_t) event->xbutton.x;
10489 pan_info.y=(ssize_t) event->xbutton.y;
10490 state|=UpdateConfigurationState;
10493 case ButtonRelease:
10496 User has finished panning the image.
10498 pan_info.x=(ssize_t) event->xbutton.x;
10499 pan_info.y=(ssize_t) event->xbutton.y;
10500 state|=UpdateConfigurationState | ExitState;
10505 pan_info.x=(ssize_t) event->xmotion.x;
10506 pan_info.y=(ssize_t) event->xmotion.y;
10507 state|=UpdateConfigurationState;
10512 if ((state & UpdateConfigurationState) != 0)
10515 Check boundary conditions.
10517 if (pan_info.x < (ssize_t) (pan_info.width/2))
10520 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10521 if (pan_info.x < 0)
10524 if ((int) (pan_info.x+windows->image.width) >
10525 windows->image.ximage->width)
10526 pan_info.x=(ssize_t)
10527 (windows->image.ximage->width-windows->image.width);
10528 if (pan_info.y < (ssize_t) (pan_info.height/2))
10531 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10532 if (pan_info.y < 0)
10535 if ((int) (pan_info.y+windows->image.height) >
10536 windows->image.ximage->height)
10537 pan_info.y=(ssize_t)
10538 (windows->image.ximage->height-windows->image.height);
10539 if ((windows->image.x != (int) pan_info.x) ||
10540 (windows->image.y != (int) pan_info.y))
10543 Display image pan offset.
10545 windows->image.x=(int) pan_info.x;
10546 windows->image.y=(int) pan_info.y;
10547 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10548 windows->image.width,windows->image.height,windows->image.x,
10550 XInfoWidget(display,windows,text);
10552 Refresh Image window.
10554 XDrawPanRectangle(display,windows);
10555 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10557 state&=(~UpdateConfigurationState);
10560 Wait for next event.
10562 if ((state & ExitState) == 0)
10563 XScreenEvent(display,windows,event,exception);
10564 } while ((state & ExitState) == 0);
10568 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10569 (void) XFreeCursor(display,cursor);
10570 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10578 + X P a s t e I m a g e %
10582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10584 % XPasteImage() pastes an image previously saved with XCropImage in the X
10585 % window image at a location the user chooses with the pointer.
10587 % The format of the XPasteImage method is:
10589 % MagickBooleanType XPasteImage(Display *display,
10590 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10591 % ExceptionInfo *exception)
10593 % A description of each parameter follows:
10595 % o display: Specifies a connection to an X server; returned from
10598 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10600 % o windows: Specifies a pointer to a XWindows structure.
10602 % o image: the image; returned from ReadImage.
10604 % o exception: return any errors or warnings in this structure.
10607 static MagickBooleanType XPasteImage(Display *display,
10608 XResourceInfo *resource_info,XWindows *windows,Image *image,
10609 ExceptionInfo *exception)
10620 static const ModeType
10623 PasteOperatorsCommand,
10625 PasteDismissCommand
10628 static CompositeOperator
10629 compose = CopyCompositeOp;
10632 text[MaxTextExtent];
10666 if (resource_info->copy_image == (Image *) NULL)
10667 return(MagickFalse);
10668 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10670 Map Command widget.
10672 (void) CloneString(&windows->command.name,"Paste");
10673 windows->command.data=1;
10674 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10675 (void) XMapRaised(display,windows->command.id);
10676 XClientMessage(display,windows->image.id,windows->im_protocols,
10677 windows->im_update_widget,CurrentTime);
10679 Track pointer until button 1 is pressed.
10681 XSetCursorState(display,windows,MagickFalse);
10682 XQueryPosition(display,windows->image.id,&x,&y);
10683 (void) XSelectInput(display,windows->image.id,
10684 windows->image.attributes.event_mask | PointerMotionMask);
10685 paste_info.x=(ssize_t) windows->image.x+x;
10686 paste_info.y=(ssize_t) windows->image.y+y;
10687 paste_info.width=0;
10688 paste_info.height=0;
10689 cursor=XCreateFontCursor(display,XC_ul_angle);
10690 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10691 state=DefaultState;
10694 if (windows->info.mapped != MagickFalse)
10697 Display pointer position.
10699 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10700 (long) paste_info.x,(long) paste_info.y);
10701 XInfoWidget(display,windows,text);
10703 highlight_info=paste_info;
10704 highlight_info.x=paste_info.x-windows->image.x;
10705 highlight_info.y=paste_info.y-windows->image.y;
10706 XHighlightRectangle(display,windows->image.id,
10707 windows->image.highlight_context,&highlight_info);
10709 Wait for next event.
10711 XScreenEvent(display,windows,&event,exception);
10712 XHighlightRectangle(display,windows->image.id,
10713 windows->image.highlight_context,&highlight_info);
10714 if (event.xany.window == windows->command.id)
10717 Select a command from the Command widget.
10719 id=XCommandWidget(display,windows,PasteMenu,&event);
10722 switch (PasteCommands[id])
10724 case PasteOperatorsCommand:
10727 command[MaxTextExtent],
10731 Select a command from the pop-up menu.
10733 operators=GetCommandOptions(MagickComposeOptions);
10734 if (operators == (char **) NULL)
10736 entry=XMenuWidget(display,windows,PasteMenu[id],
10737 (const char **) operators,command);
10739 compose=(CompositeOperator) ParseCommandOption(
10740 MagickComposeOptions,MagickFalse,operators[entry]);
10741 operators=DestroyStringList(operators);
10744 case PasteHelpCommand:
10746 XTextViewWidget(display,resource_info,windows,MagickFalse,
10747 "Help Viewer - Image Composite",ImagePasteHelp);
10750 case PasteDismissCommand:
10755 state|=EscapeState;
10764 switch (event.type)
10768 if (image->debug != MagickFalse)
10769 (void) LogMagickEvent(X11Event,GetMagickModule(),
10770 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10771 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10772 if (event.xbutton.button != Button1)
10774 if (event.xbutton.window != windows->image.id)
10777 Paste rectangle is relative to image configuration.
10779 width=(unsigned int) image->columns;
10780 height=(unsigned int) image->rows;
10783 if (windows->image.crop_geometry != (char *) NULL)
10784 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10786 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10787 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10788 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10789 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10790 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10791 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10792 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10795 case ButtonRelease:
10797 if (image->debug != MagickFalse)
10798 (void) LogMagickEvent(X11Event,GetMagickModule(),
10799 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10800 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10801 if (event.xbutton.button != Button1)
10803 if (event.xbutton.window != windows->image.id)
10805 if ((paste_info.width != 0) && (paste_info.height != 0))
10808 User has selected the location of the paste image.
10810 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10811 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10821 command[MaxTextExtent];
10829 if (event.xkey.window != windows->image.id)
10832 Respond to a user key press.
10834 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10835 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10836 *(command+length)='\0';
10837 if (image->debug != MagickFalse)
10838 (void) LogMagickEvent(X11Event,GetMagickModule(),
10839 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10840 switch ((int) key_symbol)
10848 paste_image=DestroyImage(paste_image);
10849 state|=EscapeState;
10856 (void) XSetFunction(display,windows->image.highlight_context,
10858 XTextViewWidget(display,resource_info,windows,MagickFalse,
10859 "Help Viewer - Image Composite",ImagePasteHelp);
10860 (void) XSetFunction(display,windows->image.highlight_context,
10866 (void) XBell(display,0);
10875 Map and unmap Info widget as text cursor crosses its boundaries.
10879 if (windows->info.mapped != MagickFalse)
10881 if ((x < (int) (windows->info.x+windows->info.width)) &&
10882 (y < (int) (windows->info.y+windows->info.height)))
10883 (void) XWithdrawWindow(display,windows->info.id,
10884 windows->info.screen);
10887 if ((x > (int) (windows->info.x+windows->info.width)) ||
10888 (y > (int) (windows->info.y+windows->info.height)))
10889 (void) XMapWindow(display,windows->info.id);
10890 paste_info.x=(ssize_t) windows->image.x+x;
10891 paste_info.y=(ssize_t) windows->image.y+y;
10896 if (image->debug != MagickFalse)
10897 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10902 } while ((state & ExitState) == 0);
10903 (void) XSelectInput(display,windows->image.id,
10904 windows->image.attributes.event_mask);
10905 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10906 XSetCursorState(display,windows,MagickFalse);
10907 (void) XFreeCursor(display,cursor);
10908 if ((state & EscapeState) != 0)
10909 return(MagickTrue);
10911 Image pasting is relative to image configuration.
10913 XSetCursorState(display,windows,MagickTrue);
10914 XCheckRefreshWindows(display,windows);
10915 width=(unsigned int) image->columns;
10916 height=(unsigned int) image->rows;
10919 if (windows->image.crop_geometry != (char *) NULL)
10920 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10921 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10923 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10924 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10925 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10927 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10928 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10930 Paste image with X Image window.
10932 (void) CompositeImage(image,paste_image,compose,MagickTrue,paste_info.x,
10933 paste_info.y,exception);
10934 paste_image=DestroyImage(paste_image);
10935 XSetCursorState(display,windows,MagickFalse);
10937 Update image colormap.
10939 XConfigureImageColormap(display,resource_info,windows,image,exception);
10940 (void) XConfigureImage(display,resource_info,windows,image,exception);
10941 return(MagickTrue);
10945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10949 + X P r i n t I m a g e %
10953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10955 % XPrintImage() prints an image to a Postscript printer.
10957 % The format of the XPrintImage method is:
10959 % MagickBooleanType XPrintImage(Display *display,
10960 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10961 % ExceptionInfo *exception)
10963 % A description of each parameter follows:
10965 % o display: Specifies a connection to an X server; returned from
10968 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10970 % o windows: Specifies a pointer to a XWindows structure.
10972 % o image: the image.
10974 % o exception: return any errors or warnings in this structure.
10977 static MagickBooleanType XPrintImage(Display *display,
10978 XResourceInfo *resource_info,XWindows *windows,Image *image,
10979 ExceptionInfo *exception)
10982 filename[MaxTextExtent],
10983 geometry[MaxTextExtent];
10995 Request Postscript page geometry from user.
10997 image_info=CloneImageInfo(resource_info->image_info);
10998 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
10999 if (image_info->page != (char *) NULL)
11000 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11001 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11002 "Select Postscript Page Geometry:",geometry);
11003 if (*geometry == '\0')
11004 return(MagickTrue);
11005 image_info->page=GetPageGeometry(geometry);
11007 Apply image transforms.
11009 XSetCursorState(display,windows,MagickTrue);
11010 XCheckRefreshWindows(display,windows);
11011 print_image=CloneImage(image,0,0,MagickTrue,exception);
11012 if (print_image == (Image *) NULL)
11013 return(MagickFalse);
11014 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11015 windows->image.ximage->width,windows->image.ximage->height);
11016 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11021 (void) AcquireUniqueFilename(filename);
11022 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11024 status=WriteImage(image_info,print_image,exception);
11025 (void) RelinquishUniqueFileResource(filename);
11026 print_image=DestroyImage(print_image);
11027 image_info=DestroyImageInfo(image_info);
11028 XSetCursorState(display,windows,MagickFalse);
11029 return(status != 0 ? MagickTrue : MagickFalse);
11033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11037 + X R O I I m a g e %
11041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11043 % XROIImage() applies an image processing technique to a region of interest.
11045 % The format of the XROIImage method is:
11047 % MagickBooleanType XROIImage(Display *display,
11048 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11049 % ExceptionInfo *exception)
11051 % A description of each parameter follows:
11053 % o display: Specifies a connection to an X server; returned from
11056 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11058 % o windows: Specifies a pointer to a XWindows structure.
11060 % o image: the image; returned from ReadImage.
11062 % o exception: return any errors or warnings in this structure.
11065 static MagickBooleanType XROIImage(Display *display,
11066 XResourceInfo *resource_info,XWindows *windows,Image **image,
11067 ExceptionInfo *exception)
11069 #define ApplyMenus 7
11119 "Contrast Stretch...",
11120 "Sigmoidal Contrast...",
11154 "Charcoal Draw...",
11157 *MiscellanyMenu[] =
11168 **Menus[ApplyMenus] =
11179 static const CommandType
11202 TransformCommands[] =
11206 RotateRightCommand,
11209 EnhanceCommands[] =
11217 ContrastStretchCommand,
11218 SigmoidalContrastCommand,
11226 EffectsCommands[] =
11230 ReduceNoiseCommand,
11249 CharcoalDrawCommand
11251 MiscellanyCommands[] =
11255 ShowPreviewCommand,
11256 ShowHistogramCommand,
11265 static const CommandType
11266 *Commands[ApplyMenus] =
11278 command[MaxTextExtent],
11279 text[MaxTextExtent];
11299 MagickProgressMonitor
11318 Map Command widget.
11320 (void) CloneString(&windows->command.name,"ROI");
11321 windows->command.data=0;
11322 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11323 (void) XMapRaised(display,windows->command.id);
11324 XClientMessage(display,windows->image.id,windows->im_protocols,
11325 windows->im_update_widget,CurrentTime);
11327 Track pointer until button 1 is pressed.
11329 XQueryPosition(display,windows->image.id,&x,&y);
11330 (void) XSelectInput(display,windows->image.id,
11331 windows->image.attributes.event_mask | PointerMotionMask);
11332 roi_info.x=(ssize_t) windows->image.x+x;
11333 roi_info.y=(ssize_t) windows->image.y+y;
11336 cursor=XCreateFontCursor(display,XC_fleur);
11337 state=DefaultState;
11340 if (windows->info.mapped != MagickFalse)
11343 Display pointer position.
11345 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11346 (long) roi_info.x,(long) roi_info.y);
11347 XInfoWidget(display,windows,text);
11350 Wait for next event.
11352 XScreenEvent(display,windows,&event,exception);
11353 if (event.xany.window == windows->command.id)
11356 Select a command from the Command widget.
11358 id=XCommandWidget(display,windows,ROIMenu,&event);
11361 switch (ROICommands[id])
11363 case ROIHelpCommand:
11365 XTextViewWidget(display,resource_info,windows,MagickFalse,
11366 "Help Viewer - Region of Interest",ImageROIHelp);
11369 case ROIDismissCommand:
11374 state|=EscapeState;
11383 switch (event.type)
11387 if (event.xbutton.button != Button1)
11389 if (event.xbutton.window != windows->image.id)
11392 Note first corner of region of interest rectangle-- exit loop.
11394 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11395 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11396 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11400 case ButtonRelease:
11409 if (event.xkey.window != windows->image.id)
11412 Respond to a user key press.
11414 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11415 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11416 switch ((int) key_symbol)
11424 state|=EscapeState;
11431 XTextViewWidget(display,resource_info,windows,MagickFalse,
11432 "Help Viewer - Region of Interest",ImageROIHelp);
11437 (void) XBell(display,0);
11446 Map and unmap Info widget as text cursor crosses its boundaries.
11450 if (windows->info.mapped != MagickFalse)
11452 if ((x < (int) (windows->info.x+windows->info.width)) &&
11453 (y < (int) (windows->info.y+windows->info.height)))
11454 (void) XWithdrawWindow(display,windows->info.id,
11455 windows->info.screen);
11458 if ((x > (int) (windows->info.x+windows->info.width)) ||
11459 (y > (int) (windows->info.y+windows->info.height)))
11460 (void) XMapWindow(display,windows->info.id);
11461 roi_info.x=(ssize_t) windows->image.x+x;
11462 roi_info.y=(ssize_t) windows->image.y+y;
11468 } while ((state & ExitState) == 0);
11469 (void) XSelectInput(display,windows->image.id,
11470 windows->image.attributes.event_mask);
11471 if ((state & EscapeState) != 0)
11474 User want to exit without region of interest.
11476 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11477 (void) XFreeCursor(display,cursor);
11478 return(MagickTrue);
11480 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11484 Size rectangle as pointer moves until the mouse button is released.
11486 x=(int) roi_info.x;
11487 y=(int) roi_info.y;
11490 state=DefaultState;
11493 highlight_info=roi_info;
11494 highlight_info.x=roi_info.x-windows->image.x;
11495 highlight_info.y=roi_info.y-windows->image.y;
11496 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11499 Display info and draw region of interest rectangle.
11501 if (windows->info.mapped == MagickFalse)
11502 (void) XMapWindow(display,windows->info.id);
11503 (void) FormatLocaleString(text,MaxTextExtent,
11504 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11505 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11506 XInfoWidget(display,windows,text);
11507 XHighlightRectangle(display,windows->image.id,
11508 windows->image.highlight_context,&highlight_info);
11511 if (windows->info.mapped != MagickFalse)
11512 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11514 Wait for next event.
11516 XScreenEvent(display,windows,&event,exception);
11517 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11518 XHighlightRectangle(display,windows->image.id,
11519 windows->image.highlight_context,&highlight_info);
11520 switch (event.type)
11524 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11525 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11528 case ButtonRelease:
11531 User has committed to region of interest rectangle.
11533 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11534 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11535 XSetCursorState(display,windows,MagickFalse);
11537 if (LocaleCompare(windows->command.name,"Apply") == 0)
11539 (void) CloneString(&windows->command.name,"Apply");
11540 windows->command.data=ApplyMenus;
11541 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11548 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11549 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11554 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11555 ((state & ExitState) != 0))
11558 Check boundary conditions.
11560 if (roi_info.x < 0)
11563 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11564 roi_info.x=(ssize_t) windows->image.ximage->width;
11565 if ((int) roi_info.x < x)
11566 roi_info.width=(unsigned int) (x-roi_info.x);
11569 roi_info.width=(unsigned int) (roi_info.x-x);
11570 roi_info.x=(ssize_t) x;
11572 if (roi_info.y < 0)
11575 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11576 roi_info.y=(ssize_t) windows->image.ximage->height;
11577 if ((int) roi_info.y < y)
11578 roi_info.height=(unsigned int) (y-roi_info.y);
11581 roi_info.height=(unsigned int) (roi_info.y-y);
11582 roi_info.y=(ssize_t) y;
11585 } while ((state & ExitState) == 0);
11587 Wait for user to grab a corner of the rectangle or press return.
11589 state=DefaultState;
11590 command_type=NullCommand;
11591 (void) XMapWindow(display,windows->info.id);
11594 if (windows->info.mapped != MagickFalse)
11597 Display pointer position.
11599 (void) FormatLocaleString(text,MaxTextExtent,
11600 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11601 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11602 XInfoWidget(display,windows,text);
11604 highlight_info=roi_info;
11605 highlight_info.x=roi_info.x-windows->image.x;
11606 highlight_info.y=roi_info.y-windows->image.y;
11607 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11609 state|=EscapeState;
11613 if ((state & UpdateRegionState) != 0)
11615 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11616 switch (command_type)
11621 (void) XMagickCommand(display,resource_info,windows,command_type,
11628 Region of interest is relative to image configuration.
11630 progress_monitor=SetImageProgressMonitor(*image,
11631 (MagickProgressMonitor) NULL,(*image)->client_data);
11632 crop_info=roi_info;
11633 width=(unsigned int) (*image)->columns;
11634 height=(unsigned int) (*image)->rows;
11637 if (windows->image.crop_geometry != (char *) NULL)
11638 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11640 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11642 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11643 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11644 scale_factor=(MagickRealType)
11645 height/windows->image.ximage->height;
11647 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11648 crop_info.height=(unsigned int)
11649 (scale_factor*crop_info.height+0.5);
11650 roi_image=CropImage(*image,&crop_info,exception);
11651 (void) SetImageProgressMonitor(*image,progress_monitor,
11652 (*image)->client_data);
11653 if (roi_image == (Image *) NULL)
11656 Apply image processing technique to the region of interest.
11658 windows->image.orphan=MagickTrue;
11659 (void) XMagickCommand(display,resource_info,windows,command_type,
11660 &roi_image,exception);
11661 progress_monitor=SetImageProgressMonitor(*image,
11662 (MagickProgressMonitor) NULL,(*image)->client_data);
11663 (void) XMagickCommand(display,resource_info,windows,
11664 SaveToUndoBufferCommand,image,exception);
11665 windows->image.orphan=MagickFalse;
11666 (void) CompositeImage(*image,roi_image,CopyCompositeOp,
11667 MagickTrue,crop_info.x,crop_info.y,exception);
11668 roi_image=DestroyImage(roi_image);
11669 (void) SetImageProgressMonitor(*image,progress_monitor,
11670 (*image)->client_data);
11674 if (command_type != InfoCommand)
11676 XConfigureImageColormap(display,resource_info,windows,*image,
11678 (void) XConfigureImage(display,resource_info,windows,*image,
11681 XCheckRefreshWindows(display,windows);
11682 XInfoWidget(display,windows,text);
11683 (void) XSetFunction(display,windows->image.highlight_context,
11685 state&=(~UpdateRegionState);
11687 XHighlightRectangle(display,windows->image.id,
11688 windows->image.highlight_context,&highlight_info);
11689 XScreenEvent(display,windows,&event,exception);
11690 if (event.xany.window == windows->command.id)
11693 Select a command from the Command widget.
11695 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11696 command_type=NullCommand;
11697 id=XCommandWidget(display,windows,ApplyMenu,&event);
11700 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11701 command_type=ApplyCommands[id];
11702 if (id < ApplyMenus)
11705 Select a command from a pop-up menu.
11707 entry=XMenuWidget(display,windows,ApplyMenu[id],
11708 (const char **) Menus[id],command);
11711 (void) CopyMagickString(command,Menus[id][entry],
11713 command_type=Commands[id][entry];
11717 (void) XSetFunction(display,windows->image.highlight_context,
11719 XHighlightRectangle(display,windows->image.id,
11720 windows->image.highlight_context,&highlight_info);
11721 if (command_type == HelpCommand)
11723 (void) XSetFunction(display,windows->image.highlight_context,
11725 XTextViewWidget(display,resource_info,windows,MagickFalse,
11726 "Help Viewer - Region of Interest",ImageROIHelp);
11727 (void) XSetFunction(display,windows->image.highlight_context,
11731 if (command_type == QuitCommand)
11736 state|=EscapeState;
11740 if (command_type != NullCommand)
11741 state|=UpdateRegionState;
11744 XHighlightRectangle(display,windows->image.id,
11745 windows->image.highlight_context,&highlight_info);
11746 switch (event.type)
11750 x=windows->image.x;
11751 y=windows->image.y;
11752 if (event.xbutton.button != Button1)
11754 if (event.xbutton.window != windows->image.id)
11756 x=windows->image.x+event.xbutton.x;
11757 y=windows->image.y+event.xbutton.y;
11758 if ((x < (int) (roi_info.x+RoiDelta)) &&
11759 (x > (int) (roi_info.x-RoiDelta)) &&
11760 (y < (int) (roi_info.y+RoiDelta)) &&
11761 (y > (int) (roi_info.y-RoiDelta)))
11763 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11764 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11765 state|=UpdateConfigurationState;
11768 if ((x < (int) (roi_info.x+RoiDelta)) &&
11769 (x > (int) (roi_info.x-RoiDelta)) &&
11770 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11771 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11773 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11774 state|=UpdateConfigurationState;
11777 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11778 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11779 (y < (int) (roi_info.y+RoiDelta)) &&
11780 (y > (int) (roi_info.y-RoiDelta)))
11782 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11783 state|=UpdateConfigurationState;
11786 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11787 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11788 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11789 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11791 state|=UpdateConfigurationState;
11795 case ButtonRelease:
11797 if (event.xbutton.window == windows->pan.id)
11798 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11799 (highlight_info.y != crop_info.y-windows->image.y))
11800 XHighlightRectangle(display,windows->image.id,
11801 windows->image.highlight_context,&highlight_info);
11802 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11803 event.xbutton.time);
11808 if (event.xexpose.window == windows->image.id)
11809 if (event.xexpose.count == 0)
11811 event.xexpose.x=(int) highlight_info.x;
11812 event.xexpose.y=(int) highlight_info.y;
11813 event.xexpose.width=(int) highlight_info.width;
11814 event.xexpose.height=(int) highlight_info.height;
11815 XRefreshWindow(display,&windows->image,&event);
11817 if (event.xexpose.window == windows->info.id)
11818 if (event.xexpose.count == 0)
11819 XInfoWidget(display,windows,text);
11827 if (event.xkey.window != windows->image.id)
11830 Respond to a user key press.
11832 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11833 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11834 switch ((int) key_symbol)
11841 state|=EscapeState;
11850 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11851 roi_info.y=(ssize_t) (windows->image.height/2L-
11852 roi_info.height/2L);
11884 (void) XSetFunction(display,windows->image.highlight_context,
11886 XTextViewWidget(display,resource_info,windows,MagickFalse,
11887 "Help Viewer - Region of Interest",ImageROIHelp);
11888 (void) XSetFunction(display,windows->image.highlight_context,
11894 command_type=XImageWindowCommand(display,resource_info,windows,
11895 event.xkey.state,key_symbol,image,exception);
11896 if (command_type != NullCommand)
11897 state|=UpdateRegionState;
11901 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11909 if (event.xbutton.window != windows->image.id)
11912 Map and unmap Info widget as text cursor crosses its boundaries.
11916 if (windows->info.mapped != MagickFalse)
11918 if ((x < (int) (windows->info.x+windows->info.width)) &&
11919 (y < (int) (windows->info.y+windows->info.height)))
11920 (void) XWithdrawWindow(display,windows->info.id,
11921 windows->info.screen);
11924 if ((x > (int) (windows->info.x+windows->info.width)) ||
11925 (y > (int) (windows->info.y+windows->info.height)))
11926 (void) XMapWindow(display,windows->info.id);
11927 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11928 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11931 case SelectionRequest:
11936 XSelectionRequestEvent
11940 Set primary selection.
11942 (void) FormatLocaleString(text,MaxTextExtent,
11943 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11944 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11945 request=(&(event.xselectionrequest));
11946 (void) XChangeProperty(request->display,request->requestor,
11947 request->property,request->target,8,PropModeReplace,
11948 (unsigned char *) text,(int) strlen(text));
11949 notify.type=SelectionNotify;
11950 notify.display=request->display;
11951 notify.requestor=request->requestor;
11952 notify.selection=request->selection;
11953 notify.target=request->target;
11954 notify.time=request->time;
11955 if (request->property == None)
11956 notify.property=request->target;
11958 notify.property=request->property;
11959 (void) XSendEvent(request->display,request->requestor,False,0,
11960 (XEvent *) ¬ify);
11965 if ((state & UpdateConfigurationState) != 0)
11967 (void) XPutBackEvent(display,&event);
11968 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11971 } while ((state & ExitState) == 0);
11972 } while ((state & ExitState) == 0);
11973 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11974 XSetCursorState(display,windows,MagickFalse);
11975 if ((state & EscapeState) != 0)
11976 return(MagickTrue);
11977 return(MagickTrue);
11981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11985 + X R o t a t e I m a g e %
11989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11991 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11992 % rotation angle is computed from the slope of a line drawn by the user.
11994 % The format of the XRotateImage method is:
11996 % MagickBooleanType XRotateImage(Display *display,
11997 % XResourceInfo *resource_info,XWindows *windows,double degrees,
11998 % Image **image,ExceptionInfo *exception)
12000 % A description of each parameter follows:
12002 % o display: Specifies a connection to an X server; returned from
12005 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12007 % o windows: Specifies a pointer to a XWindows structure.
12009 % o degrees: Specifies the number of degrees to rotate the image.
12011 % o image: the image.
12013 % o exception: return any errors or warnings in this structure.
12016 static MagickBooleanType XRotateImage(Display *display,
12017 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12018 ExceptionInfo *exception)
12031 direction = HorizontalRotateCommand;
12033 static const ModeType
12034 DirectionCommands[] =
12036 HorizontalRotateCommand,
12037 VerticalRotateCommand
12041 RotateColorCommand,
12042 RotateDirectionCommand,
12044 RotateDismissCommand
12047 static unsigned int
12051 command[MaxTextExtent],
12052 text[MaxTextExtent];
12063 normalized_degrees;
12073 if (degrees == 0.0)
12088 Map Command widget.
12090 (void) CloneString(&windows->command.name,"Rotate");
12091 windows->command.data=2;
12092 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12093 (void) XMapRaised(display,windows->command.id);
12094 XClientMessage(display,windows->image.id,windows->im_protocols,
12095 windows->im_update_widget,CurrentTime);
12097 Wait for first button press.
12099 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12100 XQueryPosition(display,windows->image.id,&x,&y);
12105 state=DefaultState;
12108 XHighlightLine(display,windows->image.id,
12109 windows->image.highlight_context,&rotate_info);
12111 Wait for next event.
12113 XScreenEvent(display,windows,&event,exception);
12114 XHighlightLine(display,windows->image.id,
12115 windows->image.highlight_context,&rotate_info);
12116 if (event.xany.window == windows->command.id)
12119 Select a command from the Command widget.
12121 id=XCommandWidget(display,windows,RotateMenu,&event);
12124 (void) XSetFunction(display,windows->image.highlight_context,
12126 switch (RotateCommands[id])
12128 case RotateColorCommand:
12131 *ColorMenu[MaxNumberPens];
12140 Initialize menu selections.
12142 for (i=0; i < (int) (MaxNumberPens-2); i++)
12143 ColorMenu[i]=resource_info->pen_colors[i];
12144 ColorMenu[MaxNumberPens-2]="Browser...";
12145 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12147 Select a pen color from the pop-up menu.
12149 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12150 (const char **) ColorMenu,command);
12151 if (pen_number < 0)
12153 if (pen_number == (MaxNumberPens-2))
12156 color_name[MaxTextExtent] = "gray";
12159 Select a pen color from a dialog.
12161 resource_info->pen_colors[pen_number]=color_name;
12162 XColorBrowserWidget(display,windows,"Select",color_name);
12163 if (*color_name == '\0')
12169 (void) XParseColor(display,windows->map_info->colormap,
12170 resource_info->pen_colors[pen_number],&color);
12171 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12172 (unsigned int) MaxColors,&color);
12173 windows->pixel_info->pen_colors[pen_number]=color;
12174 pen_id=(unsigned int) pen_number;
12177 case RotateDirectionCommand:
12188 Select a command from the pop-up menu.
12190 id=XMenuWidget(display,windows,RotateMenu[id],
12191 Directions,command);
12193 direction=DirectionCommands[id];
12196 case RotateHelpCommand:
12198 XTextViewWidget(display,resource_info,windows,MagickFalse,
12199 "Help Viewer - Image Rotation",ImageRotateHelp);
12202 case RotateDismissCommand:
12207 state|=EscapeState;
12214 (void) XSetFunction(display,windows->image.highlight_context,
12218 switch (event.type)
12222 if (event.xbutton.button != Button1)
12224 if (event.xbutton.window != windows->image.id)
12229 (void) XSetFunction(display,windows->image.highlight_context,
12231 rotate_info.x1=event.xbutton.x;
12232 rotate_info.y1=event.xbutton.y;
12236 case ButtonRelease:
12243 command[MaxTextExtent];
12248 if (event.xkey.window != windows->image.id)
12251 Respond to a user key press.
12253 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12254 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12255 switch ((int) key_symbol)
12263 state|=EscapeState;
12270 (void) XSetFunction(display,windows->image.highlight_context,
12272 XTextViewWidget(display,resource_info,windows,MagickFalse,
12273 "Help Viewer - Image Rotation",ImageRotateHelp);
12274 (void) XSetFunction(display,windows->image.highlight_context,
12280 (void) XBell(display,0);
12288 rotate_info.x1=event.xmotion.x;
12289 rotate_info.y1=event.xmotion.y;
12292 rotate_info.x2=rotate_info.x1;
12293 rotate_info.y2=rotate_info.y1;
12294 if (direction == HorizontalRotateCommand)
12295 rotate_info.x2+=32;
12297 rotate_info.y2-=32;
12298 } while ((state & ExitState) == 0);
12299 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12300 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12301 if ((state & EscapeState) != 0)
12302 return(MagickTrue);
12304 Draw line as pointer moves until the mouse button is released.
12307 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12308 state=DefaultState;
12314 Display info and draw rotation line.
12316 if (windows->info.mapped == MagickFalse)
12317 (void) XMapWindow(display,windows->info.id);
12318 (void) FormatLocaleString(text,MaxTextExtent," %g",
12319 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12320 XInfoWidget(display,windows,text);
12321 XHighlightLine(display,windows->image.id,
12322 windows->image.highlight_context,&rotate_info);
12325 if (windows->info.mapped != MagickFalse)
12326 (void) XWithdrawWindow(display,windows->info.id,
12327 windows->info.screen);
12329 Wait for next event.
12331 XScreenEvent(display,windows,&event,exception);
12333 XHighlightLine(display,windows->image.id,
12334 windows->image.highlight_context,&rotate_info);
12335 switch (event.type)
12339 case ButtonRelease:
12342 User has committed to rotation line.
12344 rotate_info.x2=event.xbutton.x;
12345 rotate_info.y2=event.xbutton.y;
12353 rotate_info.x2=event.xmotion.x;
12354 rotate_info.y2=event.xmotion.y;
12360 Check boundary conditions.
12362 if (rotate_info.x2 < 0)
12365 if (rotate_info.x2 > (int) windows->image.width)
12366 rotate_info.x2=(short) windows->image.width;
12367 if (rotate_info.y2 < 0)
12370 if (rotate_info.y2 > (int) windows->image.height)
12371 rotate_info.y2=(short) windows->image.height;
12373 Compute rotation angle from the slope of the line.
12376 distance=(unsigned int)
12377 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12378 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12380 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12381 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12382 } while ((state & ExitState) == 0);
12383 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12384 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12386 return(MagickTrue);
12388 if (direction == VerticalRotateCommand)
12390 if (degrees == 0.0)
12391 return(MagickTrue);
12395 normalized_degrees=degrees;
12396 while (normalized_degrees < -45.0)
12397 normalized_degrees+=360.0;
12398 for (rotations=0; normalized_degrees > 45.0; rotations++)
12399 normalized_degrees-=90.0;
12400 if (normalized_degrees != 0.0)
12401 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12403 XSetCursorState(display,windows,MagickTrue);
12404 XCheckRefreshWindows(display,windows);
12405 (*image)->background_color.red=(double) ScaleShortToQuantum(
12406 windows->pixel_info->pen_colors[pen_id].red);
12407 (*image)->background_color.green=(double) ScaleShortToQuantum(
12408 windows->pixel_info->pen_colors[pen_id].green);
12409 (*image)->background_color.blue=(double) ScaleShortToQuantum(
12410 windows->pixel_info->pen_colors[pen_id].blue);
12411 rotate_image=RotateImage(*image,degrees,exception);
12412 XSetCursorState(display,windows,MagickFalse);
12413 if (rotate_image == (Image *) NULL)
12414 return(MagickFalse);
12415 *image=DestroyImage(*image);
12416 *image=rotate_image;
12417 if (windows->image.crop_geometry != (char *) NULL)
12420 Rotate crop geometry.
12422 width=(unsigned int) (*image)->columns;
12423 height=(unsigned int) (*image)->rows;
12424 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12425 switch (rotations % 4)
12435 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12436 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12443 Rotate 180 degrees.
12445 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12446 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12452 Rotate 270 degrees.
12454 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12455 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12460 if (windows->image.orphan != MagickFalse)
12461 return(MagickTrue);
12462 if (normalized_degrees != 0.0)
12465 Update image colormap.
12467 windows->image.window_changes.width=(int) (*image)->columns;
12468 windows->image.window_changes.height=(int) (*image)->rows;
12469 if (windows->image.crop_geometry != (char *) NULL)
12472 Obtain dimensions of image from crop geometry.
12474 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12476 windows->image.window_changes.width=(int) width;
12477 windows->image.window_changes.height=(int) height;
12479 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12482 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12484 windows->image.window_changes.width=windows->image.ximage->height;
12485 windows->image.window_changes.height=windows->image.ximage->width;
12488 Update image configuration.
12490 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12491 return(MagickTrue);
12495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12499 + X S a v e I m a g e %
12503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12505 % XSaveImage() saves an image to a file.
12507 % The format of the XSaveImage method is:
12509 % MagickBooleanType XSaveImage(Display *display,
12510 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12511 % ExceptionInfo *exception)
12513 % A description of each parameter follows:
12515 % o display: Specifies a connection to an X server; returned from
12518 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12520 % o windows: Specifies a pointer to a XWindows structure.
12522 % o image: the image.
12524 % o exception: return any errors or warnings in this structure.
12527 static MagickBooleanType XSaveImage(Display *display,
12528 XResourceInfo *resource_info,XWindows *windows,Image *image,
12529 ExceptionInfo *exception)
12532 filename[MaxTextExtent],
12533 geometry[MaxTextExtent];
12545 Request file name from user.
12547 if (resource_info->write_filename != (char *) NULL)
12548 (void) CopyMagickString(filename,resource_info->write_filename,
12553 path[MaxTextExtent];
12558 GetPathComponent(image->filename,HeadPath,path);
12559 GetPathComponent(image->filename,TailPath,filename);
12562 status=chdir(path);
12564 (void) ThrowMagickException(exception,GetMagickModule(),
12565 FileOpenError,"UnableToOpenFile","%s",path);
12568 XFileBrowserWidget(display,windows,"Save",filename);
12569 if (*filename == '\0')
12570 return(MagickTrue);
12571 if (IsPathAccessible(filename) != MagickFalse)
12577 File exists-- seek user's permission before overwriting.
12579 status=XConfirmWidget(display,windows,"Overwrite",filename);
12581 return(MagickTrue);
12583 image_info=CloneImageInfo(resource_info->image_info);
12584 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12585 (void) SetImageInfo(image_info,1,exception);
12586 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12587 (LocaleCompare(image_info->magick,"JPG") == 0))
12590 quality[MaxTextExtent];
12596 Request JPEG quality from user.
12598 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12600 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12602 if (*quality == '\0')
12603 return(MagickTrue);
12604 image->quality=StringToUnsignedLong(quality);
12605 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12607 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12608 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12609 (LocaleCompare(image_info->magick,"PS") == 0) ||
12610 (LocaleCompare(image_info->magick,"PS2") == 0))
12613 geometry[MaxTextExtent];
12616 Request page geometry from user.
12618 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12619 if (LocaleCompare(image_info->magick,"PDF") == 0)
12620 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12621 if (image_info->page != (char *) NULL)
12622 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12623 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12624 "Select page geometry:",geometry);
12625 if (*geometry != '\0')
12626 image_info->page=GetPageGeometry(geometry);
12629 Apply image transforms.
12631 XSetCursorState(display,windows,MagickTrue);
12632 XCheckRefreshWindows(display,windows);
12633 save_image=CloneImage(image,0,0,MagickTrue,exception);
12634 if (save_image == (Image *) NULL)
12635 return(MagickFalse);
12636 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12637 windows->image.ximage->width,windows->image.ximage->height);
12638 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12643 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12644 status=WriteImage(image_info,save_image,exception);
12645 if (status != MagickFalse)
12646 image->taint=MagickFalse;
12647 save_image=DestroyImage(save_image);
12648 image_info=DestroyImageInfo(image_info);
12649 XSetCursorState(display,windows,MagickFalse);
12650 return(status != 0 ? MagickTrue : MagickFalse);
12654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12658 + X S c r e e n E v e n t %
12662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12664 % XScreenEvent() handles global events associated with the Pan and Magnify
12667 % The format of the XScreenEvent function is:
12669 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12670 % ExceptionInfo *exception)
12672 % A description of each parameter follows:
12674 % o display: Specifies a pointer to the Display structure; returned from
12677 % o windows: Specifies a pointer to a XWindows structure.
12679 % o event: Specifies a pointer to a X11 XEvent structure.
12681 % o exception: return any errors or warnings in this structure.
12685 #if defined(__cplusplus) || defined(c_plusplus)
12689 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12694 windows=(XWindows *) data;
12695 if ((event->type == ClientMessage) &&
12696 (event->xclient.window == windows->image.id))
12697 return(MagickFalse);
12698 return(MagickTrue);
12701 #if defined(__cplusplus) || defined(c_plusplus)
12705 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12706 ExceptionInfo *exception)
12712 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12713 if (event->xany.window == windows->command.id)
12715 switch (event->type)
12718 case ButtonRelease:
12720 if ((event->xbutton.button == Button3) &&
12721 (event->xbutton.state & Mod1Mask))
12724 Convert Alt-Button3 to Button2.
12726 event->xbutton.button=Button2;
12727 event->xbutton.state&=(~Mod1Mask);
12729 if (event->xbutton.window == windows->backdrop.id)
12731 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12732 event->xbutton.time);
12735 if (event->xbutton.window == windows->pan.id)
12737 XPanImage(display,windows,event,exception);
12740 if (event->xbutton.window == windows->image.id)
12741 if (event->xbutton.button == Button2)
12744 Update magnified image.
12746 x=event->xbutton.x;
12747 y=event->xbutton.y;
12751 if (x >= (int) windows->image.width)
12752 x=(int) (windows->image.width-1);
12753 windows->magnify.x=(int) windows->image.x+x;
12757 if (y >= (int) windows->image.height)
12758 y=(int) (windows->image.height-1);
12759 windows->magnify.y=windows->image.y+y;
12760 if (windows->magnify.mapped == MagickFalse)
12761 (void) XMapRaised(display,windows->magnify.id);
12762 XMakeMagnifyImage(display,windows,exception);
12763 if (event->type == ButtonRelease)
12764 (void) XWithdrawWindow(display,windows->info.id,
12765 windows->info.screen);
12770 case ClientMessage:
12773 If client window delete message, exit.
12775 if (event->xclient.message_type != windows->wm_protocols)
12777 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12779 if (event->xclient.window == windows->magnify.id)
12781 (void) XWithdrawWindow(display,windows->magnify.id,
12782 windows->magnify.screen);
12787 case ConfigureNotify:
12789 if (event->xconfigure.window == windows->magnify.id)
12795 Magnify window has a new configuration.
12797 windows->magnify.width=(unsigned int) event->xconfigure.width;
12798 windows->magnify.height=(unsigned int) event->xconfigure.height;
12799 if (windows->magnify.mapped == MagickFalse)
12802 while ((int) magnify <= event->xconfigure.width)
12804 while ((int) magnify <= event->xconfigure.height)
12807 if (((int) magnify != event->xconfigure.width) ||
12808 ((int) magnify != event->xconfigure.height))
12813 window_changes.width=(int) magnify;
12814 window_changes.height=(int) magnify;
12815 (void) XReconfigureWMWindow(display,windows->magnify.id,
12816 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12820 XMakeMagnifyImage(display,windows,exception);
12827 if (event->xexpose.window == windows->image.id)
12829 XRefreshWindow(display,&windows->image,event);
12832 if (event->xexpose.window == windows->pan.id)
12833 if (event->xexpose.count == 0)
12835 XDrawPanRectangle(display,windows);
12838 if (event->xexpose.window == windows->magnify.id)
12839 if (event->xexpose.count == 0)
12841 XMakeMagnifyImage(display,windows,exception);
12849 command[MaxTextExtent];
12854 if (event->xkey.window != windows->magnify.id)
12857 Respond to a user key press.
12859 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12860 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12861 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12867 if (event->xmap.window == windows->magnify.id)
12869 windows->magnify.mapped=MagickTrue;
12870 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12873 if (event->xmap.window == windows->info.id)
12875 windows->info.mapped=MagickTrue;
12882 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12883 if (event->xmotion.window == windows->image.id)
12884 if (windows->magnify.mapped != MagickFalse)
12887 Update magnified image.
12889 x=event->xmotion.x;
12890 y=event->xmotion.y;
12894 if (x >= (int) windows->image.width)
12895 x=(int) (windows->image.width-1);
12896 windows->magnify.x=(int) windows->image.x+x;
12900 if (y >= (int) windows->image.height)
12901 y=(int) (windows->image.height-1);
12902 windows->magnify.y=windows->image.y+y;
12903 XMakeMagnifyImage(display,windows,exception);
12909 if (event->xunmap.window == windows->magnify.id)
12911 windows->magnify.mapped=MagickFalse;
12914 if (event->xunmap.window == windows->info.id)
12916 windows->info.mapped=MagickFalse;
12927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12931 + X S e t C r o p G e o m e t r y %
12935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12937 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12938 % and translates it to a cropping geometry relative to the image.
12940 % The format of the XSetCropGeometry method is:
12942 % void XSetCropGeometry(Display *display,XWindows *windows,
12943 % RectangleInfo *crop_info,Image *image)
12945 % A description of each parameter follows:
12947 % o display: Specifies a connection to an X server; returned from
12950 % o windows: Specifies a pointer to a XWindows structure.
12952 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12953 % Image window to crop.
12955 % o image: the image.
12958 static void XSetCropGeometry(Display *display,XWindows *windows,
12959 RectangleInfo *crop_info,Image *image)
12962 text[MaxTextExtent];
12975 if (windows->info.mapped != MagickFalse)
12978 Display info on cropping rectangle.
12980 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12981 (double) crop_info->width,(double) crop_info->height,(double)
12982 crop_info->x,(double) crop_info->y);
12983 XInfoWidget(display,windows,text);
12986 Cropping geometry is relative to any previous crop geometry.
12990 width=(unsigned int) image->columns;
12991 height=(unsigned int) image->rows;
12992 if (windows->image.crop_geometry != (char *) NULL)
12993 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12995 windows->image.crop_geometry=AcquireString((char *) NULL);
12997 Define the crop geometry string from the cropping rectangle.
12999 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13000 if (crop_info->x > 0)
13001 x+=(int) (scale_factor*crop_info->x+0.5);
13002 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13005 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13006 if (crop_info->y > 0)
13007 y+=(int) (scale_factor*crop_info->y+0.5);
13008 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13011 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13012 "%ux%u%+d%+d",width,height,x,y);
13016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13020 + X T i l e I m a g e %
13024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13026 % XTileImage() loads or deletes a selected tile from a visual image directory.
13027 % The load or delete command is chosen from a menu.
13029 % The format of the XTileImage method is:
13031 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13032 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13034 % A description of each parameter follows:
13036 % o tile_image: XTileImage reads or deletes the tile image
13037 % and returns it. A null image is returned if an error occurs.
13039 % o display: Specifies a connection to an X server; returned from
13042 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13044 % o windows: Specifies a pointer to a XWindows structure.
13046 % o image: the image; returned from ReadImage.
13048 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13049 % the entire image is refreshed.
13051 % o exception: return any errors or warnings in this structure.
13054 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13055 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13068 static const ModeType
13079 command[MaxTextExtent],
13080 filename[MaxTextExtent];
13107 Tile image is relative to montage image configuration.
13111 width=(unsigned int) image->columns;
13112 height=(unsigned int) image->rows;
13113 if (windows->image.crop_geometry != (char *) NULL)
13114 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13115 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13116 event->xbutton.x+=windows->image.x;
13117 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13118 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13119 event->xbutton.y+=windows->image.y;
13120 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13122 Determine size and location of each tile in the visual image directory.
13124 width=(unsigned int) image->columns;
13125 height=(unsigned int) image->rows;
13128 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13129 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13130 (event->xbutton.x-x)/width;
13134 Button press is outside any tile.
13136 (void) XBell(display,0);
13137 return((Image *) NULL);
13140 Determine file name from the tile directory.
13142 p=image->directory;
13143 for (i=tile; (i != 0) && (*p != '\0'); )
13152 Button press is outside any tile.
13154 (void) XBell(display,0);
13155 return((Image *) NULL);
13158 Select a command from the pop-up menu.
13160 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13162 return((Image *) NULL);
13164 while ((*q != '\n') && (*q != '\0'))
13166 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13168 Perform command for the selected tile.
13170 XSetCursorState(display,windows,MagickTrue);
13171 XCheckRefreshWindows(display,windows);
13172 tile_image=NewImageList();
13173 switch (TileCommands[id])
13175 case TileLoadCommand:
13180 XCheckRefreshWindows(display,windows);
13181 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13183 (void) CopyMagickString(resource_info->image_info->filename,filename,
13185 tile_image=ReadImage(resource_info->image_info,exception);
13186 CatchException(exception);
13187 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13190 case TileNextCommand:
13193 Display next image.
13195 XClientMessage(display,windows->image.id,windows->im_protocols,
13196 windows->im_next_image,CurrentTime);
13199 case TileFormerCommand:
13202 Display former image.
13204 XClientMessage(display,windows->image.id,windows->im_protocols,
13205 windows->im_former_image,CurrentTime);
13208 case TileDeleteCommand:
13213 if (IsPathAccessible(filename) == MagickFalse)
13215 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13218 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13221 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
13222 if (status != MagickFalse)
13224 XNoticeWidget(display,windows,"Unable to delete image file:",
13229 case TileUpdateCommand:
13245 Ensure all the images exist.
13248 GetPixelInfo(image,&pixel);
13249 for (p=image->directory; *p != '\0'; p++)
13255 while ((*q != '\n') && (*q != '\0'))
13257 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13259 if (IsPathAccessible(filename) != MagickFalse)
13265 Overwrite tile with background color.
13267 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13268 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13269 image_view=AcquireAuthenticCacheView(image,exception);
13270 (void) GetOneCacheViewVirtualPixelInfo(image_view,0,0,&pixel,exception);
13271 for (i=0; i < (int) height; i++)
13273 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13274 y_offset+i,width,1,exception);
13275 if (s == (Quantum *) NULL)
13277 for (j=0; j < (int) width; j++)
13279 SetPixelInfoPixel(image,&pixel,s);
13280 s+=GetPixelChannels(image);
13282 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13285 image_view=DestroyCacheView(image_view);
13288 windows->image.window_changes.width=(int) image->columns;
13289 windows->image.window_changes.height=(int) image->rows;
13290 XConfigureImageColormap(display,resource_info,windows,image,exception);
13291 (void) XConfigureImage(display,resource_info,windows,image,exception);
13297 XSetCursorState(display,windows,MagickFalse);
13298 return(tile_image);
13302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13306 + X T r a n s l a t e I m a g e %
13310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13312 % XTranslateImage() translates the image within an Image window by one pixel
13313 % as specified by the key symbol. If the image has a montage string the
13314 % translation is respect to the width and height contained within the string.
13316 % The format of the XTranslateImage method is:
13318 % void XTranslateImage(Display *display,XWindows *windows,
13319 % Image *image,const KeySym key_symbol)
13321 % A description of each parameter follows:
13323 % o display: Specifies a connection to an X server; returned from
13326 % o windows: Specifies a pointer to a XWindows structure.
13328 % o image: the image.
13330 % o key_symbol: Specifies a KeySym which indicates which side of the image
13334 static void XTranslateImage(Display *display,XWindows *windows,
13335 Image *image,const KeySym key_symbol)
13338 text[MaxTextExtent];
13349 User specified a pan position offset.
13351 x_offset=windows->image.width;
13352 y_offset=windows->image.height;
13353 if (image->montage != (char *) NULL)
13354 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13355 switch ((int) key_symbol)
13360 windows->image.x=(int) windows->image.width/2;
13361 windows->image.y=(int) windows->image.height/2;
13367 windows->image.x-=x_offset;
13374 windows->image.y-=y_offset;
13380 windows->image.x+=x_offset;
13387 windows->image.y+=y_offset;
13394 Check boundary conditions.
13396 if (windows->image.x < 0)
13397 windows->image.x=0;
13399 if ((int) (windows->image.x+windows->image.width) >
13400 windows->image.ximage->width)
13401 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13402 if (windows->image.y < 0)
13403 windows->image.y=0;
13405 if ((int) (windows->image.y+windows->image.height) >
13406 windows->image.ximage->height)
13407 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13409 Refresh Image window.
13411 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13412 windows->image.width,windows->image.height,windows->image.x,
13414 XInfoWidget(display,windows,text);
13415 XCheckRefreshWindows(display,windows);
13416 XDrawPanRectangle(display,windows);
13417 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13418 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13426 + X T r i m I m a g e %
13430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13432 % XTrimImage() trims the edges from the Image window.
13434 % The format of the XTrimImage method is:
13436 % MagickBooleanType XTrimImage(Display *display,
13437 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13438 % ExceptionInfo *exception)
13440 % A description of each parameter follows:
13442 % o display: Specifies a connection to an X server; returned from
13445 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13447 % o windows: Specifies a pointer to a XWindows structure.
13449 % o image: the image.
13451 % o exception: return any errors or warnings in this structure.
13454 static MagickBooleanType XTrimImage(Display *display,
13455 XResourceInfo *resource_info,XWindows *windows,Image *image,
13456 ExceptionInfo *exception)
13470 Trim edges from image.
13472 XSetCursorState(display,windows,MagickTrue);
13473 XCheckRefreshWindows(display,windows);
13475 Crop the left edge.
13477 background=XGetPixel(windows->image.ximage,0,0);
13478 trim_info.width=(size_t) windows->image.ximage->width;
13479 for (x=0; x < windows->image.ximage->width; x++)
13481 for (y=0; y < windows->image.ximage->height; y++)
13483 pixel=XGetPixel(windows->image.ximage,x,y);
13484 if (pixel != background)
13487 if (y < windows->image.ximage->height)
13490 trim_info.x=(ssize_t) x;
13491 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13493 XSetCursorState(display,windows,MagickFalse);
13494 return(MagickFalse);
13497 Crop the right edge.
13499 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13500 for (x=windows->image.ximage->width-1; x != 0; x--)
13502 for (y=0; y < windows->image.ximage->height; y++)
13504 pixel=XGetPixel(windows->image.ximage,x,y);
13505 if (pixel != background)
13508 if (y < windows->image.ximage->height)
13511 trim_info.width=(size_t) (x-trim_info.x+1);
13515 background=XGetPixel(windows->image.ximage,0,0);
13516 trim_info.height=(size_t) windows->image.ximage->height;
13517 for (y=0; y < windows->image.ximage->height; y++)
13519 for (x=0; x < windows->image.ximage->width; x++)
13521 pixel=XGetPixel(windows->image.ximage,x,y);
13522 if (pixel != background)
13525 if (x < windows->image.ximage->width)
13528 trim_info.y=(ssize_t) y;
13530 Crop the bottom edge.
13532 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13533 for (y=windows->image.ximage->height-1; y != 0; y--)
13535 for (x=0; x < windows->image.ximage->width; x++)
13537 pixel=XGetPixel(windows->image.ximage,x,y);
13538 if (pixel != background)
13541 if (x < windows->image.ximage->width)
13544 trim_info.height=(size_t) y-trim_info.y+1;
13545 if (((unsigned int) trim_info.width != windows->image.width) ||
13546 ((unsigned int) trim_info.height != windows->image.height))
13549 Reconfigure Image window as defined by the trimming rectangle.
13551 XSetCropGeometry(display,windows,&trim_info,image);
13552 windows->image.window_changes.width=(int) trim_info.width;
13553 windows->image.window_changes.height=(int) trim_info.height;
13554 (void) XConfigureImage(display,resource_info,windows,image,exception);
13556 XSetCursorState(display,windows,MagickFalse);
13557 return(MagickTrue);
13561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13565 + X V i s u a l D i r e c t o r y I m a g e %
13569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13571 % XVisualDirectoryImage() creates a Visual Image Directory.
13573 % The format of the XVisualDirectoryImage method is:
13575 % Image *XVisualDirectoryImage(Display *display,
13576 % XResourceInfo *resource_info,XWindows *windows,
13577 % ExceptionInfo *exception)
13579 % A description of each parameter follows:
13581 % o display: Specifies a connection to an X server; returned from
13584 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13586 % o windows: Specifies a pointer to a XWindows structure.
13588 % o exception: return any errors or warnings in this structure.
13591 static Image *XVisualDirectoryImage(Display *display,
13592 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13594 #define TileImageTag "Scale/Image"
13595 #define XClientName "montage"
13628 filename[MaxTextExtent] = "\0",
13629 filenames[MaxTextExtent] = "*";
13632 background_resources;
13635 Request file name from user.
13637 XFileBrowserWidget(display,windows,"Directory",filenames);
13638 if (*filenames == '\0')
13639 return((Image *) NULL);
13641 Expand the filenames.
13643 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13644 if (filelist == (char **) NULL)
13646 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13648 return((Image *) NULL);
13651 filelist[0]=filenames;
13652 status=ExpandFilenames(&number_files,&filelist);
13653 if ((status == MagickFalse) || (number_files == 0))
13655 if (number_files == 0)
13656 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13658 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13660 return((Image *) NULL);
13663 Set image background resources.
13665 background_resources=(*resource_info);
13666 background_resources.window_id=AcquireString("");
13667 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13668 "0x%lx",windows->image.id);
13669 background_resources.backdrop=MagickTrue;
13671 Read each image and convert them to a tile.
13673 backdrop=(windows->visual_info->klass == TrueColor) ||
13674 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13675 read_info=CloneImageInfo(resource_info->image_info);
13676 (void) SetImageOption(read_info,"jpeg:size","120x120");
13677 (void) CloneString(&read_info->size,DefaultTileGeometry);
13678 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13680 images=NewImageList();
13681 XSetCursorState(display,windows,MagickTrue);
13682 XCheckRefreshWindows(display,windows);
13683 for (i=0; i < (int) number_files; i++)
13685 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13686 filelist[i]=DestroyString(filelist[i]);
13687 *read_info->magick='\0';
13688 next_image=ReadImage(read_info,exception);
13689 CatchException(exception);
13690 if (next_image != (Image *) NULL)
13692 (void) DeleteImageProperty(next_image,"label");
13693 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13694 read_info,next_image,DefaultTileLabel,exception),exception);
13695 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13697 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13698 geometry.height,exception);
13699 if (thumbnail_image != (Image *) NULL)
13701 next_image=DestroyImage(next_image);
13702 next_image=thumbnail_image;
13706 (void) XDisplayBackgroundImage(display,&background_resources,
13707 next_image,exception);
13708 XSetCursorState(display,windows,MagickTrue);
13710 AppendImageToList(&images,next_image);
13711 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13716 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13717 (MagickSizeType) number_files);
13718 if (proceed == MagickFalse)
13723 filelist=(char **) RelinquishMagickMemory(filelist);
13724 if (images == (Image *) NULL)
13726 read_info=DestroyImageInfo(read_info);
13727 XSetCursorState(display,windows,MagickFalse);
13728 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13729 return((Image *) NULL);
13732 Create the Visual Image Directory.
13734 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13735 montage_info->pointsize=10;
13736 if (resource_info->font != (char *) NULL)
13737 (void) CloneString(&montage_info->font,resource_info->font);
13738 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13739 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13740 images),exception);
13741 images=DestroyImageList(images);
13742 montage_info=DestroyMontageInfo(montage_info);
13743 read_info=DestroyImageInfo(read_info);
13744 XSetCursorState(display,windows,MagickFalse);
13745 if (montage_image == (Image *) NULL)
13746 return(montage_image);
13747 XClientMessage(display,windows->image.id,windows->im_protocols,
13748 windows->im_next_image,CurrentTime);
13749 return(montage_image);
13753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13757 % X D i s p l a y B a c k g r o u n d I m a g e %
13761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13763 % XDisplayBackgroundImage() displays an image in the background of a window.
13765 % The format of the XDisplayBackgroundImage method is:
13767 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13768 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13770 % A description of each parameter follows:
13772 % o display: Specifies a connection to an X server; returned from
13775 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13777 % o image: the image.
13779 % o exception: return any errors or warnings in this structure.
13782 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13783 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13786 geometry[MaxTextExtent],
13787 visual_type[MaxTextExtent];
13800 static XStandardColormap
13804 *visual_info = (XVisualInfo *) NULL;
13825 Determine target window.
13827 assert(image != (Image *) NULL);
13828 assert(image->signature == MagickSignature);
13829 if (image->debug != MagickFalse)
13830 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13831 resources=(*resource_info);
13832 window_info.id=(Window) NULL;
13833 root_window=XRootWindow(display,XDefaultScreen(display));
13834 if (LocaleCompare(resources.window_id,"root") == 0)
13835 window_info.id=root_window;
13838 if (isdigit((unsigned char) *resources.window_id) != 0)
13839 window_info.id=XWindowByID(display,root_window,
13840 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13841 if (window_info.id == (Window) NULL)
13842 window_info.id=XWindowByName(display,root_window,resources.window_id);
13844 if (window_info.id == (Window) NULL)
13846 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13847 resources.window_id);
13848 return(MagickFalse);
13851 Determine window visual id.
13853 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13854 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13855 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13856 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13858 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13859 XVisualIDFromVisual(window_attributes.visual));
13860 if (visual_info == (XVisualInfo *) NULL)
13863 Allocate standard colormap.
13865 map_info=XAllocStandardColormap();
13866 if (map_info == (XStandardColormap *) NULL)
13867 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13869 map_info->colormap=(Colormap) NULL;
13870 pixel.pixels=(unsigned long *) NULL;
13872 Initialize visual info.
13874 resources.map_type=(char *) NULL;
13875 resources.visual_type=visual_type;
13876 visual_info=XBestVisualInfo(display,map_info,&resources);
13877 if (visual_info == (XVisualInfo *) NULL)
13878 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13879 resources.visual_type);
13881 Initialize window info.
13883 window_info.ximage=(XImage *) NULL;
13884 window_info.matte_image=(XImage *) NULL;
13885 window_info.pixmap=(Pixmap) NULL;
13886 window_info.matte_pixmap=(Pixmap) NULL;
13889 Free previous root colors.
13891 if (window_info.id == root_window)
13892 (void) XDestroyWindowColors(display,root_window);
13894 Initialize Standard Colormap.
13896 resources.colormap=SharedColormap;
13897 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13900 Graphic context superclass.
13902 context_values.background=pixel.background_color.pixel;
13903 context_values.foreground=pixel.foreground_color.pixel;
13904 pixel.annotate_context=XCreateGC(display,window_info.id,
13905 (size_t) (GCBackground | GCForeground),&context_values);
13906 if (pixel.annotate_context == (GC) NULL)
13907 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13910 Initialize Image window attributes.
13912 window_info.name=AcquireString("\0");
13913 window_info.icon_name=AcquireString("\0");
13914 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13915 &resources,&window_info);
13917 Create the X image.
13919 window_info.width=(unsigned int) image->columns;
13920 window_info.height=(unsigned int) image->rows;
13921 if ((image->columns != window_info.width) ||
13922 (image->rows != window_info.height))
13923 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13925 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13926 window_attributes.width,window_attributes.height);
13927 geometry_info.width=window_info.width;
13928 geometry_info.height=window_info.height;
13929 geometry_info.x=(ssize_t) window_info.x;
13930 geometry_info.y=(ssize_t) window_info.y;
13931 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13932 &geometry_info.width,&geometry_info.height);
13933 window_info.width=(unsigned int) geometry_info.width;
13934 window_info.height=(unsigned int) geometry_info.height;
13935 window_info.x=(int) geometry_info.x;
13936 window_info.y=(int) geometry_info.y;
13937 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13938 window_info.height,exception);
13939 if (status == MagickFalse)
13940 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13944 if (image->debug != MagickFalse)
13946 (void) LogMagickEvent(X11Event,GetMagickModule(),
13947 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13948 (double) image->columns,(double) image->rows);
13949 if (image->colors != 0)
13950 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13952 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13955 Adjust image dimensions as specified by backdrop or geometry options.
13957 width=(int) window_info.width;
13958 height=(int) window_info.height;
13959 if (resources.backdrop != MagickFalse)
13962 Center image on window.
13964 window_info.x=(window_attributes.width/2)-
13965 (window_info.ximage->width/2);
13966 window_info.y=(window_attributes.height/2)-
13967 (window_info.ximage->height/2);
13968 width=window_attributes.width;
13969 height=window_attributes.height;
13971 if ((resources.image_geometry != (char *) NULL) &&
13972 (*resources.image_geometry != '\0'))
13975 default_geometry[MaxTextExtent];
13985 User specified geometry.
13987 size_hints=XAllocSizeHints();
13988 if (size_hints == (XSizeHints *) NULL)
13989 ThrowXWindowFatalException(ResourceLimitFatalError,
13990 "MemoryAllocationFailed",image->filename);
13991 size_hints->flags=0L;
13992 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
13994 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13995 default_geometry,window_info.border_width,size_hints,&window_info.x,
13996 &window_info.y,&width,&height,&gravity);
13997 if (flags & (XValue | YValue))
13999 width=window_attributes.width;
14000 height=window_attributes.height;
14002 (void) XFree((void *) size_hints);
14005 Create the X pixmap.
14007 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14008 (unsigned int) height,window_info.depth);
14009 if (window_info.pixmap == (Pixmap) NULL)
14010 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14013 Display pixmap on the window.
14015 if (((unsigned int) width > window_info.width) ||
14016 ((unsigned int) height > window_info.height))
14017 (void) XFillRectangle(display,window_info.pixmap,
14018 window_info.annotate_context,0,0,(unsigned int) width,
14019 (unsigned int) height);
14020 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14021 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14022 window_info.width,(unsigned int) window_info.height);
14023 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14024 (void) XClearWindow(display,window_info.id);
14025 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14026 XDelay(display,delay == 0UL ? 10UL : delay);
14027 (void) XSync(display,MagickFalse);
14028 return(window_info.id == root_window ? MagickTrue : MagickFalse);
14032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14036 + X D i s p l a y I m a g e %
14040 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14042 % XDisplayImage() displays an image via X11. A new image is created and
14043 % returned if the user interactively transforms the displayed image.
14045 % The format of the XDisplayImage method is:
14047 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14048 % char **argv,int argc,Image **image,size_t *state,
14049 % ExceptionInfo *exception)
14051 % A description of each parameter follows:
14053 % o nexus: Method XDisplayImage returns an image when the
14054 % user chooses 'Open Image' from the command menu or picks a tile
14055 % from the image directory. Otherwise a null image is returned.
14057 % o display: Specifies a connection to an X server; returned from
14060 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14062 % o argv: Specifies the application's argument list.
14064 % o argc: Specifies the number of arguments.
14066 % o image: Specifies an address to an address of an Image structure;
14068 % o exception: return any errors or warnings in this structure.
14071 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14072 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14074 #define MagnifySize 256 /* must be a power of 2 */
14075 #define MagickMenus 10
14076 #define MagickTitle "Commands"
14103 "Visual Directory...",
14149 "Contrast Stretch...",
14150 "Sigmoidal Contrast...",
14184 "Charcoal Draw...",
14198 "Region of Interest...",
14201 *MiscellanyMenu[] =
14216 "Browse Documentation",
14243 **Menus[MagickMenus] =
14281 VisualDirectoryCommand,
14295 OriginalSizeCommand,
14302 TransformCommands[] =
14308 RotateRightCommand,
14315 EnhanceCommands[] =
14323 ContrastStretchCommand,
14324 SigmoidalContrastCommand,
14332 EffectsCommands[] =
14336 ReduceNoiseCommand,
14356 CharcoalDrawCommand
14358 ImageEditCommands[] =
14369 RegionofInterestCommand
14371 MiscellanyCommands[] =
14375 ShowPreviewCommand,
14376 ShowHistogramCommand,
14385 BrowseDocumentationCommand,
14388 ShortCutsCommands[] =
14400 VirtualCommands[] =
14409 *Commands[MagickMenus] =
14419 MiscellanyCommands,
14424 command[MaxTextExtent],
14426 geometry[MaxTextExtent],
14427 resource_name[MaxTextExtent];
14454 working_directory[MaxTextExtent];
14460 *magick_windows[MaxXWindows];
14462 static unsigned int
14522 assert(image != (Image **) NULL);
14523 assert((*image)->signature == MagickSignature);
14524 if ((*image)->debug != MagickFalse)
14525 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14526 display_image=(*image);
14527 warning_handler=(WarningHandler) NULL;
14528 windows=XSetWindows((XWindows *) ~0);
14529 if (windows != (XWindows *) NULL)
14534 status=chdir(working_directory);
14536 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14537 "UnableToOpenFile","%s",working_directory);
14538 warning_handler=resource_info->display_warnings ?
14539 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14540 warning_handler=resource_info->display_warnings ?
14541 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14546 Allocate windows structure.
14548 resource_info->colors=display_image->colors;
14549 windows=XSetWindows(XInitializeWindows(display,resource_info));
14550 if (windows == (XWindows *) NULL)
14551 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14552 (*image)->filename);
14554 Initialize window id's.
14557 magick_windows[number_windows++]=(&windows->icon);
14558 magick_windows[number_windows++]=(&windows->backdrop);
14559 magick_windows[number_windows++]=(&windows->image);
14560 magick_windows[number_windows++]=(&windows->info);
14561 magick_windows[number_windows++]=(&windows->command);
14562 magick_windows[number_windows++]=(&windows->widget);
14563 magick_windows[number_windows++]=(&windows->popup);
14564 magick_windows[number_windows++]=(&windows->magnify);
14565 magick_windows[number_windows++]=(&windows->pan);
14566 for (i=0; i < (int) number_windows; i++)
14567 magick_windows[i]->id=(Window) NULL;
14572 Initialize font info.
14574 if (windows->font_info != (XFontStruct *) NULL)
14575 (void) XFreeFont(display,windows->font_info);
14576 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14577 if (windows->font_info == (XFontStruct *) NULL)
14578 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14579 resource_info->font);
14581 Initialize Standard Colormap.
14583 map_info=windows->map_info;
14584 icon_map=windows->icon_map;
14585 visual_info=windows->visual_info;
14586 icon_visual=windows->icon_visual;
14587 pixel=windows->pixel_info;
14588 icon_pixel=windows->icon_pixel;
14589 font_info=windows->font_info;
14590 icon_resources=windows->icon_resources;
14591 class_hints=windows->class_hints;
14592 manager_hints=windows->manager_hints;
14593 root_window=XRootWindow(display,visual_info->screen);
14594 nexus=NewImageList();
14595 if (display_image->debug != MagickFalse)
14597 (void) LogMagickEvent(X11Event,GetMagickModule(),
14598 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14599 (double) display_image->scene,(double) display_image->columns,
14600 (double) display_image->rows);
14601 if (display_image->colors != 0)
14602 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14603 display_image->colors);
14604 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14605 display_image->magick);
14607 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14608 map_info,pixel,exception);
14609 display_image->taint=MagickFalse;
14611 Initialize graphic context.
14613 windows->context.id=(Window) NULL;
14614 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14615 resource_info,&windows->context);
14616 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14617 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14618 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14619 manager_hints->flags=InputHint | StateHint;
14620 manager_hints->input=MagickFalse;
14621 manager_hints->initial_state=WithdrawnState;
14622 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14623 &windows->context);
14624 if (display_image->debug != MagickFalse)
14625 (void) LogMagickEvent(X11Event,GetMagickModule(),
14626 "Window id: 0x%lx (context)",windows->context.id);
14627 context_values.background=pixel->background_color.pixel;
14628 context_values.font=font_info->fid;
14629 context_values.foreground=pixel->foreground_color.pixel;
14630 context_values.graphics_exposures=MagickFalse;
14631 context_mask=(MagickStatusType)
14632 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14633 if (pixel->annotate_context != (GC) NULL)
14634 (void) XFreeGC(display,pixel->annotate_context);
14635 pixel->annotate_context=XCreateGC(display,windows->context.id,
14636 context_mask,&context_values);
14637 if (pixel->annotate_context == (GC) NULL)
14638 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14639 display_image->filename);
14640 context_values.background=pixel->depth_color.pixel;
14641 if (pixel->widget_context != (GC) NULL)
14642 (void) XFreeGC(display,pixel->widget_context);
14643 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14645 if (pixel->widget_context == (GC) NULL)
14646 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14647 display_image->filename);
14648 context_values.background=pixel->foreground_color.pixel;
14649 context_values.foreground=pixel->background_color.pixel;
14650 context_values.plane_mask=context_values.background ^
14651 context_values.foreground;
14652 if (pixel->highlight_context != (GC) NULL)
14653 (void) XFreeGC(display,pixel->highlight_context);
14654 pixel->highlight_context=XCreateGC(display,windows->context.id,
14655 (size_t) (context_mask | GCPlaneMask),&context_values);
14656 if (pixel->highlight_context == (GC) NULL)
14657 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14658 display_image->filename);
14659 (void) XDestroyWindow(display,windows->context.id);
14661 Initialize icon window.
14663 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14664 icon_resources,&windows->icon);
14665 windows->icon.geometry=resource_info->icon_geometry;
14666 XBestIconSize(display,&windows->icon,display_image);
14667 windows->icon.attributes.colormap=XDefaultColormap(display,
14668 icon_visual->screen);
14669 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14670 manager_hints->flags=InputHint | StateHint;
14671 manager_hints->input=MagickFalse;
14672 manager_hints->initial_state=IconicState;
14673 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14675 if (display_image->debug != MagickFalse)
14676 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14679 Initialize graphic context for icon window.
14681 if (icon_pixel->annotate_context != (GC) NULL)
14682 (void) XFreeGC(display,icon_pixel->annotate_context);
14683 context_values.background=icon_pixel->background_color.pixel;
14684 context_values.foreground=icon_pixel->foreground_color.pixel;
14685 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14686 (size_t) (GCBackground | GCForeground),&context_values);
14687 if (icon_pixel->annotate_context == (GC) NULL)
14688 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14689 display_image->filename);
14690 windows->icon.annotate_context=icon_pixel->annotate_context;
14692 Initialize Image window.
14694 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14696 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14697 if (resource_info->use_shared_memory == MagickFalse)
14698 windows->image.shared_memory=MagickFalse;
14699 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14704 title=InterpretImageProperties(resource_info->image_info,display_image,
14705 resource_info->title,exception);
14706 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14707 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14708 title=DestroyString(title);
14713 filename[MaxTextExtent];
14716 Window name is the base of the filename.
14718 GetPathComponent(display_image->magick_filename,TailPath,filename);
14719 if (display_image->scene == 0)
14720 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14721 "%s: %s",MagickPackageName,filename);
14723 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14724 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14725 (double) display_image->scene,(double) GetImageListLength(
14727 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14729 if (resource_info->immutable)
14730 windows->image.immutable=MagickTrue;
14731 windows->image.use_pixmap=resource_info->use_pixmap;
14732 windows->image.geometry=resource_info->image_geometry;
14733 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14734 XDisplayWidth(display,visual_info->screen),
14735 XDisplayHeight(display,visual_info->screen));
14736 geometry_info.width=display_image->columns;
14737 geometry_info.height=display_image->rows;
14740 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14741 &geometry_info.width,&geometry_info.height);
14742 windows->image.width=(unsigned int) geometry_info.width;
14743 windows->image.height=(unsigned int) geometry_info.height;
14744 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14745 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14746 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14747 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14748 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14749 resource_info,&windows->backdrop);
14750 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14753 Initialize backdrop window.
14755 windows->backdrop.x=0;
14756 windows->backdrop.y=0;
14757 (void) CloneString(&windows->backdrop.name,"Backdrop");
14758 windows->backdrop.flags=(size_t) (USSize | USPosition);
14759 windows->backdrop.width=(unsigned int)
14760 XDisplayWidth(display,visual_info->screen);
14761 windows->backdrop.height=(unsigned int)
14762 XDisplayHeight(display,visual_info->screen);
14763 windows->backdrop.border_width=0;
14764 windows->backdrop.immutable=MagickTrue;
14765 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14767 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14768 StructureNotifyMask;
14769 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14770 manager_hints->icon_window=windows->icon.id;
14771 manager_hints->input=MagickTrue;
14772 manager_hints->initial_state=resource_info->iconic ? IconicState :
14774 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14775 &windows->backdrop);
14776 if (display_image->debug != MagickFalse)
14777 (void) LogMagickEvent(X11Event,GetMagickModule(),
14778 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14779 (void) XMapWindow(display,windows->backdrop.id);
14780 (void) XClearWindow(display,windows->backdrop.id);
14781 if (windows->image.id != (Window) NULL)
14783 (void) XDestroyWindow(display,windows->image.id);
14784 windows->image.id=(Window) NULL;
14787 Position image in the center the backdrop.
14789 windows->image.flags|=USPosition;
14790 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14791 (windows->image.width/2);
14792 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14793 (windows->image.height/2);
14795 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14796 manager_hints->icon_window=windows->icon.id;
14797 manager_hints->input=MagickTrue;
14798 manager_hints->initial_state=resource_info->iconic ? IconicState :
14800 if (windows->group_leader.id != (Window) NULL)
14805 manager_hints->flags|=WindowGroupHint;
14806 manager_hints->window_group=windows->group_leader.id;
14807 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14808 if (display_image->debug != MagickFalse)
14809 (void) LogMagickEvent(X11Event,GetMagickModule(),
14810 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14812 XMakeWindow(display,
14813 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14814 argv,argc,class_hints,manager_hints,&windows->image);
14815 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14816 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14817 if (windows->group_leader.id != (Window) NULL)
14818 (void) XSetTransientForHint(display,windows->image.id,
14819 windows->group_leader.id);
14820 if (display_image->debug != MagickFalse)
14821 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14822 windows->image.id);
14824 Initialize Info widget.
14826 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14828 (void) CloneString(&windows->info.name,"Info");
14829 (void) CloneString(&windows->info.icon_name,"Info");
14830 windows->info.border_width=1;
14833 windows->info.flags|=PPosition;
14834 windows->info.attributes.win_gravity=UnmapGravity;
14835 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14836 StructureNotifyMask;
14837 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14838 manager_hints->input=MagickFalse;
14839 manager_hints->initial_state=NormalState;
14840 manager_hints->window_group=windows->image.id;
14841 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14843 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14844 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14845 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14846 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14847 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14848 if (windows->image.mapped != MagickFalse)
14849 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14850 if (display_image->debug != MagickFalse)
14851 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14854 Initialize Command widget.
14856 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14857 resource_info,&windows->command);
14858 windows->command.data=MagickMenus;
14859 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14860 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14861 resource_info->client_name);
14862 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14863 resource_name,"geometry",(char *) NULL);
14864 (void) CloneString(&windows->command.name,MagickTitle);
14865 windows->command.border_width=0;
14866 windows->command.flags|=PPosition;
14867 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14868 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14869 OwnerGrabButtonMask | StructureNotifyMask;
14870 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14871 manager_hints->input=MagickTrue;
14872 manager_hints->initial_state=NormalState;
14873 manager_hints->window_group=windows->image.id;
14874 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14875 &windows->command);
14876 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14877 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14879 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14880 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14881 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14882 if (windows->command.mapped != MagickFalse)
14883 (void) XMapRaised(display,windows->command.id);
14884 if (display_image->debug != MagickFalse)
14885 (void) LogMagickEvent(X11Event,GetMagickModule(),
14886 "Window id: 0x%lx (command)",windows->command.id);
14888 Initialize Widget window.
14890 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14891 resource_info,&windows->widget);
14892 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14893 resource_info->client_name);
14894 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14895 resource_name,"geometry",(char *) NULL);
14896 windows->widget.border_width=0;
14897 windows->widget.flags|=PPosition;
14898 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14899 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14900 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14901 StructureNotifyMask;
14902 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14903 manager_hints->input=MagickTrue;
14904 manager_hints->initial_state=NormalState;
14905 manager_hints->window_group=windows->image.id;
14906 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14908 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14909 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14910 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14911 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14912 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14913 if (display_image->debug != MagickFalse)
14914 (void) LogMagickEvent(X11Event,GetMagickModule(),
14915 "Window id: 0x%lx (widget)",windows->widget.id);
14917 Initialize popup window.
14919 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14920 resource_info,&windows->popup);
14921 windows->popup.border_width=0;
14922 windows->popup.flags|=PPosition;
14923 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14924 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14925 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14926 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14927 manager_hints->input=MagickTrue;
14928 manager_hints->initial_state=NormalState;
14929 manager_hints->window_group=windows->image.id;
14930 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14932 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14933 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14934 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14935 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14936 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14937 if (display_image->debug != MagickFalse)
14938 (void) LogMagickEvent(X11Event,GetMagickModule(),
14939 "Window id: 0x%lx (pop up)",windows->popup.id);
14941 Initialize Magnify window and cursor.
14943 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14944 resource_info,&windows->magnify);
14945 if (resource_info->use_shared_memory == MagickFalse)
14946 windows->magnify.shared_memory=MagickFalse;
14947 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14948 resource_info->client_name);
14949 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14950 resource_name,"geometry",(char *) NULL);
14951 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14952 resource_info->magnify);
14953 if (windows->magnify.cursor != (Cursor) NULL)
14954 (void) XFreeCursor(display,windows->magnify.cursor);
14955 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14956 map_info->colormap,resource_info->background_color,
14957 resource_info->foreground_color);
14958 if (windows->magnify.cursor == (Cursor) NULL)
14959 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14960 display_image->filename);
14961 windows->magnify.width=MagnifySize;
14962 windows->magnify.height=MagnifySize;
14963 windows->magnify.flags|=PPosition;
14964 windows->magnify.min_width=MagnifySize;
14965 windows->magnify.min_height=MagnifySize;
14966 windows->magnify.width_inc=MagnifySize;
14967 windows->magnify.height_inc=MagnifySize;
14968 windows->magnify.data=resource_info->magnify;
14969 windows->magnify.attributes.cursor=windows->magnify.cursor;
14970 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14971 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14972 StructureNotifyMask;
14973 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14974 manager_hints->input=MagickTrue;
14975 manager_hints->initial_state=NormalState;
14976 manager_hints->window_group=windows->image.id;
14977 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14978 &windows->magnify);
14979 if (display_image->debug != MagickFalse)
14980 (void) LogMagickEvent(X11Event,GetMagickModule(),
14981 "Window id: 0x%lx (magnify)",windows->magnify.id);
14982 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14984 Initialize panning window.
14986 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14987 resource_info,&windows->pan);
14988 (void) CloneString(&windows->pan.name,"Pan Icon");
14989 windows->pan.width=windows->icon.width;
14990 windows->pan.height=windows->icon.height;
14991 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
14992 resource_info->client_name);
14993 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14994 resource_name,"geometry",(char *) NULL);
14995 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14996 &windows->pan.width,&windows->pan.height);
14997 windows->pan.flags|=PPosition;
14998 windows->pan.immutable=MagickTrue;
14999 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15000 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15001 StructureNotifyMask;
15002 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15003 manager_hints->input=MagickFalse;
15004 manager_hints->initial_state=NormalState;
15005 manager_hints->window_group=windows->image.id;
15006 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15008 if (display_image->debug != MagickFalse)
15009 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15011 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15012 if (windows->info.mapped != MagickFalse)
15013 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15014 if ((windows->image.mapped == MagickFalse) ||
15015 (windows->backdrop.id != (Window) NULL))
15016 (void) XMapWindow(display,windows->image.id);
15018 Set our progress monitor and warning handlers.
15020 if (warning_handler == (WarningHandler) NULL)
15022 warning_handler=resource_info->display_warnings ?
15023 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15024 warning_handler=resource_info->display_warnings ?
15025 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15028 Initialize Image and Magnify X images.
15030 windows->image.x=0;
15031 windows->image.y=0;
15032 windows->magnify.shape=MagickFalse;
15033 width=(unsigned int) display_image->columns;
15034 height=(unsigned int) display_image->rows;
15035 if ((display_image->columns != width) || (display_image->rows != height))
15036 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15037 display_image->filename);
15038 status=XMakeImage(display,resource_info,&windows->image,display_image,
15039 width,height,exception);
15040 if (status == MagickFalse)
15041 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15042 display_image->filename);
15043 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15044 windows->magnify.width,windows->magnify.height,exception);
15045 if (status == MagickFalse)
15046 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15047 display_image->filename);
15048 if (windows->magnify.mapped != MagickFalse)
15049 (void) XMapRaised(display,windows->magnify.id);
15050 if (windows->pan.mapped != MagickFalse)
15051 (void) XMapRaised(display,windows->pan.id);
15052 windows->image.window_changes.width=(int) display_image->columns;
15053 windows->image.window_changes.height=(int) display_image->rows;
15054 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15055 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15056 (void) XSync(display,MagickFalse);
15060 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15061 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15063 if (resource_info->update != MagickFalse)
15069 Determine when file data was last modified.
15071 status=GetPathAttributes(display_image->filename,&attributes);
15072 if (status != MagickFalse)
15073 update_time=attributes.st_mtime;
15075 *state&=(~FormerImageState);
15076 *state&=(~MontageImageState);
15077 *state&=(~NextImageState);
15081 Handle a window event.
15083 if (windows->image.mapped != MagickFalse)
15084 if ((display_image->delay != 0) || (resource_info->update != 0))
15086 if (timer < time((time_t *) NULL))
15088 if (resource_info->update == MagickFalse)
15089 *state|=NextImageState | ExitState;
15096 Determine if image file was modified.
15098 status=GetPathAttributes(display_image->filename,&attributes);
15099 if (status != MagickFalse)
15100 if (update_time != attributes.st_mtime)
15105 (void) FormatLocaleString(
15106 resource_info->image_info->filename,MaxTextExtent,
15107 "%s:%s",display_image->magick,
15108 display_image->filename);
15109 nexus=ReadImage(resource_info->image_info,exception);
15110 if (nexus != (Image *) NULL)
15112 nexus=DestroyImage(nexus);
15113 *state|=NextImageState | ExitState;
15116 delay=display_image->delay/MagickMax(
15117 display_image->ticks_per_second,1L);
15118 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15121 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15124 Do not block if delay > 0.
15126 XDelay(display,SuspendTime << 2);
15130 timestamp=time((time_t *) NULL);
15131 (void) XNextEvent(display,&event);
15132 if (windows->image.stasis == MagickFalse)
15133 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15134 MagickTrue : MagickFalse;
15135 if (windows->magnify.stasis == MagickFalse)
15136 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15137 MagickTrue : MagickFalse;
15138 if (event.xany.window == windows->command.id)
15141 Select a command from the Command widget.
15143 id=XCommandWidget(display,windows,CommandMenu,&event);
15146 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15147 command_type=CommandMenus[id];
15148 if (id < MagickMenus)
15151 Select a command from a pop-up menu.
15153 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15157 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15158 command_type=Commands[id][entry];
15160 if (command_type != NullCommand)
15161 nexus=XMagickCommand(display,resource_info,windows,command_type,
15162 &display_image,exception);
15165 switch (event.type)
15169 if (display_image->debug != MagickFalse)
15170 (void) LogMagickEvent(X11Event,GetMagickModule(),
15171 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15172 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15173 if ((event.xbutton.button == Button3) &&
15174 (event.xbutton.state & Mod1Mask))
15177 Convert Alt-Button3 to Button2.
15179 event.xbutton.button=Button2;
15180 event.xbutton.state&=(~Mod1Mask);
15182 if (event.xbutton.window == windows->backdrop.id)
15184 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15185 event.xbutton.time);
15188 if (event.xbutton.window == windows->image.id)
15190 switch (event.xbutton.button)
15194 if (resource_info->immutable)
15197 Select a command from the Virtual menu.
15199 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15202 nexus=XMagickCommand(display,resource_info,windows,
15203 VirtualCommands[entry],&display_image,exception);
15207 Map/unmap Command widget.
15209 if (windows->command.mapped != MagickFalse)
15210 (void) XWithdrawWindow(display,windows->command.id,
15211 windows->command.screen);
15214 (void) XCommandWidget(display,windows,CommandMenu,
15216 (void) XMapRaised(display,windows->command.id);
15223 User pressed the image magnify button.
15225 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15226 &display_image,exception);
15227 XMagnifyImage(display,windows,&event,exception);
15232 if (resource_info->immutable)
15235 Select a command from the Virtual menu.
15237 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15240 nexus=XMagickCommand(display,resource_info,windows,
15241 VirtualCommands[entry],&display_image,exception);
15244 if (display_image->montage != (char *) NULL)
15247 Open or delete a tile from a visual image directory.
15249 nexus=XTileImage(display,resource_info,windows,
15250 display_image,&event,exception);
15251 if (nexus != (Image *) NULL)
15252 *state|=MontageImageState | NextImageState | ExitState;
15253 vid_info.x=(short int) windows->image.x;
15254 vid_info.y=(short int) windows->image.y;
15258 Select a command from the Short Cuts menu.
15260 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15263 nexus=XMagickCommand(display,resource_info,windows,
15264 ShortCutsCommands[entry],&display_image,exception);
15272 XTranslateImage(display,windows,*image,XK_Up);
15280 XTranslateImage(display,windows,*image,XK_Down);
15288 if (event.xbutton.window == windows->magnify.id)
15308 MagnifyCommands[] =
15321 Select a magnify factor from the pop-up menu.
15323 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15325 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15329 if (event.xbutton.window == windows->pan.id)
15331 switch (event.xbutton.button)
15338 XTranslateImage(display,windows,*image,XK_Up);
15346 XTranslateImage(display,windows,*image,XK_Down);
15351 XPanImage(display,windows,&event,exception);
15357 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15359 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15362 case ButtonRelease:
15364 if (display_image->debug != MagickFalse)
15365 (void) LogMagickEvent(X11Event,GetMagickModule(),
15366 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15367 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15370 case ClientMessage:
15372 if (display_image->debug != MagickFalse)
15373 (void) LogMagickEvent(X11Event,GetMagickModule(),
15374 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15375 event.xclient.message_type,event.xclient.format,(unsigned long)
15376 event.xclient.data.l[0]);
15377 if (event.xclient.message_type == windows->im_protocols)
15379 if (*event.xclient.data.l == (long) windows->im_update_widget)
15381 (void) CloneString(&windows->command.name,MagickTitle);
15382 windows->command.data=MagickMenus;
15383 (void) XCommandWidget(display,windows,CommandMenu,
15387 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15390 Update graphic context and window colormap.
15392 for (i=0; i < (int) number_windows; i++)
15394 if (magick_windows[i]->id == windows->icon.id)
15396 context_values.background=pixel->background_color.pixel;
15397 context_values.foreground=pixel->foreground_color.pixel;
15398 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15399 context_mask,&context_values);
15400 (void) XChangeGC(display,magick_windows[i]->widget_context,
15401 context_mask,&context_values);
15402 context_values.background=pixel->foreground_color.pixel;
15403 context_values.foreground=pixel->background_color.pixel;
15404 context_values.plane_mask=context_values.background ^
15405 context_values.foreground;
15406 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15407 (size_t) (context_mask | GCPlaneMask),
15409 magick_windows[i]->attributes.background_pixel=
15410 pixel->background_color.pixel;
15411 magick_windows[i]->attributes.border_pixel=
15412 pixel->border_color.pixel;
15413 magick_windows[i]->attributes.colormap=map_info->colormap;
15414 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15415 (unsigned long) magick_windows[i]->mask,
15416 &magick_windows[i]->attributes);
15418 if (windows->pan.mapped != MagickFalse)
15420 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15421 windows->pan.pixmap);
15422 (void) XClearWindow(display,windows->pan.id);
15423 XDrawPanRectangle(display,windows);
15425 if (windows->backdrop.id != (Window) NULL)
15426 (void) XInstallColormap(display,map_info->colormap);
15429 if (*event.xclient.data.l == (long) windows->im_former_image)
15431 *state|=FormerImageState | ExitState;
15434 if (*event.xclient.data.l == (long) windows->im_next_image)
15436 *state|=NextImageState | ExitState;
15439 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15441 *state|=RetainColorsState;
15444 if (*event.xclient.data.l == (long) windows->im_exit)
15451 if (event.xclient.message_type == windows->dnd_protocols)
15469 Display image named by the Drag-and-Drop selection.
15471 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15473 selection=XInternAtom(display,"DndSelection",MagickFalse);
15474 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15475 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15476 &length,&after,&data);
15477 if ((status != Success) || (length == 0))
15479 if (*event.xclient.data.l == 2)
15484 (void) CopyMagickString(resource_info->image_info->filename,
15485 (char *) data,MaxTextExtent);
15492 if (strncmp((char *) data, "file:", 5) != 0)
15494 (void) XFree((void *) data);
15497 (void) CopyMagickString(resource_info->image_info->filename,
15498 ((char *) data)+5,MaxTextExtent);
15500 nexus=ReadImage(resource_info->image_info,exception);
15501 CatchException(exception);
15502 if (nexus != (Image *) NULL)
15503 *state|=NextImageState | ExitState;
15504 (void) XFree((void *) data);
15508 If client window delete message, exit.
15510 if (event.xclient.message_type != windows->wm_protocols)
15512 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15514 (void) XWithdrawWindow(display,event.xclient.window,
15515 visual_info->screen);
15516 if (event.xclient.window == windows->image.id)
15521 if (event.xclient.window == windows->pan.id)
15524 Restore original image size when pan window is deleted.
15526 windows->image.window_changes.width=windows->image.ximage->width;
15527 windows->image.window_changes.height=windows->image.ximage->height;
15528 (void) XConfigureImage(display,resource_info,windows,
15529 display_image,exception);
15533 case ConfigureNotify:
15535 if (display_image->debug != MagickFalse)
15536 (void) LogMagickEvent(X11Event,GetMagickModule(),
15537 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15538 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15539 event.xconfigure.y,event.xconfigure.send_event);
15540 if (event.xconfigure.window == windows->image.id)
15543 Image window has a new configuration.
15545 if (event.xconfigure.send_event != 0)
15551 Position the transient windows relative of the Image window.
15553 if (windows->command.geometry == (char *) NULL)
15554 if (windows->command.mapped == MagickFalse)
15556 windows->command.x=event.xconfigure.x-
15557 windows->command.width-25;
15558 windows->command.y=event.xconfigure.y;
15559 XConstrainWindowPosition(display,&windows->command);
15560 window_changes.x=windows->command.x;
15561 window_changes.y=windows->command.y;
15562 (void) XReconfigureWMWindow(display,windows->command.id,
15563 windows->command.screen,(unsigned int) (CWX | CWY),
15566 if (windows->widget.geometry == (char *) NULL)
15567 if (windows->widget.mapped == MagickFalse)
15569 windows->widget.x=event.xconfigure.x+
15570 event.xconfigure.width/10;
15571 windows->widget.y=event.xconfigure.y+
15572 event.xconfigure.height/10;
15573 XConstrainWindowPosition(display,&windows->widget);
15574 window_changes.x=windows->widget.x;
15575 window_changes.y=windows->widget.y;
15576 (void) XReconfigureWMWindow(display,windows->widget.id,
15577 windows->widget.screen,(unsigned int) (CWX | CWY),
15580 if (windows->magnify.geometry == (char *) NULL)
15581 if (windows->magnify.mapped == MagickFalse)
15583 windows->magnify.x=event.xconfigure.x+
15584 event.xconfigure.width+25;
15585 windows->magnify.y=event.xconfigure.y;
15586 XConstrainWindowPosition(display,&windows->magnify);
15587 window_changes.x=windows->magnify.x;
15588 window_changes.y=windows->magnify.y;
15589 (void) XReconfigureWMWindow(display,windows->magnify.id,
15590 windows->magnify.screen,(unsigned int) (CWX | CWY),
15593 if (windows->pan.geometry == (char *) NULL)
15594 if (windows->pan.mapped == MagickFalse)
15596 windows->pan.x=event.xconfigure.x+
15597 event.xconfigure.width+25;
15598 windows->pan.y=event.xconfigure.y+
15599 windows->magnify.height+50;
15600 XConstrainWindowPosition(display,&windows->pan);
15601 window_changes.x=windows->pan.x;
15602 window_changes.y=windows->pan.y;
15603 (void) XReconfigureWMWindow(display,windows->pan.id,
15604 windows->pan.screen,(unsigned int) (CWX | CWY),
15608 if ((event.xconfigure.width == (int) windows->image.width) &&
15609 (event.xconfigure.height == (int) windows->image.height))
15611 windows->image.width=(unsigned int) event.xconfigure.width;
15612 windows->image.height=(unsigned int) event.xconfigure.height;
15613 windows->image.x=0;
15614 windows->image.y=0;
15615 if (display_image->montage != (char *) NULL)
15617 windows->image.x=vid_info.x;
15618 windows->image.y=vid_info.y;
15620 if ((windows->image.mapped != MagickFalse) &&
15621 (windows->image.stasis != MagickFalse))
15624 Update image window configuration.
15626 windows->image.window_changes.width=event.xconfigure.width;
15627 windows->image.window_changes.height=event.xconfigure.height;
15628 (void) XConfigureImage(display,resource_info,windows,
15629 display_image,exception);
15632 Update pan window configuration.
15634 if ((event.xconfigure.width < windows->image.ximage->width) ||
15635 (event.xconfigure.height < windows->image.ximage->height))
15637 (void) XMapRaised(display,windows->pan.id);
15638 XDrawPanRectangle(display,windows);
15641 if (windows->pan.mapped != MagickFalse)
15642 (void) XWithdrawWindow(display,windows->pan.id,
15643 windows->pan.screen);
15646 if (event.xconfigure.window == windows->magnify.id)
15652 Magnify window has a new configuration.
15654 windows->magnify.width=(unsigned int) event.xconfigure.width;
15655 windows->magnify.height=(unsigned int) event.xconfigure.height;
15656 if (windows->magnify.mapped == MagickFalse)
15659 while ((int) magnify <= event.xconfigure.width)
15661 while ((int) magnify <= event.xconfigure.height)
15664 if (((int) magnify != event.xconfigure.width) ||
15665 ((int) magnify != event.xconfigure.height))
15667 window_changes.width=(int) magnify;
15668 window_changes.height=(int) magnify;
15669 (void) XReconfigureWMWindow(display,windows->magnify.id,
15670 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15674 if ((windows->magnify.mapped != MagickFalse) &&
15675 (windows->magnify.stasis != MagickFalse))
15677 status=XMakeImage(display,resource_info,&windows->magnify,
15678 display_image,windows->magnify.width,windows->magnify.height,
15680 XMakeMagnifyImage(display,windows,exception);
15684 if ((windows->magnify.mapped != MagickFalse) &&
15685 (event.xconfigure.window == windows->pan.id))
15688 Pan icon window has a new configuration.
15690 if (event.xconfigure.send_event != 0)
15692 windows->pan.x=event.xconfigure.x;
15693 windows->pan.y=event.xconfigure.y;
15695 windows->pan.width=(unsigned int) event.xconfigure.width;
15696 windows->pan.height=(unsigned int) event.xconfigure.height;
15699 if (event.xconfigure.window == windows->icon.id)
15702 Icon window has a new configuration.
15704 windows->icon.width=(unsigned int) event.xconfigure.width;
15705 windows->icon.height=(unsigned int) event.xconfigure.height;
15710 case DestroyNotify:
15713 Group leader has exited.
15715 if (display_image->debug != MagickFalse)
15716 (void) LogMagickEvent(X11Event,GetMagickModule(),
15717 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15718 if (event.xdestroywindow.window == windows->group_leader.id)
15728 Selectively install colormap.
15730 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15731 if (event.xcrossing.mode != NotifyUngrab)
15732 XInstallColormap(display,map_info->colormap);
15737 if (display_image->debug != MagickFalse)
15738 (void) LogMagickEvent(X11Event,GetMagickModule(),
15739 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15740 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15743 Refresh windows that are now exposed.
15745 if ((event.xexpose.window == windows->image.id) &&
15746 (windows->image.mapped != MagickFalse))
15748 XRefreshWindow(display,&windows->image,&event);
15749 delay=display_image->delay/MagickMax(
15750 display_image->ticks_per_second,1L);
15751 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15754 if ((event.xexpose.window == windows->magnify.id) &&
15755 (windows->magnify.mapped != MagickFalse))
15757 XMakeMagnifyImage(display,windows,exception);
15760 if (event.xexpose.window == windows->pan.id)
15762 XDrawPanRectangle(display,windows);
15765 if (event.xexpose.window == windows->icon.id)
15767 XRefreshWindow(display,&windows->icon,&event);
15778 Respond to a user key press.
15780 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15781 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15782 *(command+length)='\0';
15783 if (display_image->debug != MagickFalse)
15784 (void) LogMagickEvent(X11Event,GetMagickModule(),
15785 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15786 key_symbol,command);
15787 if (event.xkey.window == windows->image.id)
15789 command_type=XImageWindowCommand(display,resource_info,windows,
15790 event.xkey.state,key_symbol,&display_image,exception);
15791 if (command_type != NullCommand)
15792 nexus=XMagickCommand(display,resource_info,windows,command_type,
15793 &display_image,exception);
15795 if (event.xkey.window == windows->magnify.id)
15796 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15798 if (event.xkey.window == windows->pan.id)
15800 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15801 (void) XWithdrawWindow(display,windows->pan.id,
15802 windows->pan.screen);
15804 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15805 XTextViewWidget(display,resource_info,windows,MagickFalse,
15806 "Help Viewer - Image Pan",ImagePanHelp);
15808 XTranslateImage(display,windows,*image,key_symbol);
15810 delay=display_image->delay/MagickMax(
15811 display_image->ticks_per_second,1L);
15812 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15818 Respond to a user key release.
15820 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15821 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15822 if (display_image->debug != MagickFalse)
15823 (void) LogMagickEvent(X11Event,GetMagickModule(),
15824 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15830 Selectively uninstall colormap.
15832 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15833 if (event.xcrossing.mode != NotifyUngrab)
15834 XUninstallColormap(display,map_info->colormap);
15839 if (display_image->debug != MagickFalse)
15840 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15841 event.xmap.window);
15842 if (event.xmap.window == windows->backdrop.id)
15844 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15846 windows->backdrop.mapped=MagickTrue;
15849 if (event.xmap.window == windows->image.id)
15851 if (windows->backdrop.id != (Window) NULL)
15852 (void) XInstallColormap(display,map_info->colormap);
15853 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15855 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15856 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15858 if (((int) windows->image.width < windows->image.ximage->width) ||
15859 ((int) windows->image.height < windows->image.ximage->height))
15860 (void) XMapRaised(display,windows->pan.id);
15861 windows->image.mapped=MagickTrue;
15864 if (event.xmap.window == windows->magnify.id)
15866 XMakeMagnifyImage(display,windows,exception);
15867 windows->magnify.mapped=MagickTrue;
15868 (void) XWithdrawWindow(display,windows->info.id,
15869 windows->info.screen);
15872 if (event.xmap.window == windows->pan.id)
15874 XMakePanImage(display,resource_info,windows,display_image,
15876 windows->pan.mapped=MagickTrue;
15879 if (event.xmap.window == windows->info.id)
15881 windows->info.mapped=MagickTrue;
15884 if (event.xmap.window == windows->icon.id)
15890 Create an icon image.
15892 taint=display_image->taint;
15893 XMakeStandardColormap(display,icon_visual,icon_resources,
15894 display_image,icon_map,icon_pixel,exception);
15895 (void) XMakeImage(display,icon_resources,&windows->icon,
15896 display_image,windows->icon.width,windows->icon.height,
15898 display_image->taint=taint;
15899 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15900 windows->icon.pixmap);
15901 (void) XClearWindow(display,windows->icon.id);
15902 (void) XWithdrawWindow(display,windows->info.id,
15903 windows->info.screen);
15904 windows->icon.mapped=MagickTrue;
15907 if (event.xmap.window == windows->command.id)
15909 windows->command.mapped=MagickTrue;
15912 if (event.xmap.window == windows->popup.id)
15914 windows->popup.mapped=MagickTrue;
15917 if (event.xmap.window == windows->widget.id)
15919 windows->widget.mapped=MagickTrue;
15924 case MappingNotify:
15926 (void) XRefreshKeyboardMapping(&event.xmapping);
15931 case PropertyNotify:
15947 if (display_image->debug != MagickFalse)
15948 (void) LogMagickEvent(X11Event,GetMagickModule(),
15949 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15950 event.xproperty.atom,event.xproperty.state);
15951 if (event.xproperty.atom != windows->im_remote_command)
15954 Display image named by the remote command protocol.
15956 status=XGetWindowProperty(display,event.xproperty.window,
15957 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15958 AnyPropertyType,&type,&format,&length,&after,&data);
15959 if ((status != Success) || (length == 0))
15961 if (LocaleCompare((char *) data,"-quit") == 0)
15963 XClientMessage(display,windows->image.id,windows->im_protocols,
15964 windows->im_exit,CurrentTime);
15965 (void) XFree((void *) data);
15968 (void) CopyMagickString(resource_info->image_info->filename,
15969 (char *) data,MaxTextExtent);
15970 (void) XFree((void *) data);
15971 nexus=ReadImage(resource_info->image_info,exception);
15972 CatchException(exception);
15973 if (nexus != (Image *) NULL)
15974 *state|=NextImageState | ExitState;
15977 case ReparentNotify:
15979 if (display_image->debug != MagickFalse)
15980 (void) LogMagickEvent(X11Event,GetMagickModule(),
15981 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15982 event.xreparent.window);
15987 if (display_image->debug != MagickFalse)
15988 (void) LogMagickEvent(X11Event,GetMagickModule(),
15989 "Unmap Notify: 0x%lx",event.xunmap.window);
15990 if (event.xunmap.window == windows->backdrop.id)
15992 windows->backdrop.mapped=MagickFalse;
15995 if (event.xunmap.window == windows->image.id)
15997 windows->image.mapped=MagickFalse;
16000 if (event.xunmap.window == windows->magnify.id)
16002 windows->magnify.mapped=MagickFalse;
16005 if (event.xunmap.window == windows->pan.id)
16007 windows->pan.mapped=MagickFalse;
16010 if (event.xunmap.window == windows->info.id)
16012 windows->info.mapped=MagickFalse;
16015 if (event.xunmap.window == windows->icon.id)
16017 if (map_info->colormap == icon_map->colormap)
16018 XConfigureImageColormap(display,resource_info,windows,
16019 display_image,exception);
16020 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16022 windows->icon.mapped=MagickFalse;
16025 if (event.xunmap.window == windows->command.id)
16027 windows->command.mapped=MagickFalse;
16030 if (event.xunmap.window == windows->popup.id)
16032 if (windows->backdrop.id != (Window) NULL)
16033 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16035 windows->popup.mapped=MagickFalse;
16038 if (event.xunmap.window == windows->widget.id)
16040 if (windows->backdrop.id != (Window) NULL)
16041 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16043 windows->widget.mapped=MagickFalse;
16050 if (display_image->debug != MagickFalse)
16051 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16056 } while (!(*state & ExitState));
16057 if ((*state & ExitState) == 0)
16058 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16059 &display_image,exception);
16061 if (resource_info->confirm_edit != MagickFalse)
16064 Query user if image has changed.
16066 if ((resource_info->immutable == MagickFalse) &&
16067 (display_image->taint != MagickFalse))
16072 status=XConfirmWidget(display,windows,"Your image changed.",
16073 "Do you want to save it");
16075 *state&=(~ExitState);
16078 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16079 &display_image,exception);
16082 if ((windows->visual_info->klass == GrayScale) ||
16083 (windows->visual_info->klass == PseudoColor) ||
16084 (windows->visual_info->klass == DirectColor))
16087 Withdraw pan and Magnify window.
16089 if (windows->info.mapped != MagickFalse)
16090 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16091 if (windows->magnify.mapped != MagickFalse)
16092 (void) XWithdrawWindow(display,windows->magnify.id,
16093 windows->magnify.screen);
16094 if (windows->command.mapped != MagickFalse)
16095 (void) XWithdrawWindow(display,windows->command.id,
16096 windows->command.screen);
16098 if (windows->pan.mapped != MagickFalse)
16099 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16100 if (resource_info->backdrop == MagickFalse)
16101 if (windows->backdrop.mapped)
16103 (void) XWithdrawWindow(display,windows->backdrop.id,
16104 windows->backdrop.screen);
16105 (void) XDestroyWindow(display,windows->backdrop.id);
16106 windows->backdrop.id=(Window) NULL;
16107 (void) XWithdrawWindow(display,windows->image.id,
16108 windows->image.screen);
16109 (void) XDestroyWindow(display,windows->image.id);
16110 windows->image.id=(Window) NULL;
16112 XSetCursorState(display,windows,MagickTrue);
16113 XCheckRefreshWindows(display,windows);
16114 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16115 *state&=(~ExitState);
16116 if (*state & ExitState)
16119 Free Standard Colormap.
16121 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16122 if (resource_info->map_type == (char *) NULL)
16123 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16127 if (resource_info->copy_image != (Image *) NULL)
16129 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16130 resource_info->copy_image=NewImageList();
16132 DestroyXResources();
16134 (void) XSync(display,MagickFalse);
16136 Restore our progress monitor and warning handlers.
16138 (void) SetErrorHandler(warning_handler);
16139 (void) SetWarningHandler(warning_handler);
16141 Change to home directory.
16143 directory=getcwd(working_directory,MaxTextExtent);
16149 status=chdir(resource_info->home_directory);
16151 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16152 "UnableToOpenFile","%s",resource_info->home_directory);
16154 *image=display_image;
16160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16164 + D i s p l a y I m a g e s %
16168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16170 % DisplayImages() displays an image sequence to any X window screen. It
16171 % returns a value other than 0 if successful. Check the exception member
16172 % of image to determine the reason for any failure.
16174 % The format of the DisplayImages method is:
16176 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16177 % Image *images,ExceptionInfo *exception)
16179 % A description of each parameter follows:
16181 % o image_info: the image info.
16183 % o image: the image.
16185 % o exception: return any errors or warnings in this structure.
16188 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16189 Image *image,ExceptionInfo *exception)
16191 assert(image_info != (const ImageInfo *) NULL);
16192 assert(image_info->signature == MagickSignature);
16193 assert(image != (Image *) NULL);
16194 assert(image->signature == MagickSignature);
16195 if (image->debug != MagickFalse)
16196 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16197 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16198 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
16199 return(MagickFalse);
16203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16207 + R e m o t e D i s p l a y C o m m a n d %
16211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16213 % RemoteDisplayCommand() encourages a remote display program to display the
16214 % specified image filename.
16216 % The format of the RemoteDisplayCommand method is:
16218 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16219 % const char *window,const char *filename,ExceptionInfo *exception)
16221 % A description of each parameter follows:
16223 % o image_info: the image info.
16225 % o window: Specifies the name or id of an X window.
16227 % o filename: the name of the image filename to display.
16229 % o exception: return any errors or warnings in this structure.
16232 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16233 const char *window,const char *filename,ExceptionInfo *exception)
16235 assert(image_info != (const ImageInfo *) NULL);
16236 assert(image_info->signature == MagickSignature);
16237 assert(filename != (char *) NULL);
16239 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16240 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16241 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
16242 return(MagickFalse);