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-2015 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/attribute.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/channel.h"
49 #include "MagickCore/client.h"
50 #include "MagickCore/color.h"
51 #include "MagickCore/colorspace.h"
52 #include "MagickCore/composite.h"
53 #include "MagickCore/constitute.h"
54 #include "MagickCore/decorate.h"
55 #include "MagickCore/delegate.h"
56 #include "MagickCore/display.h"
57 #include "MagickCore/display-private.h"
58 #include "MagickCore/distort.h"
59 #include "MagickCore/draw.h"
60 #include "MagickCore/effect.h"
61 #include "MagickCore/enhance.h"
62 #include "MagickCore/exception.h"
63 #include "MagickCore/exception-private.h"
64 #include "MagickCore/fx.h"
65 #include "MagickCore/geometry.h"
66 #include "MagickCore/image.h"
67 #include "MagickCore/image-private.h"
68 #include "MagickCore/list.h"
69 #include "MagickCore/log.h"
70 #include "MagickCore/magick.h"
71 #include "MagickCore/memory_.h"
72 #include "MagickCore/monitor.h"
73 #include "MagickCore/monitor-private.h"
74 #include "MagickCore/montage.h"
75 #include "MagickCore/nt-base-private.h"
76 #include "MagickCore/option.h"
77 #include "MagickCore/paint.h"
78 #include "MagickCore/pixel.h"
79 #include "MagickCore/pixel-accessor.h"
80 #include "MagickCore/PreRvIcccm.h"
81 #include "MagickCore/property.h"
82 #include "MagickCore/quantum.h"
83 #include "MagickCore/quantum-private.h"
84 #include "MagickCore/resize.h"
85 #include "MagickCore/resource_.h"
86 #include "MagickCore/shear.h"
87 #include "MagickCore/segment.h"
88 #include "MagickCore/statistic.h"
89 #include "MagickCore/string_.h"
90 #include "MagickCore/string-private.h"
91 #include "MagickCore/transform.h"
92 #include "MagickCore/threshold.h"
93 #include "MagickCore/utility.h"
94 #include "MagickCore/utility-private.h"
95 #include "MagickCore/version.h"
96 #include "MagickCore/widget.h"
97 #include "MagickCore/widget-private.h"
98 #include "MagickCore/xwindow.h"
99 #include "MagickCore/xwindow-private.h"
101 #if defined(MAGICKCORE_X11_DELEGATE)
105 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
108 Constant declarations.
110 static const unsigned char
113 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
117 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
145 Help widget declarations.
148 *ImageAnnotateHelp[] =
150 "In annotate mode, the Command widget has these options:",
200 "Choose a font name from the Font Name sub-menu. Additional",
201 "font names can be specified with the font browser. You can",
202 "change the menu names by setting the X resources font1",
205 "Choose a font color from the Font Color sub-menu.",
206 "Additional font colors can be specified with the color",
207 "browser. You can change the menu colors by setting the X",
208 "resources pen1 through pen9.",
210 "If you select the color browser and press Grab, you can",
211 "choose the font color by moving the pointer to the desired",
212 "color on the screen and press any button.",
214 "If you choose to rotate the text, choose Rotate Text from the",
215 "menu and select an angle. Typically you will only want to",
216 "rotate one line of text at a time. Depending on the angle you",
217 "choose, subsequent lines may end up overwriting each other.",
219 "Choosing a font and its color is optional. The default font",
220 "is fixed and the default color is black. However, you must",
221 "choose a location to begin entering text and press button 1.",
222 "An underscore character will appear at the location of the",
223 "pointer. The cursor changes to a pencil to indicate you are",
224 "in text mode. To exit immediately, press Dismiss.",
226 "In text mode, any key presses will display the character at",
227 "the location of the underscore and advance the underscore",
228 "cursor. Enter your text and once completed press Apply to",
229 "finish your image annotation. To correct errors press BACK",
230 "SPACE. To delete an entire line of text, press DELETE. Any",
231 "text that exceeds the boundaries of the image window is",
232 "automagically continued onto the next line.",
234 "The actual color you request for the font is saved in the",
235 "image. However, the color that appears in your image window",
236 "may be different. For example, on a monochrome screen the",
237 "text will appear black or white even if you choose the color",
238 "red as the font color. However, the image saved to a file",
239 "with -write is written with red lettering. To assure the",
240 "correct color text in the final image, any PseudoClass image",
241 "is promoted to DirectClass (see miff(5)). To force a",
242 "PseudoClass image to remain PseudoClass, use -colors.",
247 "In chop mode, the Command widget has these options:",
255 "If the you choose the horizontal direction (this the",
256 "default), the area of the image between the two horizontal",
257 "endpoints of the chop line is removed. Otherwise, the area",
258 "of the image between the two vertical endpoints of the chop",
261 "Select a location within the image window to begin your chop,",
262 "press and hold any button. Next, move the pointer to",
263 "another location in the image. As you move a line will",
264 "connect the initial location and the pointer. When you",
265 "release the button, the area within the image to chop is",
266 "determined by which direction you choose from the Command",
269 "To cancel the image chopping, move the pointer back to the",
270 "starting point of the line and release the button.",
273 *ImageColorEditHelp[] =
275 "In color edit mode, the Command widget has these options:",
316 "Choose a color editing method from the Method sub-menu",
317 "of the Command widget. The point method recolors any pixel",
318 "selected with the pointer until the button is released. The",
319 "replace method recolors any pixel that matches the color of",
320 "the pixel you select with a button press. Floodfill recolors",
321 "any pixel that matches the color of the pixel you select with",
322 "a button press and is a neighbor. Whereas filltoborder recolors",
323 "any neighbor pixel that is not the border color. Finally reset",
324 "changes the entire image to the designated color.",
326 "Next, choose a pixel color from the Pixel Color sub-menu.",
327 "Additional pixel colors can be specified with the color",
328 "browser. You can change the menu colors by setting the X",
329 "resources pen1 through pen9.",
331 "Now press button 1 to select a pixel within the image window",
332 "to change its color. Additional pixels may be recolored as",
333 "prescribed by the method you choose.",
335 "If the Magnify widget is mapped, it can be helpful in positioning",
336 "your pointer within the image (refer to button 2).",
338 "The actual color you request for the pixels is saved in the",
339 "image. However, the color that appears in your image window",
340 "may be different. For example, on a monochrome screen the",
341 "pixel will appear black or white even if you choose the",
342 "color red as the pixel color. However, the image saved to a",
343 "file with -write is written with red pixels. To assure the",
344 "correct color text in the final image, any PseudoClass image",
345 "is promoted to DirectClass (see miff(5)). To force a",
346 "PseudoClass image to remain PseudoClass, use -colors.",
349 *ImageCompositeHelp[] =
351 "First a widget window is displayed requesting you to enter an",
352 "image name. Press Composite, Grab or type a file name.",
353 "Press Cancel if you choose not to create a composite image.",
354 "When you choose Grab, move the pointer to the desired window",
355 "and press any button.",
357 "If the Composite image does not have any matte information,",
358 "you are informed and the file browser is displayed again.",
359 "Enter the name of a mask image. The image is typically",
360 "grayscale and the same size as the composite image. If the",
361 "image is not grayscale, it is converted to grayscale and the",
362 "resulting intensities are used as matte information.",
364 "A small window appears showing the location of the cursor in",
365 "the image window. You are now in composite mode. To exit",
366 "immediately, press Dismiss. In composite mode, the Command",
367 "widget has these options:",
393 "Choose a composite operation from the Operators sub-menu of",
394 "the Command widget. How each operator behaves is described",
395 "below. Image window is the image currently displayed on",
396 "your X server and image is the image obtained with the File",
399 "Over The result is the union of the two image shapes,",
400 " with image obscuring image window in the region of",
403 "In The result is simply image cut by the shape of",
404 " image window. None of the image data of image",
405 " window is in the result.",
407 "Out The resulting image is image with the shape of",
408 " image window cut out.",
410 "Atop The result is the same shape as image image window,",
411 " with image obscuring image window where the image",
412 " shapes overlap. Note this differs from over",
413 " because the portion of image outside image window's",
414 " shape does not appear in the result.",
416 "Xor The result is the image data from both image and",
417 " image window that is outside the overlap region.",
418 " The overlap region is blank.",
420 "Plus The result is just the sum of the image data.",
421 " Output values are cropped to QuantumRange (no overflow).",
423 "Minus The result of image - image window, with underflow",
426 "Add The result of image + image window, with overflow",
427 " wrapping around (mod 256).",
429 "Subtract The result of image - image window, with underflow",
430 " wrapping around (mod 256). The add and subtract",
431 " operators can be used to perform reversible",
435 " The result of abs(image - image window). This",
436 " useful for comparing two very similar images.",
439 " The result of image * image window. This",
440 " useful for the creation of drop-shadows.",
442 "Bumpmap The result of surface normals from image * image",
445 "Copy The resulting image is image window replaced with",
446 " image. Here the matte information is ignored.",
448 "CopyRed The red layer of the image window is replace with",
449 " the red layer of the image. The other layers are",
453 " The green layer of the image window is replace with",
454 " the green layer of the image. The other layers are",
457 "CopyBlue The blue layer of the image window is replace with",
458 " the blue layer of the image. The other layers are",
462 " The matte layer of the image window is replace with",
463 " the matte layer of the image. The other layers are",
466 "The image compositor requires a matte, or alpha channel in",
467 "the image for some operations. This extra channel usually",
468 "defines a mask which represents a sort of a cookie-cutter",
469 "for the image. This the case when matte is opaque (full",
470 "coverage) for pixels inside the shape, zero outside, and",
471 "between 0 and QuantumRange on the boundary. If image does not",
472 "have a matte channel, it is initialized with 0 for any pixel",
473 "matching in color to pixel location (0,0), otherwise QuantumRange.",
475 "If you choose Dissolve, the composite operator becomes Over. The",
476 "image matte channel percent transparency is initialized to factor.",
477 "The image window is initialized to (100-factor). Where factor is the",
478 "value you specify in the Dialog widget.",
480 "Displace shifts the image pixels as defined by a displacement",
481 "map. With this option, image is used as a displacement map.",
482 "Black, within the displacement map, is a maximum positive",
483 "displacement. White is a maximum negative displacement and",
484 "middle gray is neutral. The displacement is scaled to determine",
485 "the pixel shift. By default, the displacement applies in both the",
486 "horizontal and vertical directions. However, if you specify a mask,",
487 "image is the horizontal X displacement and mask the vertical Y",
490 "Note that matte information for image window is not retained",
491 "for colormapped X server visuals (e.g. StaticColor,",
492 "StaticColor, GrayScale, PseudoColor). Correct compositing",
493 "behavior may require a TrueColor or DirectColor visual or a",
494 "Standard Colormap.",
496 "Choosing a composite operator is optional. The default",
497 "operator is replace. However, you must choose a location to",
498 "composite your image and press button 1. Press and hold the",
499 "button before releasing and an outline of the image will",
500 "appear to help you identify your location.",
502 "The actual colors of the composite image is saved. However,",
503 "the color that appears in image window may be different.",
504 "For example, on a monochrome screen image window will appear",
505 "black or white even though your composited image may have",
506 "many colors. If the image is saved to a file it is written",
507 "with the correct colors. To assure the correct colors are",
508 "saved in the final image, any PseudoClass image is promoted",
509 "to DirectClass (see miff(5)). To force a PseudoClass image",
510 "to remain PseudoClass, use -colors.",
515 "In cut mode, the Command widget has these options:",
520 "To define a cut region, press button 1 and drag. The",
521 "cut region is defined by a highlighted rectangle that",
522 "expands or contracts as it follows the pointer. Once you",
523 "are satisfied with the cut region, release the button.",
524 "You are now in rectify mode. In rectify mode, the Command",
525 "widget has these options:",
531 "You can make adjustments by moving the pointer to one of the",
532 "cut rectangle corners, pressing a button, and dragging.",
533 "Finally, press Cut to commit your copy region. To",
534 "exit without cutting the image, press Dismiss.",
539 "In copy mode, the Command widget has these options:",
544 "To define a copy region, press button 1 and drag. The",
545 "copy region is defined by a highlighted rectangle that",
546 "expands or contracts as it follows the pointer. Once you",
547 "are satisfied with the copy region, release the button.",
548 "You are now in rectify mode. In rectify mode, the Command",
549 "widget has these options:",
555 "You can make adjustments by moving the pointer to one of the",
556 "copy rectangle corners, pressing a button, and dragging.",
557 "Finally, press Copy to commit your copy region. To",
558 "exit without copying the image, press Dismiss.",
563 "In crop mode, the Command widget has these options:",
568 "To define a cropping region, press button 1 and drag. The",
569 "cropping region is defined by a highlighted rectangle that",
570 "expands or contracts as it follows the pointer. Once you",
571 "are satisfied with the cropping region, release the button.",
572 "You are now in rectify mode. In rectify mode, the Command",
573 "widget has these options:",
579 "You can make adjustments by moving the pointer to one of the",
580 "cropping rectangle corners, pressing a button, and dragging.",
581 "Finally, press Crop to commit your cropping region. To",
582 "exit without cropping the image, press Dismiss.",
587 "The cursor changes to a crosshair to indicate you are in",
588 "draw mode. To exit immediately, press Dismiss. In draw mode,",
589 "the Command widget has these options:",
634 "Choose a drawing primitive from the Element sub-menu.",
636 "Choose a color from the Color sub-menu. Additional",
637 "colors can be specified with the color browser.",
639 "If you choose the color browser and press Grab, you can",
640 "select the color by moving the pointer to the desired",
641 "color on the screen and press any button. The transparent",
642 "color updates the image matte channel and is useful for",
643 "image compositing.",
645 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
646 "Additional stipples can be specified with the file browser.",
647 "Stipples obtained from the file browser must be on disk in the",
648 "X11 bitmap format.",
650 "Choose a width, if appropriate, from the Width sub-menu. To",
651 "choose a specific width select the Dialog widget.",
653 "Choose a point in the Image window and press button 1 and",
654 "hold. Next, move the pointer to another location in the",
655 "image. As you move, a line connects the initial location and",
656 "the pointer. When you release the button, the image is",
657 "updated with the primitive you just drew. For polygons, the",
658 "image is updated when you press and release the button without",
659 "moving the pointer.",
661 "To cancel image drawing, move the pointer back to the",
662 "starting point of the line and release the button.",
668 " The effects of each button press is described below. Three",
669 " buttons are required. If you have a two button mouse,",
670 " button 1 and 3 are returned. Press ALT and button 3 to",
671 " simulate button 2.",
673 " 1 Press this button to map or unmap the Command widget.",
675 " 2 Press and drag to define a region of the image to",
678 " 3 Press and drag to choose from a select set of commands.",
679 " This button behaves differently if the image being",
680 " displayed is a visual image directory. Here, choose a",
681 " particular tile of the directory and press this button and",
682 " drag to select a command from a pop-up menu. Choose from",
683 " these menu items:",
691 " If you choose Open, the image represented by the tile is",
692 " displayed. To return to the visual image directory, choose",
693 " Next from the Command widget. Next and Former moves to the",
694 " next or former image respectively. Choose Delete to delete",
695 " a particular image tile. Finally, choose Update to",
696 " synchronize all the image tiles with their respective",
700 " The Command widget lists a number of sub-menus and commands.",
712 " Visual Directory...",
746 " Contrast Stretch...",
747 " Sigmoidal Contrast...",
775 " Charcoal Drawing...",
786 " Region of Interest...",
798 " Browse Documentation",
801 " Menu items with a indented triangle have a sub-menu. They",
802 " are represented above as the indented items. To access a",
803 " sub-menu item, move the pointer to the appropriate menu and",
804 " press a button and drag. When you find the desired sub-menu",
805 " item, release the button and the command is executed. Move",
806 " the pointer away from the sub-menu if you decide not to",
807 " execute a particular command.",
809 "KEYBOARD ACCELERATORS",
810 " Accelerators are one or two key presses that effect a",
811 " particular command. The keyboard accelerators that",
812 " display(1) understands is:",
814 " Ctl+O Press to open an image from a file.",
816 " space Press to display the next image.",
818 " If the image is a multi-paged document such as a Postscript",
819 " document, you can skip ahead several pages by preceding",
820 " this command with a number. For example to display the",
821 " third page beyond the current page, press 3<space>.",
823 " backspace Press to display the former image.",
825 " If the image is a multi-paged document such as a Postscript",
826 " document, you can skip behind several pages by preceding",
827 " this command with a number. For example to display the",
828 " third page preceding the current page, press 3<backspace>.",
830 " Ctl+S Press to write the image to a file.",
832 " Ctl+P Press to print the image to a Postscript printer.",
834 " Ctl+D Press to delete an image file.",
836 " Ctl+N Press to create a blank canvas.",
838 " Ctl+Q Press to discard all images and exit program.",
840 " Ctl+Z Press to undo last image transformation.",
842 " Ctl+R Press to redo last image transformation.",
844 " Ctl+X Press to cut a region of the image.",
846 " Ctl+C Press to copy a region of the image.",
848 " Ctl+V Press to paste a region to the image.",
850 " < Press to half the image size.",
852 " - Press to return to the original image size.",
854 " > Press to double the image size.",
856 " % Press to resize the image to a width and height you",
859 "Cmd-A Press to make any image transformations permanent."
861 " By default, any image size transformations are applied",
862 " to the original image to create the image displayed on",
863 " the X server. However, the transformations are not",
864 " permanent (i.e. the original image does not change",
865 " size only the X image does). For example, if you",
866 " press > the X image will appear to double in size,",
867 " but the original image will in fact remain the same size.",
868 " To force the original image to double in size, press >",
869 " followed by Cmd-A.",
871 " @ Press to refresh the image window.",
873 " C Press to cut out a rectangular region of the image.",
875 " [ Press to chop the image.",
877 " H Press to flop image in the horizontal direction.",
879 " V Press to flip image in the vertical direction.",
881 " / Press to rotate the image 90 degrees clockwise.",
883 " \\ Press to rotate the image 90 degrees counter-clockwise.",
885 " * Press to rotate the image the number of degrees you",
888 " S Press to shear the image the number of degrees you",
891 " R Press to roll the image.",
893 " T Press to trim the image edges.",
895 " Shft-H Press to vary the image hue.",
897 " Shft-S Press to vary the color saturation.",
899 " Shft-L Press to vary the color brightness.",
901 " Shft-G Press to gamma correct the image.",
903 " Shft-C Press to sharpen the image contrast.",
905 " Shft-Z Press to dull the image contrast.",
907 " = Press to perform histogram equalization on the image.",
909 " Shft-N Press to perform histogram normalization on the image.",
911 " Shft-~ Press to negate the colors of the image.",
913 " . Press to convert the image colors to gray.",
915 " Shft-# Press to set the maximum number of unique colors in the",
918 " F2 Press to reduce the speckles in an image.",
920 " F3 Press to eliminate peak noise from an image.",
922 " F4 Press to add noise to an image.",
924 " F5 Press to sharpen an image.",
926 " F6 Press to delete an image file.",
928 " F7 Press to threshold the image.",
930 " F8 Press to detect edges within an image.",
932 " F9 Press to emboss an image.",
934 " F10 Press to displace pixels by a random amount.",
936 " F11 Press to negate all pixels above the threshold level.",
938 " F12 Press to shade the image using a distant light source.",
940 " F13 Press to lighten or darken image edges to create a 3-D effect.",
942 " F14 Press to segment the image by color.",
944 " Meta-S Press to swirl image pixels about the center.",
946 " Meta-I Press to implode image pixels about the center.",
948 " Meta-W Press to alter an image along a sine wave.",
950 " Meta-P Press to simulate an oil painting.",
952 " Meta-C Press to simulate a charcoal drawing.",
954 " Alt-A Press to annotate the image with text.",
956 " Alt-D Press to draw on an image.",
958 " Alt-P Press to edit an image pixel color.",
960 " Alt-M Press to edit the image matte information.",
962 " Alt-V Press to composite the image with another.",
964 " Alt-B Press to add a border to the image.",
966 " Alt-F Press to add an ornamental border to the image.",
969 " Press to add an image comment.",
971 " Ctl-A Press to apply image processing techniques to a region",
974 " Shft-? Press to display information about the image.",
976 " Shft-+ Press to map the zoom image window.",
978 " Shft-P Press to preview an image enhancement, effect, or f/x.",
980 " F1 Press to display helpful information about display(1).",
982 " Find Press to browse documentation about ImageMagick.",
984 " 1-9 Press to change the level of magnification.",
986 " Use the arrow keys to move the image one pixel up, down,",
987 " left, or right within the magnify window. Be sure to first",
988 " map the magnify window by pressing button 2.",
990 " Press ALT and one of the arrow keys to trim off one pixel",
991 " from any side of the image.",
994 *ImageMatteEditHelp[] =
996 "Matte information within an image is useful for some",
997 "operations such as image compositing (See IMAGE",
998 "COMPOSITING). This extra channel usually defines a mask",
999 "which represents a sort of a cookie-cutter for the image.",
1000 "This the case when matte is opaque (full coverage) for",
1001 "pixels inside the shape, zero outside, and between 0 and",
1002 "QuantumRange on the boundary.",
1004 "A small window appears showing the location of the cursor in",
1005 "the image window. You are now in matte edit mode. To exit",
1006 "immediately, press Dismiss. In matte edit mode, the Command",
1007 "widget has these options:",
1041 "Choose a matte editing method from the Method sub-menu of",
1042 "the Command widget. The point method changes the matte value",
1043 "of any pixel selected with the pointer until the button is",
1044 "is released. The replace method changes the matte value of",
1045 "any pixel that matches the color of the pixel you select with",
1046 "a button press. Floodfill changes the matte value of any pixel",
1047 "that matches the color of the pixel you select with a button",
1048 "press and is a neighbor. Whereas filltoborder changes the matte",
1049 "value any neighbor pixel that is not the border color. Finally",
1050 "reset changes the entire image to the designated matte value.",
1052 "Choose Matte Value and pick Opaque or Transarent. For other values",
1053 "select the Dialog entry. Here a dialog appears requesting a matte",
1054 "value. The value you select is assigned as the opacity value of the",
1055 "selected pixel or pixels.",
1057 "Now, press any button to select a pixel within the image",
1058 "window to change its matte value.",
1060 "If the Magnify widget is mapped, it can be helpful in positioning",
1061 "your pointer within the image (refer to button 2).",
1063 "Matte information is only valid in a DirectClass image.",
1064 "Therefore, any PseudoClass image is promoted to DirectClass",
1065 "(see miff(5)). Note that matte information for PseudoClass",
1066 "is not retained for colormapped X server visuals (e.g.",
1067 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1068 "immediately save your image to a file (refer to Write).",
1069 "Correct matte editing behavior may require a TrueColor or",
1070 "DirectColor visual or a Standard Colormap.",
1075 "When an image exceeds the width or height of the X server",
1076 "screen, display maps a small panning icon. The rectangle",
1077 "within the panning icon shows the area that is currently",
1078 "displayed in the image window. To pan about the image,",
1079 "press any button and drag the pointer within the panning",
1080 "icon. The pan rectangle moves with the pointer and the",
1081 "image window is updated to reflect the location of the",
1082 "rectangle within the panning icon. When you have selected",
1083 "the area of the image you wish to view, release the button.",
1085 "Use the arrow keys to pan the image one pixel up, down,",
1086 "left, or right within the image window.",
1088 "The panning icon is withdrawn if the image becomes smaller",
1089 "than the dimensions of the X server screen.",
1094 "A small window appears showing the location of the cursor in",
1095 "the image window. You are now in paste mode. To exit",
1096 "immediately, press Dismiss. In paste mode, the Command",
1097 "widget has these options:",
1114 "Choose a composite operation from the Operators sub-menu of",
1115 "the Command widget. How each operator behaves is described",
1116 "below. Image window is the image currently displayed on",
1117 "your X server and image is the image obtained with the File",
1120 "Over The result is the union of the two image shapes,",
1121 " with image obscuring image window in the region of",
1124 "In The result is simply image cut by the shape of",
1125 " image window. None of the image data of image",
1126 " window is in the result.",
1128 "Out The resulting image is image with the shape of",
1129 " image window cut out.",
1131 "Atop The result is the same shape as image image window,",
1132 " with image obscuring image window where the image",
1133 " shapes overlap. Note this differs from over",
1134 " because the portion of image outside image window's",
1135 " shape does not appear in the result.",
1137 "Xor The result is the image data from both image and",
1138 " image window that is outside the overlap region.",
1139 " The overlap region is blank.",
1141 "Plus The result is just the sum of the image data.",
1142 " Output values are cropped to QuantumRange (no overflow).",
1143 " This operation is independent of the matte",
1146 "Minus The result of image - image window, with underflow",
1147 " cropped to zero.",
1149 "Add The result of image + image window, with overflow",
1150 " wrapping around (mod 256).",
1152 "Subtract The result of image - image window, with underflow",
1153 " wrapping around (mod 256). The add and subtract",
1154 " operators can be used to perform reversible",
1155 " transformations.",
1158 " The result of abs(image - image window). This",
1159 " useful for comparing two very similar images.",
1161 "Copy The resulting image is image window replaced with",
1162 " image. Here the matte information is ignored.",
1164 "CopyRed The red layer of the image window is replace with",
1165 " the red layer of the image. The other layers are",
1169 " The green layer of the image window is replace with",
1170 " the green layer of the image. The other layers are",
1173 "CopyBlue The blue layer of the image window is replace with",
1174 " the blue layer of the image. The other layers are",
1178 " The matte layer of the image window is replace with",
1179 " the matte layer of the image. The other layers are",
1182 "The image compositor requires a matte, or alpha channel in",
1183 "the image for some operations. This extra channel usually",
1184 "defines a mask which represents a sort of a cookie-cutter",
1185 "for the image. This the case when matte is opaque (full",
1186 "coverage) for pixels inside the shape, zero outside, and",
1187 "between 0 and QuantumRange on the boundary. If image does not",
1188 "have a matte channel, it is initialized with 0 for any pixel",
1189 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1191 "Note that matte information for image window is not retained",
1192 "for colormapped X server visuals (e.g. StaticColor,",
1193 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1194 "behavior may require a TrueColor or DirectColor visual or a",
1195 "Standard Colormap.",
1197 "Choosing a composite operator is optional. The default",
1198 "operator is replace. However, you must choose a location to",
1199 "paste your image and press button 1. Press and hold the",
1200 "button before releasing and an outline of the image will",
1201 "appear to help you identify your location.",
1203 "The actual colors of the pasted image is saved. However,",
1204 "the color that appears in image window may be different.",
1205 "For example, on a monochrome screen image window will appear",
1206 "black or white even though your pasted image may have",
1207 "many colors. If the image is saved to a file it is written",
1208 "with the correct colors. To assure the correct colors are",
1209 "saved in the final image, any PseudoClass image is promoted",
1210 "to DirectClass (see miff(5)). To force a PseudoClass image",
1211 "to remain PseudoClass, use -colors.",
1216 "In region of interest mode, the Command widget has these",
1222 "To define a region of interest, press button 1 and drag.",
1223 "The region of interest is defined by a highlighted rectangle",
1224 "that expands or contracts as it follows the pointer. Once",
1225 "you are satisfied with the region of interest, release the",
1226 "button. You are now in apply mode. In apply mode the",
1227 "Command widget has these options:",
1247 " Contrast Stretch",
1248 " Sigmoidal Contrast...",
1275 " Charcoal Drawing...",
1285 "You can make adjustments to the region of interest by moving",
1286 "the pointer to one of the rectangle corners, pressing a",
1287 "button, and dragging. Finally, choose an image processing",
1288 "technique from the Command widget. You can choose more than",
1289 "one image processing technique to apply to an area.",
1290 "Alternatively, you can move the region of interest before",
1291 "applying another image processing technique. To exit, press",
1295 *ImageRotateHelp[] =
1297 "In rotate mode, the Command widget has these options:",
1316 "Choose a background color from the Pixel Color sub-menu.",
1317 "Additional background colors can be specified with the color",
1318 "browser. You can change the menu colors by setting the X",
1319 "resources pen1 through pen9.",
1321 "If you choose the color browser and press Grab, you can",
1322 "select the background color by moving the pointer to the",
1323 "desired color on the screen and press any button.",
1325 "Choose a point in the image window and press this button and",
1326 "hold. Next, move the pointer to another location in the",
1327 "image. As you move a line connects the initial location and",
1328 "the pointer. When you release the button, the degree of",
1329 "image rotation is determined by the slope of the line you",
1330 "just drew. The slope is relative to the direction you",
1331 "choose from the Direction sub-menu of the Command widget.",
1333 "To cancel the image rotation, move the pointer back to the",
1334 "starting point of the line and release the button.",
1339 Enumeration declarations.
1358 VisualDirectoryCommand,
1366 OriginalSizeCommand,
1388 ContrastStretchCommand,
1389 SigmoidalContrastCommand,
1415 CharcoalDrawCommand,
1425 RegionofInterestCommand,
1431 ShowHistogramCommand,
1437 BrowseDocumentationCommand,
1439 SaveToUndoBufferCommand,
1446 AnnotateNameCommand,
1447 AnnotateFontColorCommand,
1448 AnnotateBackgroundColorCommand,
1449 AnnotateRotateCommand,
1450 AnnotateHelpCommand,
1451 AnnotateDismissCommand,
1454 ChopDirectionCommand,
1457 HorizontalChopCommand,
1458 VerticalChopCommand,
1459 ColorEditMethodCommand,
1460 ColorEditColorCommand,
1461 ColorEditBorderCommand,
1462 ColorEditFuzzCommand,
1463 ColorEditUndoCommand,
1464 ColorEditHelpCommand,
1465 ColorEditDismissCommand,
1466 CompositeOperatorsCommand,
1467 CompositeDissolveCommand,
1468 CompositeDisplaceCommand,
1469 CompositeHelpCommand,
1470 CompositeDismissCommand,
1475 RectifyDismissCommand,
1484 MatteEditBorderCommand,
1485 MatteEditFuzzCommand,
1486 MatteEditValueCommand,
1487 MatteEditUndoCommand,
1488 MatteEditHelpCommand,
1489 MatteEditDismissCommand,
1490 PasteOperatorsCommand,
1492 PasteDismissCommand,
1494 RotateDirectionCommand,
1496 RotateSharpenCommand,
1498 RotateDismissCommand,
1499 HorizontalRotateCommand,
1500 VerticalRotateCommand,
1511 #define BricksWidth 20
1512 #define BricksHeight 20
1513 #define DiagonalWidth 16
1514 #define DiagonalHeight 16
1515 #define HighlightWidth 8
1516 #define HighlightHeight 8
1517 #define OpaqueWidth 8
1518 #define OpaqueHeight 8
1519 #define ScalesWidth 16
1520 #define ScalesHeight 16
1521 #define ShadowWidth 8
1522 #define ShadowHeight 8
1523 #define VerticalWidth 16
1524 #define VerticalHeight 16
1525 #define WavyWidth 16
1526 #define WavyHeight 16
1529 Constant declaration.
1534 static const unsigned char
1537 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1538 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1539 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1540 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1541 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1545 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1546 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1547 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1551 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1552 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1553 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1557 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1558 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1559 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1563 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1564 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1565 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1569 Function prototypes.
1572 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1573 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1576 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1577 Image **,ExceptionInfo *),
1578 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1579 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1581 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1584 static MagickBooleanType
1585 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1587 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1589 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1591 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1593 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1595 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1597 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1598 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1600 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1602 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1603 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1604 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1606 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1607 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1608 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1611 XDrawPanRectangle(Display *,XWindows *),
1612 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1614 XMagnifyImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1615 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1616 XPanImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1617 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1618 const KeySym,ExceptionInfo *),
1619 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1620 XScreenEvent(Display *,XWindows *,XEvent *,ExceptionInfo *),
1621 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628 % D i s p l a y I m a g e s %
1632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634 % DisplayImages() displays an image sequence to any X window screen. It
1635 % returns a value other than 0 if successful. Check the exception member
1636 % of image to determine the reason for any failure.
1638 % The format of the DisplayImages method is:
1640 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1641 % Image *images,ExceptionInfo *exception)
1643 % A description of each parameter follows:
1645 % o image_info: the image info.
1647 % o image: the image.
1649 % o exception: return any errors or warnings in this structure.
1652 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1653 Image *images,ExceptionInfo *exception)
1676 assert(image_info != (const ImageInfo *) NULL);
1677 assert(image_info->signature == MagickSignature);
1678 assert(images != (Image *) NULL);
1679 assert(images->signature == MagickSignature);
1680 if (IfMagickTrue(images->debug) )
1681 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1682 display=XOpenDisplay(image_info->server_name);
1683 if (display == (Display *) NULL)
1685 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1686 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1687 return(MagickFalse);
1689 if (exception->severity != UndefinedException)
1690 CatchException(exception);
1691 (void) XSetErrorHandler(XError);
1692 resource_database=XGetResourceDatabase(display,GetClientName());
1693 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1694 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1695 if (image_info->page != (char *) NULL)
1696 resource_info.image_geometry=AcquireString(image_info->page);
1697 resource_info.immutable=MagickTrue;
1698 argv[0]=AcquireString(GetClientName());
1700 for (i=0; (state & ExitState) == 0; i++)
1702 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1704 image=GetImageFromList(images,i % GetImageListLength(images));
1705 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1707 (void) SetErrorHandler((ErrorHandler) NULL);
1708 (void) SetWarningHandler((WarningHandler) NULL);
1709 argv[0]=DestroyString(argv[0]);
1710 (void) XCloseDisplay(display);
1711 XDestroyResourceInfo(&resource_info);
1712 if (exception->severity != UndefinedException)
1713 return(MagickFalse);
1718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1722 % R e m o t e D i s p l a y C o m m a n d %
1726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1728 % RemoteDisplayCommand() encourages a remote display program to display the
1729 % specified image filename.
1731 % The format of the RemoteDisplayCommand method is:
1733 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1734 % const char *window,const char *filename,ExceptionInfo *exception)
1736 % A description of each parameter follows:
1738 % o image_info: the image info.
1740 % o window: Specifies the name or id of an X window.
1742 % o filename: the name of the image filename to display.
1744 % o exception: return any errors or warnings in this structure.
1747 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1748 const char *window,const char *filename,ExceptionInfo *exception)
1756 assert(image_info != (const ImageInfo *) NULL);
1757 assert(image_info->signature == MagickSignature);
1758 assert(filename != (char *) NULL);
1759 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1760 display=XOpenDisplay(image_info->server_name);
1761 if (display == (Display *) NULL)
1763 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1764 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1765 return(MagickFalse);
1767 (void) XSetErrorHandler(XError);
1768 status=XRemoteCommand(display,window,filename);
1769 (void) XCloseDisplay(display);
1770 return(IsMagickTrue(status));
1774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1778 + X A n n o t a t e E d i t I m a g e %
1782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1784 % XAnnotateEditImage() annotates the image with text.
1786 % The format of the XAnnotateEditImage method is:
1788 % MagickBooleanType XAnnotateEditImage(Display *display,
1789 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1790 % ExceptionInfo *exception)
1792 % A description of each parameter follows:
1794 % o display: Specifies a connection to an X server; returned from
1797 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1799 % o windows: Specifies a pointer to a XWindows structure.
1801 % o image: the image; returned from ReadImage.
1805 static MagickBooleanType XAnnotateEditImage(Display *display,
1806 XResourceInfo *resource_info,XWindows *windows,Image *image,
1807 ExceptionInfo *exception)
1827 static const ModeType
1828 AnnotateCommands[] =
1830 AnnotateNameCommand,
1831 AnnotateFontColorCommand,
1832 AnnotateBackgroundColorCommand,
1833 AnnotateRotateCommand,
1834 AnnotateHelpCommand,
1835 AnnotateDismissCommand
1843 static MagickBooleanType
1844 transparent_box = MagickTrue,
1845 transparent_pen = MagickFalse;
1851 box_id = MaxNumberPens-2,
1856 command[MagickPathExtent],
1857 text[MagickPathExtent];
1860 *ColorMenu[MaxNumberPens+1];
1908 (void) CloneString(&windows->command.name,"Annotate");
1909 windows->command.data=4;
1910 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1911 (void) XMapRaised(display,windows->command.id);
1912 XClientMessage(display,windows->image.id,windows->im_protocols,
1913 windows->im_update_widget,CurrentTime);
1915 Track pointer until button 1 is pressed.
1917 XQueryPosition(display,windows->image.id,&x,&y);
1918 (void) XSelectInput(display,windows->image.id,
1919 windows->image.attributes.event_mask | PointerMotionMask);
1920 cursor=XCreateFontCursor(display,XC_left_side);
1921 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1925 if (IfMagickTrue(windows->info.mapped) )
1928 Display pointer position.
1930 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
1931 x+windows->image.x,y+windows->image.y);
1932 XInfoWidget(display,windows,text);
1935 Wait for next event.
1937 XScreenEvent(display,windows,&event,exception);
1938 if (event.xany.window == windows->command.id)
1941 Select a command from the Command widget.
1943 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1944 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1947 switch (AnnotateCommands[id])
1949 case AnnotateNameCommand:
1952 *FontMenu[MaxNumberFonts];
1958 Initialize menu selections.
1960 for (i=0; i < MaxNumberFonts; i++)
1961 FontMenu[i]=resource_info->font_name[i];
1962 FontMenu[MaxNumberFonts-2]="Browser...";
1963 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1965 Select a font name from the pop-up menu.
1967 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1968 (const char **) FontMenu,command);
1969 if (font_number < 0)
1971 if (font_number == (MaxNumberFonts-2))
1974 font_name[MagickPathExtent] = "fixed";
1977 Select a font name from a browser.
1979 resource_info->font_name[font_number]=font_name;
1980 XFontBrowserWidget(display,windows,"Select",font_name);
1981 if (*font_name == '\0')
1985 Initialize font info.
1987 font_info=XLoadQueryFont(display,resource_info->font_name[
1989 if (font_info == (XFontStruct *) NULL)
1991 XNoticeWidget(display,windows,"Unable to load font:",
1992 resource_info->font_name[font_number]);
1995 font_id=(unsigned int) font_number;
1996 (void) XFreeFont(display,font_info);
1999 case AnnotateFontColorCommand:
2002 Initialize menu selections.
2004 for (i=0; i < (int) (MaxNumberPens-2); i++)
2005 ColorMenu[i]=resource_info->pen_colors[i];
2006 ColorMenu[MaxNumberPens-2]="transparent";
2007 ColorMenu[MaxNumberPens-1]="Browser...";
2008 ColorMenu[MaxNumberPens]=(const char *) NULL;
2010 Select a pen color from the pop-up menu.
2012 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2013 (const char **) ColorMenu,command);
2016 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2018 if (IfMagickTrue(transparent_pen) )
2020 if (pen_number == (MaxNumberPens-1))
2023 color_name[MagickPathExtent] = "gray";
2026 Select a pen color from a dialog.
2028 resource_info->pen_colors[pen_number]=color_name;
2029 XColorBrowserWidget(display,windows,"Select",color_name);
2030 if (*color_name == '\0')
2036 (void) XParseColor(display,windows->map_info->colormap,
2037 resource_info->pen_colors[pen_number],&color);
2038 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2039 (unsigned int) MaxColors,&color);
2040 windows->pixel_info->pen_colors[pen_number]=color;
2041 pen_id=(unsigned int) pen_number;
2044 case AnnotateBackgroundColorCommand:
2047 Initialize menu selections.
2049 for (i=0; i < (int) (MaxNumberPens-2); i++)
2050 ColorMenu[i]=resource_info->pen_colors[i];
2051 ColorMenu[MaxNumberPens-2]="transparent";
2052 ColorMenu[MaxNumberPens-1]="Browser...";
2053 ColorMenu[MaxNumberPens]=(const char *) NULL;
2055 Select a pen color from the pop-up menu.
2057 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2058 (const char **) ColorMenu,command);
2061 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2063 if (IfMagickTrue(transparent_box) )
2065 if (pen_number == (MaxNumberPens-1))
2068 color_name[MagickPathExtent] = "gray";
2071 Select a pen color from a dialog.
2073 resource_info->pen_colors[pen_number]=color_name;
2074 XColorBrowserWidget(display,windows,"Select",color_name);
2075 if (*color_name == '\0')
2081 (void) XParseColor(display,windows->map_info->colormap,
2082 resource_info->pen_colors[pen_number],&color);
2083 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2084 (unsigned int) MaxColors,&color);
2085 windows->pixel_info->pen_colors[pen_number]=color;
2086 box_id=(unsigned int) pen_number;
2089 case AnnotateRotateCommand:
2095 angle[MagickPathExtent] = "30.0";
2113 Select a command from the pop-up menu.
2115 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2121 degrees=StringToDouble(RotateMenu[entry],(char **) NULL);
2124 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2128 degrees=StringToDouble(angle,(char **) NULL);
2131 case AnnotateHelpCommand:
2133 XTextViewWidget(display,resource_info,windows,MagickFalse,
2134 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2137 case AnnotateDismissCommand:
2155 if (event.xbutton.button != Button1)
2157 if (event.xbutton.window != windows->image.id)
2160 Change to text entering mode.
2173 if (event.xkey.window != windows->image.id)
2176 Respond to a user key press.
2178 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2179 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2180 switch ((int) key_symbol)
2195 XTextViewWidget(display,resource_info,windows,MagickFalse,
2196 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2201 (void) XBell(display,0);
2210 Map and unmap Info widget as cursor crosses its boundaries.
2214 if (IfMagickTrue(windows->info.mapped) )
2216 if ((x < (int) (windows->info.x+windows->info.width)) &&
2217 (y < (int) (windows->info.y+windows->info.height)))
2218 (void) XWithdrawWindow(display,windows->info.id,
2219 windows->info.screen);
2222 if ((x > (int) (windows->info.x+windows->info.width)) ||
2223 (y > (int) (windows->info.y+windows->info.height)))
2224 (void) XMapWindow(display,windows->info.id);
2230 } while ((state & ExitState) == 0);
2231 (void) XSelectInput(display,windows->image.id,
2232 windows->image.attributes.event_mask);
2233 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2234 if ((state & EscapeState) != 0)
2237 Set font info and check boundary conditions.
2239 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2240 if (font_info == (XFontStruct *) NULL)
2242 XNoticeWidget(display,windows,"Unable to load font:",
2243 resource_info->font_name[font_id]);
2244 font_info=windows->font_info;
2246 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2247 x=(int) windows->image.width-font_info->max_bounds.width;
2248 if (y < (int) (font_info->ascent+font_info->descent))
2249 y=(int) font_info->ascent+font_info->descent;
2250 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2251 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2252 return(MagickFalse);
2254 Initialize annotate structure.
2256 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2257 if (annotate_info == (XAnnotateInfo *) NULL)
2258 return(MagickFalse);
2259 XGetAnnotateInfo(annotate_info);
2262 if (IfMagickFalse(transparent_box) && IfMagickFalse(transparent_pen))
2263 annotate_info->stencil=OpaqueStencil;
2265 if (IfMagickFalse(transparent_box) )
2266 annotate_info->stencil=BackgroundStencil;
2268 annotate_info->stencil=ForegroundStencil;
2269 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2270 annotate_info->degrees=degrees;
2271 annotate_info->font_info=font_info;
2272 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2273 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2274 sizeof(*annotate_info->text));
2275 if (annotate_info->text == (char *) NULL)
2276 return(MagickFalse);
2278 Create cursor and set graphic context.
2280 cursor=XCreateFontCursor(display,XC_pencil);
2281 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2282 annotate_context=windows->image.annotate_context;
2283 (void) XSetFont(display,annotate_context,font_info->fid);
2284 (void) XSetBackground(display,annotate_context,
2285 windows->pixel_info->pen_colors[box_id].pixel);
2286 (void) XSetForeground(display,annotate_context,
2287 windows->pixel_info->pen_colors[pen_id].pixel);
2289 Begin annotating the image with text.
2291 (void) CloneString(&windows->command.name,"Text");
2292 windows->command.data=0;
2293 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2295 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2296 text_event.xexpose.width=(int) font_info->max_bounds.width;
2297 text_event.xexpose.height=font_info->max_bounds.ascent+
2298 font_info->max_bounds.descent;
2299 p=annotate_info->text;
2303 Display text cursor.
2306 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2308 Wait for next event.
2310 XScreenEvent(display,windows,&event,exception);
2311 if (event.xany.window == windows->command.id)
2314 Select a command from the Command widget.
2316 (void) XSetBackground(display,annotate_context,
2317 windows->pixel_info->background_color.pixel);
2318 (void) XSetForeground(display,annotate_context,
2319 windows->pixel_info->foreground_color.pixel);
2320 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2321 (void) XSetBackground(display,annotate_context,
2322 windows->pixel_info->pen_colors[box_id].pixel);
2323 (void) XSetForeground(display,annotate_context,
2324 windows->pixel_info->pen_colors[pen_id].pixel);
2327 switch (TextCommands[id])
2329 case TextHelpCommand:
2331 XTextViewWidget(display,resource_info,windows,MagickFalse,
2332 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2333 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2336 case TextApplyCommand:
2339 Finished annotating.
2341 annotate_info->width=(unsigned int) XTextWidth(font_info,
2342 annotate_info->text,(int) strlen(annotate_info->text));
2343 XRefreshWindow(display,&windows->image,&text_event);
2355 text_event.xexpose.x=x;
2356 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2357 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2358 (unsigned int) text_event.xexpose.width,(unsigned int)
2359 text_event.xexpose.height,MagickFalse);
2360 XRefreshWindow(display,&windows->image,&text_event);
2365 if (event.xbutton.window != windows->image.id)
2367 if (event.xbutton.button == Button2)
2370 Request primary selection.
2372 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2373 windows->image.id,CurrentTime);
2380 if (event.xexpose.count == 0)
2386 Refresh Image window.
2388 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2389 text_info=annotate_info;
2390 while (text_info != (XAnnotateInfo *) NULL)
2392 if (annotate_info->stencil == ForegroundStencil)
2393 (void) XDrawString(display,windows->image.id,annotate_context,
2394 text_info->x,text_info->y,text_info->text,
2395 (int) strlen(text_info->text));
2397 (void) XDrawImageString(display,windows->image.id,
2398 annotate_context,text_info->x,text_info->y,text_info->text,
2399 (int) strlen(text_info->text));
2400 text_info=text_info->previous;
2402 (void) XDrawString(display,windows->image.id,annotate_context,
2412 if (event.xkey.window != windows->image.id)
2415 Respond to a user key press.
2417 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2418 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2419 *(command+length)='\0';
2420 if (((event.xkey.state & ControlMask) != 0) ||
2421 ((event.xkey.state & Mod1Mask) != 0))
2422 state|=ModifierState;
2423 if ((state & ModifierState) != 0)
2424 switch ((int) key_symbol)
2429 key_symbol=DeleteCommand;
2435 switch ((int) key_symbol)
2440 Erase one character.
2442 if (p == annotate_info->text)
2444 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2449 Go to end of the previous line of text.
2451 annotate_info=annotate_info->previous;
2452 p=annotate_info->text;
2453 x=annotate_info->x+annotate_info->width;
2455 if (annotate_info->width != 0)
2456 p+=strlen(annotate_info->text);
2461 x-=XTextWidth(font_info,p,1);
2462 text_event.xexpose.x=x;
2463 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2464 XRefreshWindow(display,&windows->image,&text_event);
2467 case XK_bracketleft:
2469 key_symbol=XK_Escape;
2475 Erase the entire line of text.
2477 while (p != annotate_info->text)
2480 x-=XTextWidth(font_info,p,1);
2481 text_event.xexpose.x=x;
2482 XRefreshWindow(display,&windows->image,&text_event);
2490 Finished annotating.
2492 annotate_info->width=(unsigned int) XTextWidth(font_info,
2493 annotate_info->text,(int) strlen(annotate_info->text));
2494 XRefreshWindow(display,&windows->image,&text_event);
2501 Draw a single character on the Image window.
2503 if ((state & ModifierState) != 0)
2505 if (*command == '\0')
2508 if (annotate_info->stencil == ForegroundStencil)
2509 (void) XDrawString(display,windows->image.id,annotate_context,
2512 (void) XDrawImageString(display,windows->image.id,
2513 annotate_context,x,y,p,1);
2514 x+=XTextWidth(font_info,p,1);
2516 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2523 Advance to the next line of text.
2526 annotate_info->width=(unsigned int) XTextWidth(font_info,
2527 annotate_info->text,(int) strlen(annotate_info->text));
2528 if (annotate_info->next != (XAnnotateInfo *) NULL)
2531 Line of text already exists.
2533 annotate_info=annotate_info->next;
2536 p=annotate_info->text;
2539 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2540 sizeof(*annotate_info->next));
2541 if (annotate_info->next == (XAnnotateInfo *) NULL)
2542 return(MagickFalse);
2543 *annotate_info->next=(*annotate_info);
2544 annotate_info->next->previous=annotate_info;
2545 annotate_info=annotate_info->next;
2546 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2547 windows->image.width/MagickMax((ssize_t)
2548 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2549 if (annotate_info->text == (char *) NULL)
2550 return(MagickFalse);
2551 annotate_info->y+=annotate_info->height;
2552 if (annotate_info->y > (int) windows->image.height)
2553 annotate_info->y=(int) annotate_info->height;
2554 annotate_info->next=(XAnnotateInfo *) NULL;
2557 p=annotate_info->text;
2566 Respond to a user key release.
2568 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2569 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2570 state&=(~ModifierState);
2573 case SelectionNotify:
2589 Obtain response from primary selection.
2591 if (event.xselection.property == (Atom) None)
2593 status=XGetWindowProperty(display,event.xselection.requestor,
2594 event.xselection.property,0L,(long) MagickPathExtent,True,XA_STRING,
2595 &type,&format,&length,&after,&data);
2596 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2600 Annotate Image window with primary selection.
2602 for (i=0; i < (ssize_t) length; i++)
2604 if ((char) data[i] != '\n')
2607 Draw a single character on the Image window.
2610 (void) XDrawString(display,windows->image.id,annotate_context,
2612 x+=XTextWidth(font_info,p,1);
2614 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2618 Advance to the next line of text.
2621 annotate_info->width=(unsigned int) XTextWidth(font_info,
2622 annotate_info->text,(int) strlen(annotate_info->text));
2623 if (annotate_info->next != (XAnnotateInfo *) NULL)
2626 Line of text already exists.
2628 annotate_info=annotate_info->next;
2631 p=annotate_info->text;
2634 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2635 sizeof(*annotate_info->next));
2636 if (annotate_info->next == (XAnnotateInfo *) NULL)
2637 return(MagickFalse);
2638 *annotate_info->next=(*annotate_info);
2639 annotate_info->next->previous=annotate_info;
2640 annotate_info=annotate_info->next;
2641 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2642 windows->image.width/MagickMax((ssize_t)
2643 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2644 if (annotate_info->text == (char *) NULL)
2645 return(MagickFalse);
2646 annotate_info->y+=annotate_info->height;
2647 if (annotate_info->y > (int) windows->image.height)
2648 annotate_info->y=(int) annotate_info->height;
2649 annotate_info->next=(XAnnotateInfo *) NULL;
2652 p=annotate_info->text;
2654 (void) XFree((void *) data);
2660 } while ((state & ExitState) == 0);
2661 (void) XFreeCursor(display,cursor);
2663 Annotation is relative to image configuration.
2665 width=(unsigned int) image->columns;
2666 height=(unsigned int) image->rows;
2669 if (windows->image.crop_geometry != (char *) NULL)
2670 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2672 Initialize annotated image.
2674 XSetCursorState(display,windows,MagickTrue);
2675 XCheckRefreshWindows(display,windows);
2676 while (annotate_info != (XAnnotateInfo *) NULL)
2678 if (annotate_info->width == 0)
2681 No text on this line-- go to the next line of text.
2683 previous_info=annotate_info->previous;
2684 annotate_info->text=(char *)
2685 RelinquishMagickMemory(annotate_info->text);
2686 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2687 annotate_info=previous_info;
2691 Determine pixel index for box and pen color.
2693 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2694 if (windows->pixel_info->colors != 0)
2695 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2696 if (windows->pixel_info->pixels[i] ==
2697 windows->pixel_info->pen_colors[box_id].pixel)
2699 windows->pixel_info->box_index=(unsigned short) i;
2702 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2703 if (windows->pixel_info->colors != 0)
2704 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2705 if (windows->pixel_info->pixels[i] ==
2706 windows->pixel_info->pen_colors[pen_id].pixel)
2708 windows->pixel_info->pen_index=(unsigned short) i;
2712 Define the annotate geometry string.
2714 annotate_info->x=(int)
2715 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2716 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2717 windows->image.y)/windows->image.ximage->height;
2718 (void) FormatLocaleString(annotate_info->geometry,MagickPathExtent,
2719 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2720 height*annotate_info->height/windows->image.ximage->height,
2721 annotate_info->x+x,annotate_info->y+y);
2723 Annotate image with text.
2725 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image,
2728 return(MagickFalse);
2732 previous_info=annotate_info->previous;
2733 annotate_info->text=DestroyString(annotate_info->text);
2734 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2735 annotate_info=previous_info;
2737 (void) XSetForeground(display,annotate_context,
2738 windows->pixel_info->foreground_color.pixel);
2739 (void) XSetBackground(display,annotate_context,
2740 windows->pixel_info->background_color.pixel);
2741 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2742 XSetCursorState(display,windows,MagickFalse);
2743 (void) XFreeFont(display,font_info);
2745 Update image configuration.
2747 XConfigureImageColormap(display,resource_info,windows,image,exception);
2748 (void) XConfigureImage(display,resource_info,windows,image,exception);
2753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2757 + X B a c k g r o u n d I m a g e %
2761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2763 % XBackgroundImage() displays the image in the background of a window.
2765 % The format of the XBackgroundImage method is:
2767 % MagickBooleanType XBackgroundImage(Display *display,
2768 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2769 % ExceptionInfo *exception)
2771 % A description of each parameter follows:
2773 % o display: Specifies a connection to an X server; returned from
2776 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2778 % o windows: Specifies a pointer to a XWindows structure.
2780 % o image: the image.
2782 % o exception: return any errors or warnings in this structure.
2785 static MagickBooleanType XBackgroundImage(Display *display,
2786 XResourceInfo *resource_info,XWindows *windows,Image **image,
2787 ExceptionInfo *exception)
2789 #define BackgroundImageTag "Background/Image"
2795 window_id[MagickPathExtent] = "root";
2798 background_resources;
2801 Put image in background.
2803 status=XDialogWidget(display,windows,"Background",
2804 "Enter window id (id 0x00 selects window with pointer):",window_id);
2805 if (*window_id == '\0')
2806 return(MagickFalse);
2807 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2809 XInfoWidget(display,windows,BackgroundImageTag);
2810 XSetCursorState(display,windows,MagickTrue);
2811 XCheckRefreshWindows(display,windows);
2812 background_resources=(*resource_info);
2813 background_resources.window_id=window_id;
2814 background_resources.backdrop=IsMagickTrue(status);
2815 status=XDisplayBackgroundImage(display,&background_resources,*image,
2817 if (IfMagickTrue(status))
2818 XClientMessage(display,windows->image.id,windows->im_protocols,
2819 windows->im_retain_colors,CurrentTime);
2820 XSetCursorState(display,windows,MagickFalse);
2821 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2831 + X C h o p I m a g e %
2835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2837 % XChopImage() chops the X image.
2839 % The format of the XChopImage method is:
2841 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2842 % XWindows *windows,Image **image,ExceptionInfo *exception)
2844 % A description of each parameter follows:
2846 % o display: Specifies a connection to an X server; returned from
2849 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2851 % o windows: Specifies a pointer to a XWindows structure.
2853 % o image: the image.
2855 % o exception: return any errors or warnings in this structure.
2858 static MagickBooleanType XChopImage(Display *display,
2859 XResourceInfo *resource_info,XWindows *windows,Image **image,
2860 ExceptionInfo *exception)
2872 direction = HorizontalChopCommand;
2874 static const ModeType
2877 ChopDirectionCommand,
2881 DirectionCommands[] =
2883 HorizontalChopCommand,
2888 text[MagickPathExtent];
2921 (void) CloneString(&windows->command.name,"Chop");
2922 windows->command.data=1;
2923 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2924 (void) XMapRaised(display,windows->command.id);
2925 XClientMessage(display,windows->image.id,windows->im_protocols,
2926 windows->im_update_widget,CurrentTime);
2928 Track pointer until button 1 is pressed.
2930 XQueryPosition(display,windows->image.id,&x,&y);
2931 (void) XSelectInput(display,windows->image.id,
2932 windows->image.attributes.event_mask | PointerMotionMask);
2936 if (IfMagickTrue(windows->info.mapped) )
2939 Display pointer position.
2941 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
2942 x+windows->image.x,y+windows->image.y);
2943 XInfoWidget(display,windows,text);
2946 Wait for next event.
2948 XScreenEvent(display,windows,&event,exception);
2949 if (event.xany.window == windows->command.id)
2952 Select a command from the Command widget.
2954 id=XCommandWidget(display,windows,ChopMenu,&event);
2957 switch (ChopCommands[id])
2959 case ChopDirectionCommand:
2962 command[MagickPathExtent];
2973 Select a command from the pop-up menu.
2975 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2977 direction=DirectionCommands[id];
2980 case ChopHelpCommand:
2982 XTextViewWidget(display,resource_info,windows,MagickFalse,
2983 "Help Viewer - Image Chop",ImageChopHelp);
2986 case ChopDismissCommand:
3004 if (event.xbutton.button != Button1)
3006 if (event.xbutton.window != windows->image.id)
3009 User has committed to start point of chopping line.
3011 segment_info.x1=(short int) event.xbutton.x;
3012 segment_info.x2=(short int) event.xbutton.x;
3013 segment_info.y1=(short int) event.xbutton.y;
3014 segment_info.y2=(short int) event.xbutton.y;
3025 command[MagickPathExtent];
3030 if (event.xkey.window != windows->image.id)
3033 Respond to a user key press.
3035 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3036 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3037 switch ((int) key_symbol)
3052 (void) XSetFunction(display,windows->image.highlight_context,
3054 XTextViewWidget(display,resource_info,windows,MagickFalse,
3055 "Help Viewer - Image Chop",ImageChopHelp);
3056 (void) XSetFunction(display,windows->image.highlight_context,
3062 (void) XBell(display,0);
3071 Map and unmap Info widget as text cursor crosses its boundaries.
3075 if (IfMagickTrue(windows->info.mapped) )
3077 if ((x < (int) (windows->info.x+windows->info.width)) &&
3078 (y < (int) (windows->info.y+windows->info.height)))
3079 (void) XWithdrawWindow(display,windows->info.id,
3080 windows->info.screen);
3083 if ((x > (int) (windows->info.x+windows->info.width)) ||
3084 (y > (int) (windows->info.y+windows->info.height)))
3085 (void) XMapWindow(display,windows->info.id);
3088 } while ((state & ExitState) == 0);
3089 (void) XSelectInput(display,windows->image.id,
3090 windows->image.attributes.event_mask);
3091 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3092 if ((state & EscapeState) != 0)
3095 Draw line as pointer moves until the mouse button is released.
3102 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3109 Display info and draw chopping line.
3111 if (IfMagickFalse(windows->info.mapped) )
3112 (void) XMapWindow(display,windows->info.id);
3113 (void) FormatLocaleString(text,MagickPathExtent,
3114 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3115 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3116 XInfoWidget(display,windows,text);
3117 XHighlightLine(display,windows->image.id,
3118 windows->image.highlight_context,&segment_info);
3121 if (IfMagickTrue(windows->info.mapped) )
3122 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3124 Wait for next event.
3126 XScreenEvent(display,windows,&event,exception);
3128 XHighlightLine(display,windows->image.id,
3129 windows->image.highlight_context,&segment_info);
3134 segment_info.x2=(short int) event.xmotion.x;
3135 segment_info.y2=(short int) event.xmotion.y;
3141 User has committed to chopping line.
3143 segment_info.x2=(short int) event.xbutton.x;
3144 segment_info.y2=(short int) event.xbutton.y;
3152 segment_info.x2=(short int) event.xmotion.x;
3153 segment_info.y2=(short int) event.xmotion.y;
3159 Check boundary conditions.
3161 if (segment_info.x2 < 0)
3164 if (segment_info.x2 > windows->image.ximage->width)
3165 segment_info.x2=windows->image.ximage->width;
3166 if (segment_info.y2 < 0)
3169 if (segment_info.y2 > windows->image.ximage->height)
3170 segment_info.y2=windows->image.ximage->height;
3171 distance=(unsigned int)
3172 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3173 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3175 Compute chopping geometry.
3177 if (direction == HorizontalChopCommand)
3179 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3180 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3183 if (segment_info.x1 > (int) segment_info.x2)
3185 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3186 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3192 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3194 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3195 if (segment_info.y1 > segment_info.y2)
3197 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3198 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3201 } while ((state & ExitState) == 0);
3202 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3203 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3207 Image chopping is relative to image configuration.
3209 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3211 XSetCursorState(display,windows,MagickTrue);
3212 XCheckRefreshWindows(display,windows);
3213 windows->image.window_changes.width=windows->image.ximage->width-
3214 (unsigned int) chop_info.width;
3215 windows->image.window_changes.height=windows->image.ximage->height-
3216 (unsigned int) chop_info.height;
3217 width=(unsigned int) (*image)->columns;
3218 height=(unsigned int) (*image)->rows;
3221 if (windows->image.crop_geometry != (char *) NULL)
3222 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3223 scale_factor=(double) width/windows->image.ximage->width;
3225 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3226 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3227 scale_factor=(double) height/windows->image.ximage->height;
3229 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3230 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3234 chop_image=ChopImage(*image,&chop_info,exception);
3235 XSetCursorState(display,windows,MagickFalse);
3236 if (chop_image == (Image *) NULL)
3237 return(MagickFalse);
3238 *image=DestroyImage(*image);
3241 Update image configuration.
3243 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3244 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3253 + X C o l o r E d i t I m a g e %
3257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3259 % XColorEditImage() allows the user to interactively change the color of one
3260 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3262 % The format of the XColorEditImage method is:
3264 % MagickBooleanType XColorEditImage(Display *display,
3265 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3266 % ExceptionInfo *exception)
3268 % A description of each parameter follows:
3270 % o display: Specifies a connection to an X server; returned from
3273 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3275 % o windows: Specifies a pointer to a XWindows structure.
3277 % o image: the image; returned from ReadImage.
3279 % o exception: return any errors or warnings in this structure.
3282 static MagickBooleanType XColorEditImage(Display *display,
3283 XResourceInfo *resource_info,XWindows *windows,Image **image,
3284 ExceptionInfo *exception)
3299 static const ModeType
3300 ColorEditCommands[] =
3302 ColorEditMethodCommand,
3303 ColorEditColorCommand,
3304 ColorEditBorderCommand,
3305 ColorEditFuzzCommand,
3306 ColorEditUndoCommand,
3307 ColorEditHelpCommand,
3308 ColorEditDismissCommand
3312 method = PointMethod;
3318 border_color = { 0, 0, 0, 0, 0, 0 };
3321 command[MagickPathExtent],
3322 text[MagickPathExtent];
3357 (void) CloneString(&windows->command.name,"Color Edit");
3358 windows->command.data=4;
3359 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3360 (void) XMapRaised(display,windows->command.id);
3361 XClientMessage(display,windows->image.id,windows->im_protocols,
3362 windows->im_update_widget,CurrentTime);
3366 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3367 resource_info->background_color,resource_info->foreground_color);
3368 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3370 Track pointer until button 1 is pressed.
3372 XQueryPosition(display,windows->image.id,&x,&y);
3373 (void) XSelectInput(display,windows->image.id,
3374 windows->image.attributes.event_mask | PointerMotionMask);
3378 if (IfMagickTrue(windows->info.mapped) )
3381 Display pointer position.
3383 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
3384 x+windows->image.x,y+windows->image.y);
3385 XInfoWidget(display,windows,text);
3388 Wait for next event.
3390 XScreenEvent(display,windows,&event,exception);
3391 if (event.xany.window == windows->command.id)
3394 Select a command from the Command widget.
3396 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3399 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3402 switch (ColorEditCommands[id])
3404 case ColorEditMethodCommand:
3410 Select a method from the pop-up menu.
3412 methods=(char **) GetCommandOptions(MagickMethodOptions);
3413 if (methods == (char **) NULL)
3415 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3416 (const char **) methods,command);
3418 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3419 MagickFalse,methods[entry]);
3420 methods=DestroyStringList(methods);
3423 case ColorEditColorCommand:
3426 *ColorMenu[MaxNumberPens];
3432 Initialize menu selections.
3434 for (i=0; i < (int) (MaxNumberPens-2); i++)
3435 ColorMenu[i]=resource_info->pen_colors[i];
3436 ColorMenu[MaxNumberPens-2]="Browser...";
3437 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3439 Select a pen color from the pop-up menu.
3441 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3442 (const char **) ColorMenu,command);
3445 if (pen_number == (MaxNumberPens-2))
3448 color_name[MagickPathExtent] = "gray";
3451 Select a pen color from a dialog.
3453 resource_info->pen_colors[pen_number]=color_name;
3454 XColorBrowserWidget(display,windows,"Select",color_name);
3455 if (*color_name == '\0')
3461 (void) XParseColor(display,windows->map_info->colormap,
3462 resource_info->pen_colors[pen_number],&color);
3463 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3464 (unsigned int) MaxColors,&color);
3465 windows->pixel_info->pen_colors[pen_number]=color;
3466 pen_id=(unsigned int) pen_number;
3469 case ColorEditBorderCommand:
3472 *ColorMenu[MaxNumberPens];
3478 Initialize menu selections.
3480 for (i=0; i < (int) (MaxNumberPens-2); i++)
3481 ColorMenu[i]=resource_info->pen_colors[i];
3482 ColorMenu[MaxNumberPens-2]="Browser...";
3483 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3485 Select a pen color from the pop-up menu.
3487 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3488 (const char **) ColorMenu,command);
3491 if (pen_number == (MaxNumberPens-2))
3494 color_name[MagickPathExtent] = "gray";
3497 Select a pen color from a dialog.
3499 resource_info->pen_colors[pen_number]=color_name;
3500 XColorBrowserWidget(display,windows,"Select",color_name);
3501 if (*color_name == '\0')
3507 (void) XParseColor(display,windows->map_info->colormap,
3508 resource_info->pen_colors[pen_number],&border_color);
3511 case ColorEditFuzzCommand:
3514 fuzz[MagickPathExtent];
3529 Select a command from the pop-up menu.
3531 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3537 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
3541 (void) (void) CopyMagickString(fuzz,"20%",MagickPathExtent);
3542 (void) XDialogWidget(display,windows,"Ok",
3543 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3546 (void) ConcatenateMagickString(fuzz,"%",MagickPathExtent);
3547 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
3551 case ColorEditUndoCommand:
3553 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3557 case ColorEditHelpCommand:
3560 XTextViewWidget(display,resource_info,windows,MagickFalse,
3561 "Help Viewer - Image Annotation",ImageColorEditHelp);
3564 case ColorEditDismissCommand:
3574 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3581 if (event.xbutton.button != Button1)
3583 if ((event.xbutton.window != windows->image.id) &&
3584 (event.xbutton.window != windows->magnify.id))
3591 (void) XMagickCommand(display,resource_info,windows,
3592 SaveToUndoBufferCommand,image,exception);
3593 state|=UpdateConfigurationState;
3598 if (event.xbutton.button != Button1)
3600 if ((event.xbutton.window != windows->image.id) &&
3601 (event.xbutton.window != windows->magnify.id))
3604 Update colormap information.
3608 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3609 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3610 XInfoWidget(display,windows,text);
3611 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3612 state&=(~UpdateConfigurationState);
3622 if (event.xkey.window == windows->magnify.id)
3627 window=windows->magnify.id;
3628 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3630 if (event.xkey.window != windows->image.id)
3633 Respond to a user key press.
3635 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3636 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3637 switch ((int) key_symbol)
3651 XTextViewWidget(display,resource_info,windows,MagickFalse,
3652 "Help Viewer - Image Annotation",ImageColorEditHelp);
3657 (void) XBell(display,0);
3666 Map and unmap Info widget as cursor crosses its boundaries.
3670 if (IfMagickTrue(windows->info.mapped) )
3672 if ((x < (int) (windows->info.x+windows->info.width)) &&
3673 (y < (int) (windows->info.y+windows->info.height)))
3674 (void) XWithdrawWindow(display,windows->info.id,
3675 windows->info.screen);
3678 if ((x > (int) (windows->info.x+windows->info.width)) ||
3679 (y > (int) (windows->info.y+windows->info.height)))
3680 (void) XMapWindow(display,windows->info.id);
3686 if (event.xany.window == windows->magnify.id)
3688 x=windows->magnify.x-windows->image.x;
3689 y=windows->magnify.y-windows->image.y;
3693 if ((state & UpdateConfigurationState) != 0)
3703 Pixel edit is relative to image configuration.
3705 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3707 color=windows->pixel_info->pen_colors[pen_id];
3708 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3709 width=(unsigned int) (*image)->columns;
3710 height=(unsigned int) (*image)->rows;
3713 if (windows->image.crop_geometry != (char *) NULL)
3714 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3717 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3719 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3720 if ((x_offset < 0) || (y_offset < 0))
3722 if ((x_offset >= (int) (*image)->columns) ||
3723 (y_offset >= (int) (*image)->rows))
3725 image_view=AcquireAuthenticCacheView(*image,exception);
3732 Update color information using point algorithm.
3734 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
3735 return(MagickFalse);
3736 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3737 (ssize_t) y_offset,1,1,exception);
3738 if (q == (Quantum *) NULL)
3740 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3741 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3742 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3743 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3753 Update color information using replace algorithm.
3755 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
3756 x_offset,(ssize_t) y_offset,&target,exception);
3757 if ((*image)->storage_class == DirectClass)
3759 for (y=0; y < (int) (*image)->rows; y++)
3761 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3762 (*image)->columns,1,exception);
3763 if (q == (Quantum *) NULL)
3765 for (x=0; x < (int) (*image)->columns; x++)
3767 GetPixelInfoPixel(*image,q,&pixel);
3768 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3770 SetPixelRed(*image,ScaleShortToQuantum(
3772 SetPixelGreen(*image,ScaleShortToQuantum(
3774 SetPixelBlue(*image,ScaleShortToQuantum(
3777 q+=GetPixelChannels(*image);
3779 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
3785 for (i=0; i < (ssize_t) (*image)->colors; i++)
3786 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3788 (*image)->colormap[i].red=(double) ScaleShortToQuantum(
3790 (*image)->colormap[i].green=(double) ScaleShortToQuantum(
3792 (*image)->colormap[i].blue=(double) ScaleShortToQuantum(
3795 (void) SyncImage(*image,exception);
3799 case FloodfillMethod:
3800 case FillToBorderMethod:
3809 Update color information using floodfill algorithm.
3811 (void) GetOneVirtualPixelInfo(*image,
3812 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3813 y_offset,&target,exception);
3814 if (method == FillToBorderMethod)
3817 ScaleShortToQuantum(border_color.red);
3818 target.green=(double)
3819 ScaleShortToQuantum(border_color.green);
3820 target.blue=(double)
3821 ScaleShortToQuantum(border_color.blue);
3823 draw_info=CloneDrawInfo(resource_info->image_info,
3825 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3826 AllCompliance,&draw_info->fill,exception);
3827 (void) FloodfillPaintImage(*image,draw_info,&target,
3828 (ssize_t)x_offset,(ssize_t)y_offset,
3829 IsMagickFalse(method == FloodfillMethod),exception);
3830 draw_info=DestroyDrawInfo(draw_info);
3836 Update color information using reset algorithm.
3838 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
3839 return(MagickFalse);
3840 for (y=0; y < (int) (*image)->rows; y++)
3842 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3843 (*image)->columns,1,exception);
3844 if (q == (Quantum *) NULL)
3846 for (x=0; x < (int) (*image)->columns; x++)
3848 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3849 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3850 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3851 q+=GetPixelChannels(*image);
3853 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
3859 image_view=DestroyCacheView(image_view);
3860 state&=(~UpdateConfigurationState);
3862 } while ((state & ExitState) == 0);
3863 (void) XSelectInput(display,windows->image.id,
3864 windows->image.attributes.event_mask);
3865 XSetCursorState(display,windows,MagickFalse);
3866 (void) XFreeCursor(display,cursor);
3871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3875 + X C o m p o s i t e I m a g e %
3879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3881 % XCompositeImage() requests an image name from the user, reads the image and
3882 % composites it with the X window image at a location the user chooses with
3885 % The format of the XCompositeImage method is:
3887 % MagickBooleanType XCompositeImage(Display *display,
3888 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3889 % ExceptionInfo *exception)
3891 % A description of each parameter follows:
3893 % o display: Specifies a connection to an X server; returned from
3896 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3898 % o windows: Specifies a pointer to a XWindows structure.
3900 % o image: the image; returned from ReadImage.
3902 % o exception: return any errors or warnings in this structure.
3905 static MagickBooleanType XCompositeImage(Display *display,
3906 XResourceInfo *resource_info,XWindows *windows,Image *image,
3907 ExceptionInfo *exception)
3910 displacement_geometry[MagickPathExtent] = "30x30",
3911 filename[MagickPathExtent] = "\0";
3924 static CompositeOperator
3925 compose = CopyCompositeOp;
3927 static const ModeType
3928 CompositeCommands[] =
3930 CompositeOperatorsCommand,
3931 CompositeDissolveCommand,
3932 CompositeDisplaceCommand,
3933 CompositeHelpCommand,
3934 CompositeDismissCommand
3938 text[MagickPathExtent];
3971 Request image file name from user.
3973 XFileBrowserWidget(display,windows,"Composite",filename);
3974 if (*filename == '\0')
3979 XSetCursorState(display,windows,MagickTrue);
3980 XCheckRefreshWindows(display,windows);
3981 (void) CopyMagickString(resource_info->image_info->filename,filename,
3983 composite_image=ReadImage(resource_info->image_info,exception);
3984 CatchException(exception);
3985 XSetCursorState(display,windows,MagickFalse);
3986 if (composite_image == (Image *) NULL)
3987 return(MagickFalse);
3991 (void) CloneString(&windows->command.name,"Composite");
3992 windows->command.data=1;
3993 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
3994 (void) XMapRaised(display,windows->command.id);
3995 XClientMessage(display,windows->image.id,windows->im_protocols,
3996 windows->im_update_widget,CurrentTime);
3998 Track pointer until button 1 is pressed.
4000 XQueryPosition(display,windows->image.id,&x,&y);
4001 (void) XSelectInput(display,windows->image.id,
4002 windows->image.attributes.event_mask | PointerMotionMask);
4003 composite_info.x=(ssize_t) windows->image.x+x;
4004 composite_info.y=(ssize_t) windows->image.y+y;
4005 composite_info.width=0;
4006 composite_info.height=0;
4007 cursor=XCreateFontCursor(display,XC_ul_angle);
4008 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4013 if (IfMagickTrue(windows->info.mapped) )
4016 Display pointer position.
4018 (void) FormatLocaleString(text,MagickPathExtent," %+ld%+ld ",
4019 (long) composite_info.x,(long) composite_info.y);
4020 XInfoWidget(display,windows,text);
4022 highlight_info=composite_info;
4023 highlight_info.x=composite_info.x-windows->image.x;
4024 highlight_info.y=composite_info.y-windows->image.y;
4025 XHighlightRectangle(display,windows->image.id,
4026 windows->image.highlight_context,&highlight_info);
4028 Wait for next event.
4030 XScreenEvent(display,windows,&event,exception);
4031 XHighlightRectangle(display,windows->image.id,
4032 windows->image.highlight_context,&highlight_info);
4033 if (event.xany.window == windows->command.id)
4036 Select a command from the Command widget.
4038 id=XCommandWidget(display,windows,CompositeMenu,&event);
4041 switch (CompositeCommands[id])
4043 case CompositeOperatorsCommand:
4046 command[MagickPathExtent],
4050 Select a command from the pop-up menu.
4052 operators=GetCommandOptions(MagickComposeOptions);
4053 if (operators == (char **) NULL)
4055 entry=XMenuWidget(display,windows,CompositeMenu[id],
4056 (const char **) operators,command);
4058 compose=(CompositeOperator) ParseCommandOption(
4059 MagickComposeOptions,MagickFalse,operators[entry]);
4060 operators=DestroyStringList(operators);
4063 case CompositeDissolveCommand:
4066 factor[MagickPathExtent] = "20.0";
4069 Dissolve the two images a given percent.
4071 (void) XSetFunction(display,windows->image.highlight_context,
4073 (void) XDialogWidget(display,windows,"Dissolve",
4074 "Enter the blend factor (0.0 - 99.9%):",factor);
4075 (void) XSetFunction(display,windows->image.highlight_context,
4077 if (*factor == '\0')
4079 blend=StringToDouble(factor,(char **) NULL);
4080 compose=DissolveCompositeOp;
4083 case CompositeDisplaceCommand:
4086 Get horizontal and vertical scale displacement geometry.
4088 (void) XSetFunction(display,windows->image.highlight_context,
4090 (void) XDialogWidget(display,windows,"Displace",
4091 "Enter the horizontal and vertical scale:",displacement_geometry);
4092 (void) XSetFunction(display,windows->image.highlight_context,
4094 if (*displacement_geometry == '\0')
4096 compose=DisplaceCompositeOp;
4099 case CompositeHelpCommand:
4101 (void) XSetFunction(display,windows->image.highlight_context,
4103 XTextViewWidget(display,resource_info,windows,MagickFalse,
4104 "Help Viewer - Image Composite",ImageCompositeHelp);
4105 (void) XSetFunction(display,windows->image.highlight_context,
4109 case CompositeDismissCommand:
4127 if (IfMagickTrue(image->debug) )
4128 (void) LogMagickEvent(X11Event,GetMagickModule(),
4129 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4130 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4131 if (event.xbutton.button != Button1)
4133 if (event.xbutton.window != windows->image.id)
4138 composite_info.width=composite_image->columns;
4139 composite_info.height=composite_image->rows;
4140 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4141 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4142 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4147 if (IfMagickTrue(image->debug) )
4148 (void) LogMagickEvent(X11Event,GetMagickModule(),
4149 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4150 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4151 if (event.xbutton.button != Button1)
4153 if (event.xbutton.window != windows->image.id)
4155 if ((composite_info.width != 0) && (composite_info.height != 0))
4158 User has selected the location of the composite image.
4160 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4161 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4171 command[MagickPathExtent];
4179 if (event.xkey.window != windows->image.id)
4182 Respond to a user key press.
4184 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4185 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4186 *(command+length)='\0';
4187 if (IfMagickTrue(image->debug) )
4188 (void) LogMagickEvent(X11Event,GetMagickModule(),
4189 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4190 switch ((int) key_symbol)
4198 composite_image=DestroyImage(composite_image);
4206 (void) XSetFunction(display,windows->image.highlight_context,
4208 XTextViewWidget(display,resource_info,windows,MagickFalse,
4209 "Help Viewer - Image Composite",ImageCompositeHelp);
4210 (void) XSetFunction(display,windows->image.highlight_context,
4216 (void) XBell(display,0);
4225 Map and unmap Info widget as text cursor crosses its boundaries.
4229 if (IfMagickTrue(windows->info.mapped) )
4231 if ((x < (int) (windows->info.x+windows->info.width)) &&
4232 (y < (int) (windows->info.y+windows->info.height)))
4233 (void) XWithdrawWindow(display,windows->info.id,
4234 windows->info.screen);
4237 if ((x > (int) (windows->info.x+windows->info.width)) ||
4238 (y > (int) (windows->info.y+windows->info.height)))
4239 (void) XMapWindow(display,windows->info.id);
4240 composite_info.x=(ssize_t) windows->image.x+x;
4241 composite_info.y=(ssize_t) windows->image.y+y;
4246 if (IfMagickTrue(image->debug) )
4247 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4252 } while ((state & ExitState) == 0);
4253 (void) XSelectInput(display,windows->image.id,
4254 windows->image.attributes.event_mask);
4255 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4256 XSetCursorState(display,windows,MagickFalse);
4257 (void) XFreeCursor(display,cursor);
4258 if ((state & EscapeState) != 0)
4261 Image compositing is relative to image configuration.
4263 XSetCursorState(display,windows,MagickTrue);
4264 XCheckRefreshWindows(display,windows);
4265 width=(unsigned int) image->columns;
4266 height=(unsigned int) image->rows;
4269 if (windows->image.crop_geometry != (char *) NULL)
4270 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4271 scale_factor=(double) width/windows->image.ximage->width;
4272 composite_info.x+=x;
4273 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4274 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4275 scale_factor=(double) height/windows->image.ximage->height;
4276 composite_info.y+=y;
4277 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4278 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4279 if ((composite_info.width != composite_image->columns) ||
4280 (composite_info.height != composite_image->rows))
4286 Scale composite image.
4288 resize_image=ResizeImage(composite_image,composite_info.width,
4289 composite_info.height,composite_image->filter,exception);
4290 composite_image=DestroyImage(composite_image);
4291 if (resize_image == (Image *) NULL)
4293 XSetCursorState(display,windows,MagickFalse);
4294 return(MagickFalse);
4296 composite_image=resize_image;
4298 if (compose == DisplaceCompositeOp)
4299 (void) SetImageArtifact(composite_image,"compose:args",
4300 displacement_geometry);
4319 Create mattes for blending.
4321 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4322 opacity=(Quantum) (ScaleQuantumToChar(QuantumRange)-
4323 ((ssize_t) ScaleQuantumToChar(QuantumRange)*blend)/100);
4324 if (IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
4325 return(MagickFalse);
4326 image->alpha_trait=BlendPixelTrait;
4327 image_view=AcquireAuthenticCacheView(image,exception);
4328 for (y=0; y < (int) image->rows; y++)
4330 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4332 if (q == (Quantum *) NULL)
4334 for (x=0; x < (int) image->columns; x++)
4336 SetPixelAlpha(image,opacity,q);
4337 q+=GetPixelChannels(image);
4339 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
4342 image_view=DestroyCacheView(image_view);
4345 Composite image with X Image window.
4347 (void) CompositeImage(image,composite_image,compose,MagickTrue,
4348 composite_info.x,composite_info.y,exception);
4349 composite_image=DestroyImage(composite_image);
4350 XSetCursorState(display,windows,MagickFalse);
4352 Update image configuration.
4354 XConfigureImageColormap(display,resource_info,windows,image,exception);
4355 (void) XConfigureImage(display,resource_info,windows,image,exception);
4360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4364 + X C o n f i g u r e I m a g e %
4368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4370 % XConfigureImage() creates a new X image. It also notifies the window
4371 % manager of the new image size and configures the transient widows.
4373 % The format of the XConfigureImage method is:
4375 % MagickBooleanType XConfigureImage(Display *display,
4376 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4377 % ExceptionInfo *exception)
4379 % A description of each parameter follows:
4381 % o display: Specifies a connection to an X server; returned from
4384 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4386 % o windows: Specifies a pointer to a XWindows structure.
4388 % o image: the image.
4390 % o exception: return any errors or warnings in this structure.
4392 % o exception: return any errors or warnings in this structure.
4395 static MagickBooleanType XConfigureImage(Display *display,
4396 XResourceInfo *resource_info,XWindows *windows,Image *image,
4397 ExceptionInfo *exception)
4400 geometry[MagickPathExtent];
4421 Dismiss if window dimensions are zero.
4423 width=(unsigned int) windows->image.window_changes.width;
4424 height=(unsigned int) windows->image.window_changes.height;
4425 if (IfMagickTrue(image->debug) )
4426 (void) LogMagickEvent(X11Event,GetMagickModule(),
4427 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4428 windows->image.ximage->height,(double) width,(double) height);
4429 if ((width*height) == 0)
4434 Resize image to fit Image window dimensions.
4436 XSetCursorState(display,windows,MagickTrue);
4437 (void) XFlush(display);
4438 if (((int) width != windows->image.ximage->width) ||
4439 ((int) height != windows->image.ximage->height))
4440 image->taint=MagickTrue;
4441 windows->magnify.x=(int)
4442 width*windows->magnify.x/windows->image.ximage->width;
4443 windows->magnify.y=(int)
4444 height*windows->magnify.y/windows->image.ximage->height;
4445 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4446 windows->image.y=(int)
4447 (height*windows->image.y/windows->image.ximage->height);
4448 status=XMakeImage(display,resource_info,&windows->image,image,
4449 (unsigned int) width,(unsigned int) height,exception);
4450 if (IfMagickFalse(status) )
4451 XNoticeWidget(display,windows,"Unable to configure X image:",
4452 windows->image.name);
4454 Notify window manager of the new configuration.
4456 if (resource_info->image_geometry != (char *) NULL)
4457 (void) FormatLocaleString(geometry,MagickPathExtent,"%s>!",
4458 resource_info->image_geometry);
4460 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
4461 XDisplayWidth(display,windows->image.screen),
4462 XDisplayHeight(display,windows->image.screen));
4463 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4464 window_changes.width=(int) width;
4465 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4466 window_changes.width=XDisplayWidth(display,windows->image.screen);
4467 window_changes.height=(int) height;
4468 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4469 window_changes.height=XDisplayHeight(display,windows->image.screen);
4470 mask=(size_t) (CWWidth | CWHeight);
4471 if (resource_info->backdrop)
4474 window_changes.x=(int)
4475 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4476 window_changes.y=(int)
4477 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4479 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4480 (unsigned int) mask,&window_changes);
4481 (void) XClearWindow(display,windows->image.id);
4482 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4484 Update Magnify window configuration.
4486 if (IfMagickTrue(windows->magnify.mapped) )
4487 XMakeMagnifyImage(display,windows,exception);
4488 windows->pan.crop_geometry=windows->image.crop_geometry;
4489 XBestIconSize(display,&windows->pan,image);
4490 while (((windows->pan.width << 1) < MaxIconSize) &&
4491 ((windows->pan.height << 1) < MaxIconSize))
4493 windows->pan.width<<=1;
4494 windows->pan.height<<=1;
4496 if (windows->pan.geometry != (char *) NULL)
4497 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4498 &windows->pan.width,&windows->pan.height);
4499 window_changes.width=(int) windows->pan.width;
4500 window_changes.height=(int) windows->pan.height;
4501 size_hints=XAllocSizeHints();
4502 if (size_hints != (XSizeHints *) NULL)
4507 size_hints->flags=PSize | PMinSize | PMaxSize;
4508 size_hints->width=window_changes.width;
4509 size_hints->height=window_changes.height;
4510 size_hints->min_width=size_hints->width;
4511 size_hints->min_height=size_hints->height;
4512 size_hints->max_width=size_hints->width;
4513 size_hints->max_height=size_hints->height;
4514 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4515 (void) XFree((void *) size_hints);
4517 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4518 (unsigned int) (CWWidth | CWHeight),&window_changes);
4520 Update icon window configuration.
4522 windows->icon.crop_geometry=windows->image.crop_geometry;
4523 XBestIconSize(display,&windows->icon,image);
4524 window_changes.width=(int) windows->icon.width;
4525 window_changes.height=(int) windows->icon.height;
4526 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4527 (unsigned int) (CWWidth | CWHeight),&window_changes);
4528 XSetCursorState(display,windows,MagickFalse);
4529 return(IsMagickTrue(status));
4533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4537 + X C r o p I m a g e %
4541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4543 % XCropImage() allows the user to select a region of the image and crop, copy,
4544 % or cut it. For copy or cut, the image can subsequently be composited onto
4545 % the image with XPasteImage.
4547 % The format of the XCropImage method is:
4549 % MagickBooleanType XCropImage(Display *display,
4550 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4551 % const ClipboardMode mode,ExceptionInfo *exception)
4553 % A description of each parameter follows:
4555 % o display: Specifies a connection to an X server; returned from
4558 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4560 % o windows: Specifies a pointer to a XWindows structure.
4562 % o image: the image; returned from ReadImage.
4564 % o mode: This unsigned value specified whether the image should be
4565 % cropped, copied, or cut.
4567 % o exception: return any errors or warnings in this structure.
4570 static MagickBooleanType XCropImage(Display *display,
4571 XResourceInfo *resource_info,XWindows *windows,Image *image,
4572 const ClipboardMode mode,ExceptionInfo *exception)
4581 *RectifyModeMenu[] =
4589 static const ModeType
4599 RectifyDismissCommand
4606 command[MagickPathExtent],
4607 text[MagickPathExtent];
4650 (void) CloneString(&windows->command.name,"Copy");
4655 (void) CloneString(&windows->command.name,"Crop");
4660 (void) CloneString(&windows->command.name,"Cut");
4664 RectifyModeMenu[0]=windows->command.name;
4665 windows->command.data=0;
4666 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4667 (void) XMapRaised(display,windows->command.id);
4668 XClientMessage(display,windows->image.id,windows->im_protocols,
4669 windows->im_update_widget,CurrentTime);
4671 Track pointer until button 1 is pressed.
4673 XQueryPosition(display,windows->image.id,&x,&y);
4674 (void) XSelectInput(display,windows->image.id,
4675 windows->image.attributes.event_mask | PointerMotionMask);
4676 crop_info.x=(ssize_t) windows->image.x+x;
4677 crop_info.y=(ssize_t) windows->image.y+y;
4680 cursor=XCreateFontCursor(display,XC_fleur);
4684 if (IfMagickTrue(windows->info.mapped) )
4687 Display pointer position.
4689 (void) FormatLocaleString(text,MagickPathExtent," %+ld%+ld ",
4690 (long) crop_info.x,(long) crop_info.y);
4691 XInfoWidget(display,windows,text);
4694 Wait for next event.
4696 XScreenEvent(display,windows,&event,exception);
4697 if (event.xany.window == windows->command.id)
4700 Select a command from the Command widget.
4702 id=XCommandWidget(display,windows,CropModeMenu,&event);
4705 switch (CropCommands[id])
4707 case CropHelpCommand:
4713 XTextViewWidget(display,resource_info,windows,MagickFalse,
4714 "Help Viewer - Image Copy",ImageCopyHelp);
4719 XTextViewWidget(display,resource_info,windows,MagickFalse,
4720 "Help Viewer - Image Crop",ImageCropHelp);
4725 XTextViewWidget(display,resource_info,windows,MagickFalse,
4726 "Help Viewer - Image Cut",ImageCutHelp);
4732 case CropDismissCommand:
4750 if (event.xbutton.button != Button1)
4752 if (event.xbutton.window != windows->image.id)
4755 Note first corner of cropping rectangle-- exit loop.
4757 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4758 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4759 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4769 if (event.xkey.window != windows->image.id)
4772 Respond to a user key press.
4774 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4775 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4776 switch ((int) key_symbol)
4795 XTextViewWidget(display,resource_info,windows,MagickFalse,
4796 "Help Viewer - Image Copy",ImageCopyHelp);
4801 XTextViewWidget(display,resource_info,windows,MagickFalse,
4802 "Help Viewer - Image Crop",ImageCropHelp);
4807 XTextViewWidget(display,resource_info,windows,MagickFalse,
4808 "Help Viewer - Image Cut",ImageCutHelp);
4816 (void) XBell(display,0);
4824 if (event.xmotion.window != windows->image.id)
4827 Map and unmap Info widget as text cursor crosses its boundaries.
4831 if (IfMagickTrue(windows->info.mapped) )
4833 if ((x < (int) (windows->info.x+windows->info.width)) &&
4834 (y < (int) (windows->info.y+windows->info.height)))
4835 (void) XWithdrawWindow(display,windows->info.id,
4836 windows->info.screen);
4839 if ((x > (int) (windows->info.x+windows->info.width)) ||
4840 (y > (int) (windows->info.y+windows->info.height)))
4841 (void) XMapWindow(display,windows->info.id);
4842 crop_info.x=(ssize_t) windows->image.x+x;
4843 crop_info.y=(ssize_t) windows->image.y+y;
4849 } while ((state & ExitState) == 0);
4850 (void) XSelectInput(display,windows->image.id,
4851 windows->image.attributes.event_mask);
4852 if ((state & EscapeState) != 0)
4855 User want to exit without cropping.
4857 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4858 (void) XFreeCursor(display,cursor);
4861 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4865 Size rectangle as pointer moves until the mouse button is released.
4867 x=(int) crop_info.x;
4868 y=(int) crop_info.y;
4874 highlight_info=crop_info;
4875 highlight_info.x=crop_info.x-windows->image.x;
4876 highlight_info.y=crop_info.y-windows->image.y;
4877 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4880 Display info and draw cropping rectangle.
4882 if (IfMagickFalse(windows->info.mapped) )
4883 (void) XMapWindow(display,windows->info.id);
4884 (void) FormatLocaleString(text,MagickPathExtent,
4885 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4886 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4887 XInfoWidget(display,windows,text);
4888 XHighlightRectangle(display,windows->image.id,
4889 windows->image.highlight_context,&highlight_info);
4892 if (IfMagickTrue(windows->info.mapped) )
4893 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4895 Wait for next event.
4897 XScreenEvent(display,windows,&event,exception);
4898 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4899 XHighlightRectangle(display,windows->image.id,
4900 windows->image.highlight_context,&highlight_info);
4905 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4906 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4912 User has committed to cropping rectangle.
4914 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4915 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4916 XSetCursorState(display,windows,MagickFalse);
4918 windows->command.data=0;
4919 (void) XCommandWidget(display,windows,RectifyModeMenu,
4927 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4928 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4933 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4934 ((state & ExitState) != 0))
4937 Check boundary conditions.
4939 if (crop_info.x < 0)
4942 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4943 crop_info.x=(ssize_t) windows->image.ximage->width;
4944 if ((int) crop_info.x < x)
4945 crop_info.width=(unsigned int) (x-crop_info.x);
4948 crop_info.width=(unsigned int) (crop_info.x-x);
4949 crop_info.x=(ssize_t) x;
4951 if (crop_info.y < 0)
4954 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4955 crop_info.y=(ssize_t) windows->image.ximage->height;
4956 if ((int) crop_info.y < y)
4957 crop_info.height=(unsigned int) (y-crop_info.y);
4960 crop_info.height=(unsigned int) (crop_info.y-y);
4961 crop_info.y=(ssize_t) y;
4964 } while ((state & ExitState) == 0);
4966 Wait for user to grab a corner of the rectangle or press return.
4969 (void) XMapWindow(display,windows->info.id);
4972 if (IfMagickTrue(windows->info.mapped) )
4975 Display pointer position.
4977 (void) FormatLocaleString(text,MagickPathExtent,
4978 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4979 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4980 XInfoWidget(display,windows,text);
4982 highlight_info=crop_info;
4983 highlight_info.x=crop_info.x-windows->image.x;
4984 highlight_info.y=crop_info.y-windows->image.y;
4985 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
4991 XHighlightRectangle(display,windows->image.id,
4992 windows->image.highlight_context,&highlight_info);
4993 XScreenEvent(display,windows,&event,exception);
4994 if (event.xany.window == windows->command.id)
4997 Select a command from the Command widget.
4999 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5000 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5001 (void) XSetFunction(display,windows->image.highlight_context,
5003 XHighlightRectangle(display,windows->image.id,
5004 windows->image.highlight_context,&highlight_info);
5006 switch (RectifyCommands[id])
5008 case RectifyCopyCommand:
5013 case RectifyHelpCommand:
5015 (void) XSetFunction(display,windows->image.highlight_context,
5021 XTextViewWidget(display,resource_info,windows,MagickFalse,
5022 "Help Viewer - Image Copy",ImageCopyHelp);
5027 XTextViewWidget(display,resource_info,windows,MagickFalse,
5028 "Help Viewer - Image Crop",ImageCropHelp);
5033 XTextViewWidget(display,resource_info,windows,MagickFalse,
5034 "Help Viewer - Image Cut",ImageCutHelp);
5038 (void) XSetFunction(display,windows->image.highlight_context,
5042 case RectifyDismissCommand:
5056 XHighlightRectangle(display,windows->image.id,
5057 windows->image.highlight_context,&highlight_info);
5062 if (event.xbutton.button != Button1)
5064 if (event.xbutton.window != windows->image.id)
5066 x=windows->image.x+event.xbutton.x;
5067 y=windows->image.y+event.xbutton.y;
5068 if ((x < (int) (crop_info.x+RoiDelta)) &&
5069 (x > (int) (crop_info.x-RoiDelta)) &&
5070 (y < (int) (crop_info.y+RoiDelta)) &&
5071 (y > (int) (crop_info.y-RoiDelta)))
5073 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5074 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5075 state|=UpdateConfigurationState;
5078 if ((x < (int) (crop_info.x+RoiDelta)) &&
5079 (x > (int) (crop_info.x-RoiDelta)) &&
5080 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5081 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5083 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5084 state|=UpdateConfigurationState;
5087 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5088 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5089 (y < (int) (crop_info.y+RoiDelta)) &&
5090 (y > (int) (crop_info.y-RoiDelta)))
5092 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5093 state|=UpdateConfigurationState;
5096 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5097 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5098 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5099 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5101 state|=UpdateConfigurationState;
5107 if (event.xbutton.window == windows->pan.id)
5108 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5109 (highlight_info.y != crop_info.y-windows->image.y))
5110 XHighlightRectangle(display,windows->image.id,
5111 windows->image.highlight_context,&highlight_info);
5112 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5113 event.xbutton.time);
5118 if (event.xexpose.window == windows->image.id)
5119 if (event.xexpose.count == 0)
5121 event.xexpose.x=(int) highlight_info.x;
5122 event.xexpose.y=(int) highlight_info.y;
5123 event.xexpose.width=(int) highlight_info.width;
5124 event.xexpose.height=(int) highlight_info.height;
5125 XRefreshWindow(display,&windows->image,&event);
5127 if (event.xexpose.window == windows->info.id)
5128 if (event.xexpose.count == 0)
5129 XInfoWidget(display,windows,text);
5134 if (event.xkey.window != windows->image.id)
5137 Respond to a user key press.
5139 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5140 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5141 switch ((int) key_symbol)
5154 crop_info.x=(ssize_t) (windows->image.width/2L-
5155 crop_info.width/2L);
5156 crop_info.y=(ssize_t) (windows->image.height/2L-
5157 crop_info.height/2L);
5189 (void) XSetFunction(display,windows->image.highlight_context,
5195 XTextViewWidget(display,resource_info,windows,MagickFalse,
5196 "Help Viewer - Image Copy",ImageCopyHelp);
5201 XTextViewWidget(display,resource_info,windows,MagickFalse,
5202 "Help Viewer - Image Cropg",ImageCropHelp);
5207 XTextViewWidget(display,resource_info,windows,MagickFalse,
5208 "Help Viewer - Image Cutg",ImageCutHelp);
5212 (void) XSetFunction(display,windows->image.highlight_context,
5218 (void) XBell(display,0);
5222 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5230 if (event.xmotion.window != windows->image.id)
5233 Map and unmap Info widget as text cursor crosses its boundaries.
5237 if (IfMagickTrue(windows->info.mapped) )
5239 if ((x < (int) (windows->info.x+windows->info.width)) &&
5240 (y < (int) (windows->info.y+windows->info.height)))
5241 (void) XWithdrawWindow(display,windows->info.id,
5242 windows->info.screen);
5245 if ((x > (int) (windows->info.x+windows->info.width)) ||
5246 (y > (int) (windows->info.y+windows->info.height)))
5247 (void) XMapWindow(display,windows->info.id);
5248 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5249 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5252 case SelectionRequest:
5257 XSelectionRequestEvent
5261 Set primary selection.
5263 (void) FormatLocaleString(text,MagickPathExtent,
5264 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5265 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5266 request=(&(event.xselectionrequest));
5267 (void) XChangeProperty(request->display,request->requestor,
5268 request->property,request->target,8,PropModeReplace,
5269 (unsigned char *) text,(int) strlen(text));
5270 notify.type=SelectionNotify;
5271 notify.display=request->display;
5272 notify.requestor=request->requestor;
5273 notify.selection=request->selection;
5274 notify.target=request->target;
5275 notify.time=request->time;
5276 if (request->property == None)
5277 notify.property=request->target;
5279 notify.property=request->property;
5280 (void) XSendEvent(request->display,request->requestor,False,0,
5281 (XEvent *) ¬ify);
5286 if ((state & UpdateConfigurationState) != 0)
5288 (void) XPutBackEvent(display,&event);
5289 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5292 } while ((state & ExitState) == 0);
5293 } while ((state & ExitState) == 0);
5294 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5295 XSetCursorState(display,windows,MagickFalse);
5296 if ((state & EscapeState) != 0)
5298 if (mode == CropMode)
5299 if (((int) crop_info.width != windows->image.ximage->width) ||
5300 ((int) crop_info.height != windows->image.ximage->height))
5303 Reconfigure Image window as defined by cropping rectangle.
5305 XSetCropGeometry(display,windows,&crop_info,image);
5306 windows->image.window_changes.width=(int) crop_info.width;
5307 windows->image.window_changes.height=(int) crop_info.height;
5308 (void) XConfigureImage(display,resource_info,windows,image,exception);
5312 Copy image before applying image transforms.
5314 XSetCursorState(display,windows,MagickTrue);
5315 XCheckRefreshWindows(display,windows);
5316 width=(unsigned int) image->columns;
5317 height=(unsigned int) image->rows;
5320 if (windows->image.crop_geometry != (char *) NULL)
5321 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5322 scale_factor=(double) width/windows->image.ximage->width;
5324 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5325 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5326 scale_factor=(double) height/windows->image.ximage->height;
5328 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5329 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5330 crop_image=CropImage(image,&crop_info,exception);
5331 XSetCursorState(display,windows,MagickFalse);
5332 if (crop_image == (Image *) NULL)
5333 return(MagickFalse);
5334 if (resource_info->copy_image != (Image *) NULL)
5335 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5336 resource_info->copy_image=crop_image;
5337 if (mode == CopyMode)
5339 (void) XConfigureImage(display,resource_info,windows,image,exception);
5345 if (IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
5346 return(MagickFalse);
5347 image->alpha_trait=BlendPixelTrait;
5348 image_view=AcquireAuthenticCacheView(image,exception);
5349 for (y=0; y < (int) crop_info.height; y++)
5351 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5352 crop_info.width,1,exception);
5353 if (q == (Quantum *) NULL)
5355 for (x=0; x < (int) crop_info.width; x++)
5357 SetPixelAlpha(image,TransparentAlpha,q);
5358 q+=GetPixelChannels(image);
5360 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
5363 image_view=DestroyCacheView(image_view);
5365 Update image configuration.
5367 XConfigureImageColormap(display,resource_info,windows,image,exception);
5368 (void) XConfigureImage(display,resource_info,windows,image,exception);
5373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5377 + X D r a w I m a g e %
5381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5383 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5386 % The format of the XDrawEditImage method is:
5388 % MagickBooleanType XDrawEditImage(Display *display,
5389 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5390 % ExceptionInfo *exception)
5392 % A description of each parameter follows:
5394 % o display: Specifies a connection to an X server; returned from
5397 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5399 % o windows: Specifies a pointer to a XWindows structure.
5401 % o image: the image.
5403 % o exception: return any errors or warnings in this structure.
5406 static MagickBooleanType XDrawEditImage(Display *display,
5407 XResourceInfo *resource_info,XWindows *windows,Image **image,
5408 ExceptionInfo *exception)
5424 element = PointElement;
5426 static const ModeType
5439 stipple = (Pixmap) NULL;
5446 command[MagickPathExtent],
5447 text[MagickPathExtent];
5496 Allocate polygon info.
5498 max_coordinates=2048;
5499 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5500 sizeof(*coordinate_info));
5501 if (coordinate_info == (XPoint *) NULL)
5503 (void) ThrowMagickException(exception,GetMagickModule(),
5504 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5505 return(MagickFalse);
5510 (void) CloneString(&windows->command.name,"Draw");
5511 windows->command.data=4;
5512 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5513 (void) XMapRaised(display,windows->command.id);
5514 XClientMessage(display,windows->image.id,windows->im_protocols,
5515 windows->im_update_widget,CurrentTime);
5517 Wait for first button press.
5519 root_window=XRootWindow(display,XDefaultScreen(display));
5520 draw_info.stencil=OpaqueStencil;
5522 cursor=XCreateFontCursor(display,XC_tcross);
5525 XQueryPosition(display,windows->image.id,&x,&y);
5526 (void) XSelectInput(display,windows->image.id,
5527 windows->image.attributes.event_mask | PointerMotionMask);
5528 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5532 if (IfMagickTrue(windows->info.mapped) )
5535 Display pointer position.
5537 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
5538 x+windows->image.x,y+windows->image.y);
5539 XInfoWidget(display,windows,text);
5542 Wait for next event.
5544 XScreenEvent(display,windows,&event,exception);
5545 if (event.xany.window == windows->command.id)
5548 Select a command from the Command widget.
5550 id=XCommandWidget(display,windows,DrawMenu,&event);
5553 switch (DrawCommands[id])
5555 case DrawElementCommand:
5574 Select a command from the pop-up menu.
5576 element=(ElementType) (XMenuWidget(display,windows,
5577 DrawMenu[id],Elements,command)+1);
5580 case DrawColorCommand:
5583 *ColorMenu[MaxNumberPens+1];
5595 Initialize menu selections.
5597 for (i=0; i < (int) (MaxNumberPens-2); i++)
5598 ColorMenu[i]=resource_info->pen_colors[i];
5599 ColorMenu[MaxNumberPens-2]="transparent";
5600 ColorMenu[MaxNumberPens-1]="Browser...";
5601 ColorMenu[MaxNumberPens]=(char *) NULL;
5603 Select a pen color from the pop-up menu.
5605 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5606 (const char **) ColorMenu,command);
5609 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5611 if (IfMagickTrue(transparent) )
5613 draw_info.stencil=TransparentStencil;
5616 if (pen_number == (MaxNumberPens-1))
5619 color_name[MagickPathExtent] = "gray";
5622 Select a pen color from a dialog.
5624 resource_info->pen_colors[pen_number]=color_name;
5625 XColorBrowserWidget(display,windows,"Select",color_name);
5626 if (*color_name == '\0')
5632 (void) XParseColor(display,windows->map_info->colormap,
5633 resource_info->pen_colors[pen_number],&color);
5634 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5635 (unsigned int) MaxColors,&color);
5636 windows->pixel_info->pen_colors[pen_number]=color;
5637 pen_id=(unsigned int) pen_number;
5638 draw_info.stencil=OpaqueStencil;
5641 case DrawStippleCommand:
5653 filename[MagickPathExtent] = "\0";
5670 Select a command from the pop-up menu.
5672 StipplesMenu[7]="Open...";
5673 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5677 if (stipple != (Pixmap) NULL)
5678 (void) XFreePixmap(display,stipple);
5679 stipple=(Pixmap) NULL;
5686 stipple=XCreateBitmapFromData(display,root_window,
5687 (char *) BricksBitmap,BricksWidth,BricksHeight);
5692 stipple=XCreateBitmapFromData(display,root_window,
5693 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5698 stipple=XCreateBitmapFromData(display,root_window,
5699 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5704 stipple=XCreateBitmapFromData(display,root_window,
5705 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5710 stipple=XCreateBitmapFromData(display,root_window,
5711 (char *) WavyBitmap,WavyWidth,WavyHeight);
5716 stipple=XCreateBitmapFromData(display,root_window,
5717 (char *) HighlightBitmap,HighlightWidth,
5724 stipple=XCreateBitmapFromData(display,root_window,
5725 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5731 XFileBrowserWidget(display,windows,"Stipple",filename);
5732 if (*filename == '\0')
5737 XSetCursorState(display,windows,MagickTrue);
5738 XCheckRefreshWindows(display,windows);
5739 image_info=AcquireImageInfo();
5740 (void) CopyMagickString(image_info->filename,filename,
5742 stipple_image=ReadImage(image_info,exception);
5743 CatchException(exception);
5744 XSetCursorState(display,windows,MagickFalse);
5745 if (stipple_image == (Image *) NULL)
5747 (void) AcquireUniqueFileResource(filename);
5748 (void) FormatLocaleString(stipple_image->filename,MagickPathExtent,
5750 (void) WriteImage(image_info,stipple_image,exception);
5751 stipple_image=DestroyImage(stipple_image);
5752 image_info=DestroyImageInfo(image_info);
5753 status=XReadBitmapFile(display,root_window,filename,&width,
5754 &height,&stipple,&x,&y);
5755 (void) RelinquishUniqueFileResource(filename);
5756 if ((status != BitmapSuccess) != 0)
5757 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5761 case DrawWidthCommand:
5764 width[MagickPathExtent] = "0";
5779 Select a command from the pop-up menu.
5781 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5787 line_width=(unsigned int) StringToUnsignedLong(
5791 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5795 line_width=(unsigned int) StringToUnsignedLong(width);
5798 case DrawUndoCommand:
5800 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5804 case DrawHelpCommand:
5806 XTextViewWidget(display,resource_info,windows,MagickFalse,
5807 "Help Viewer - Image Rotation",ImageDrawHelp);
5808 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5811 case DrawDismissCommand:
5823 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5830 if (event.xbutton.button != Button1)
5832 if (event.xbutton.window != windows->image.id)
5851 if (event.xkey.window != windows->image.id)
5854 Respond to a user key press.
5856 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5857 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5858 switch ((int) key_symbol)
5873 XTextViewWidget(display,resource_info,windows,MagickFalse,
5874 "Help Viewer - Image Rotation",ImageDrawHelp);
5879 (void) XBell(display,0);
5888 Map and unmap Info widget as text cursor crosses its boundaries.
5892 if (IfMagickTrue(windows->info.mapped) )
5894 if ((x < (int) (windows->info.x+windows->info.width)) &&
5895 (y < (int) (windows->info.y+windows->info.height)))
5896 (void) XWithdrawWindow(display,windows->info.id,
5897 windows->info.screen);
5900 if ((x > (int) (windows->info.x+windows->info.width)) ||
5901 (y > (int) (windows->info.y+windows->info.height)))
5902 (void) XMapWindow(display,windows->info.id);
5906 } while ((state & ExitState) == 0);
5907 (void) XSelectInput(display,windows->image.id,
5908 windows->image.attributes.event_mask);
5909 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5910 if ((state & EscapeState) != 0)
5913 Draw element as pointer moves until the button is released.
5921 rectangle_info.x=(ssize_t) x;
5922 rectangle_info.y=(ssize_t) y;
5923 rectangle_info.width=0;
5924 rectangle_info.height=0;
5925 number_coordinates=1;
5926 coordinate_info->x=x;
5927 coordinate_info->y=y;
5928 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5937 if (number_coordinates > 1)
5939 (void) XDrawLines(display,windows->image.id,
5940 windows->image.highlight_context,coordinate_info,
5941 number_coordinates,CoordModeOrigin);
5942 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d",
5943 coordinate_info[number_coordinates-1].x,
5944 coordinate_info[number_coordinates-1].y);
5945 XInfoWidget(display,windows,text);
5954 Display angle of the line.
5956 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5957 line_info.y1),(double) (line_info.x2-line_info.x1)));
5958 (void) FormatLocaleString(text,MagickPathExtent," %g",
5960 XInfoWidget(display,windows,text);
5961 XHighlightLine(display,windows->image.id,
5962 windows->image.highlight_context,&line_info);
5965 if (IfMagickTrue(windows->info.mapped) )
5966 (void) XWithdrawWindow(display,windows->info.id,
5967 windows->info.screen);
5970 case RectangleElement:
5971 case FillRectangleElement:
5973 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5976 Display info and draw drawing rectangle.
5978 (void) FormatLocaleString(text,MagickPathExtent,
5979 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5980 (double) rectangle_info.height,(double) rectangle_info.x,
5981 (double) rectangle_info.y);
5982 XInfoWidget(display,windows,text);
5983 XHighlightRectangle(display,windows->image.id,
5984 windows->image.highlight_context,&rectangle_info);
5987 if (IfMagickTrue(windows->info.mapped) )
5988 (void) XWithdrawWindow(display,windows->info.id,
5989 windows->info.screen);
5993 case FillCircleElement:
5994 case EllipseElement:
5995 case FillEllipseElement:
5997 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6000 Display info and draw drawing rectangle.
6002 (void) FormatLocaleString(text,MagickPathExtent,
6003 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6004 (double) rectangle_info.height,(double) rectangle_info.x,
6005 (double) rectangle_info.y);
6006 XInfoWidget(display,windows,text);
6007 XHighlightEllipse(display,windows->image.id,
6008 windows->image.highlight_context,&rectangle_info);
6011 if (IfMagickTrue(windows->info.mapped) )
6012 (void) XWithdrawWindow(display,windows->info.id,
6013 windows->info.screen);
6016 case PolygonElement:
6017 case FillPolygonElement:
6019 if (number_coordinates > 1)
6020 (void) XDrawLines(display,windows->image.id,
6021 windows->image.highlight_context,coordinate_info,
6022 number_coordinates,CoordModeOrigin);
6026 Display angle of the line.
6028 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6029 line_info.y1),(double) (line_info.x2-line_info.x1)));
6030 (void) FormatLocaleString(text,MagickPathExtent," %g",
6032 XInfoWidget(display,windows,text);
6033 XHighlightLine(display,windows->image.id,
6034 windows->image.highlight_context,&line_info);
6037 if (IfMagickTrue(windows->info.mapped) )
6038 (void) XWithdrawWindow(display,windows->info.id,
6039 windows->info.screen);
6044 Wait for next event.
6046 XScreenEvent(display,windows,&event,exception);
6052 if (number_coordinates > 1)
6053 (void) XDrawLines(display,windows->image.id,
6054 windows->image.highlight_context,coordinate_info,
6055 number_coordinates,CoordModeOrigin);
6061 XHighlightLine(display,windows->image.id,
6062 windows->image.highlight_context,&line_info);
6065 case RectangleElement:
6066 case FillRectangleElement:
6068 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6069 XHighlightRectangle(display,windows->image.id,
6070 windows->image.highlight_context,&rectangle_info);
6074 case FillCircleElement:
6075 case EllipseElement:
6076 case FillEllipseElement:
6078 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6079 XHighlightEllipse(display,windows->image.id,
6080 windows->image.highlight_context,&rectangle_info);
6083 case PolygonElement:
6084 case FillPolygonElement:
6086 if (number_coordinates > 1)
6087 (void) XDrawLines(display,windows->image.id,
6088 windows->image.highlight_context,coordinate_info,
6089 number_coordinates,CoordModeOrigin);
6091 XHighlightLine(display,windows->image.id,
6092 windows->image.highlight_context,&line_info);
6103 User has committed to element.
6105 line_info.x2=event.xbutton.x;
6106 line_info.y2=event.xbutton.y;
6107 rectangle_info.x=(ssize_t) event.xbutton.x;
6108 rectangle_info.y=(ssize_t) event.xbutton.y;
6109 coordinate_info[number_coordinates].x=event.xbutton.x;
6110 coordinate_info[number_coordinates].y=event.xbutton.y;
6111 if (((element != PolygonElement) &&
6112 (element != FillPolygonElement)) || (distance <= 9))
6117 number_coordinates++;
6118 if (number_coordinates < (int) max_coordinates)
6120 line_info.x1=event.xbutton.x;
6121 line_info.y1=event.xbutton.y;
6124 max_coordinates<<=1;
6125 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6126 max_coordinates,sizeof(*coordinate_info));
6127 if (coordinate_info == (XPoint *) NULL)
6128 (void) ThrowMagickException(exception,GetMagickModule(),
6129 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6136 if (event.xmotion.window != windows->image.id)
6138 if (element != PointElement)
6140 line_info.x2=event.xmotion.x;
6141 line_info.y2=event.xmotion.y;
6142 rectangle_info.x=(ssize_t) event.xmotion.x;
6143 rectangle_info.y=(ssize_t) event.xmotion.y;
6146 coordinate_info[number_coordinates].x=event.xbutton.x;
6147 coordinate_info[number_coordinates].y=event.xbutton.y;
6148 number_coordinates++;
6149 if (number_coordinates < (int) max_coordinates)
6151 max_coordinates<<=1;
6152 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6153 max_coordinates,sizeof(*coordinate_info));
6154 if (coordinate_info == (XPoint *) NULL)
6155 (void) ThrowMagickException(exception,GetMagickModule(),
6156 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6163 Check boundary conditions.
6165 if (line_info.x2 < 0)
6168 if (line_info.x2 > (int) windows->image.width)
6169 line_info.x2=(short) windows->image.width;
6170 if (line_info.y2 < 0)
6173 if (line_info.y2 > (int) windows->image.height)
6174 line_info.y2=(short) windows->image.height;
6175 distance=(unsigned int)
6176 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6177 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6178 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6179 ((state & ExitState) != 0))
6181 if (rectangle_info.x < 0)
6184 if (rectangle_info.x > (ssize_t) windows->image.width)
6185 rectangle_info.x=(ssize_t) windows->image.width;
6186 if ((int) rectangle_info.x < x)
6187 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6190 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6191 rectangle_info.x=(ssize_t) x;
6193 if (rectangle_info.y < 0)
6196 if (rectangle_info.y > (ssize_t) windows->image.height)
6197 rectangle_info.y=(ssize_t) windows->image.height;
6198 if ((int) rectangle_info.y < y)
6199 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6202 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6203 rectangle_info.y=(ssize_t) y;
6206 } while ((state & ExitState) == 0);
6207 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6208 if ((element == PointElement) || (element == PolygonElement) ||
6209 (element == FillPolygonElement))
6212 Determine polygon bounding box.
6214 rectangle_info.x=(ssize_t) coordinate_info->x;
6215 rectangle_info.y=(ssize_t) coordinate_info->y;
6216 x=coordinate_info->x;
6217 y=coordinate_info->y;
6218 for (i=1; i < number_coordinates; i++)
6220 if (coordinate_info[i].x > x)
6221 x=coordinate_info[i].x;
6222 if (coordinate_info[i].y > y)
6223 y=coordinate_info[i].y;
6224 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6225 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6226 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6227 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6229 rectangle_info.width=(size_t) (x-rectangle_info.x);
6230 rectangle_info.height=(size_t) (y-rectangle_info.y);
6231 for (i=0; i < number_coordinates; i++)
6233 coordinate_info[i].x-=rectangle_info.x;
6234 coordinate_info[i].y-=rectangle_info.y;
6241 if ((element == RectangleElement) ||
6242 (element == CircleElement) || (element == EllipseElement))
6244 rectangle_info.width--;
6245 rectangle_info.height--;
6248 Drawing is relative to image configuration.
6250 draw_info.x=(int) rectangle_info.x;
6251 draw_info.y=(int) rectangle_info.y;
6252 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6254 width=(unsigned int) (*image)->columns;
6255 height=(unsigned int) (*image)->rows;
6258 if (windows->image.crop_geometry != (char *) NULL)
6259 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6260 draw_info.x+=windows->image.x-(line_width/2);
6261 if (draw_info.x < 0)
6263 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6264 draw_info.y+=windows->image.y-(line_width/2);
6265 if (draw_info.y < 0)
6267 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6268 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6269 if (draw_info.width > (unsigned int) (*image)->columns)
6270 draw_info.width=(unsigned int) (*image)->columns;
6271 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6272 if (draw_info.height > (unsigned int) (*image)->rows)
6273 draw_info.height=(unsigned int) (*image)->rows;
6274 (void) FormatLocaleString(draw_info.geometry,MagickPathExtent,"%ux%u%+d%+d",
6275 width*draw_info.width/windows->image.ximage->width,
6276 height*draw_info.height/windows->image.ximage->height,
6277 draw_info.x+x,draw_info.y+y);
6279 Initialize drawing attributes.
6281 draw_info.degrees=0.0;
6282 draw_info.element=element;
6283 draw_info.stipple=stipple;
6284 draw_info.line_width=line_width;
6285 draw_info.line_info=line_info;
6286 if (line_info.x1 > (int) (line_width/2))
6287 draw_info.line_info.x1=(short) line_width/2;
6288 if (line_info.y1 > (int) (line_width/2))
6289 draw_info.line_info.y1=(short) line_width/2;
6290 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6291 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6292 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6294 draw_info.line_info.x2=(-draw_info.line_info.x2);
6295 draw_info.line_info.y2=(-draw_info.line_info.y2);
6297 if (draw_info.line_info.x2 < 0)
6299 draw_info.line_info.x2=(-draw_info.line_info.x2);
6300 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6302 if (draw_info.line_info.y2 < 0)
6304 draw_info.line_info.y2=(-draw_info.line_info.y2);
6305 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6307 draw_info.rectangle_info=rectangle_info;
6308 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6309 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6310 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6311 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6312 draw_info.number_coordinates=(unsigned int) number_coordinates;
6313 draw_info.coordinate_info=coordinate_info;
6314 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6316 Draw element on image.
6318 XSetCursorState(display,windows,MagickTrue);
6319 XCheckRefreshWindows(display,windows);
6320 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6321 XSetCursorState(display,windows,MagickFalse);
6323 Update image colormap and return to image drawing.
6325 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6326 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6328 XSetCursorState(display,windows,MagickFalse);
6329 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6330 return(IsMagickTrue(status));
6334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6338 + X D r a w P a n R e c t a n g l e %
6342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6344 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6345 % displays a zoom image and the rectangle shows which portion of the image is
6346 % displayed in the Image window.
6348 % The format of the XDrawPanRectangle method is:
6350 % XDrawPanRectangle(Display *display,XWindows *windows)
6352 % A description of each parameter follows:
6354 % o display: Specifies a connection to an X server; returned from
6357 % o windows: Specifies a pointer to a XWindows structure.
6360 static void XDrawPanRectangle(Display *display,XWindows *windows)
6369 Determine dimensions of the panning rectangle.
6371 scale_factor=(double) windows->pan.width/windows->image.ximage->width;
6372 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6373 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6374 scale_factor=(double)
6375 windows->pan.height/windows->image.ximage->height;
6376 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6377 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6379 Display the panning rectangle.
6381 (void) XClearWindow(display,windows->pan.id);
6382 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6391 + X I m a g e C a c h e %
6395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6397 % XImageCache() handles the creation, manipulation, and destruction of the
6398 % image cache (undo and redo buffers).
6400 % The format of the XImageCache method is:
6402 % void XImageCache(Display *display,XResourceInfo *resource_info,
6403 % XWindows *windows,const CommandType command,Image **image,
6404 % ExceptionInfo *exception)
6406 % A description of each parameter follows:
6408 % o display: Specifies a connection to an X server; returned from
6411 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6413 % o windows: Specifies a pointer to a XWindows structure.
6415 % o command: Specifies a command to perform.
6417 % o image: the image; XImageCache may transform the image and return a new
6420 % o exception: return any errors or warnings in this structure.
6423 static void XImageCache(Display *display,XResourceInfo *resource_info,
6424 XWindows *windows,const CommandType command,Image **image,
6425 ExceptionInfo *exception)
6431 *redo_image = (Image *) NULL,
6432 *undo_image = (Image *) NULL;
6436 case FreeBuffersCommand:
6439 Free memory from the undo and redo cache.
6441 while (undo_image != (Image *) NULL)
6443 cache_image=undo_image;
6444 undo_image=GetPreviousImageInList(undo_image);
6445 cache_image->list=DestroyImage(cache_image->list);
6446 cache_image=DestroyImage(cache_image);
6448 undo_image=NewImageList();
6449 if (redo_image != (Image *) NULL)
6450 redo_image=DestroyImage(redo_image);
6451 redo_image=NewImageList();
6457 image_geometry[MagickPathExtent];
6460 Undo the last image transformation.
6462 if (undo_image == (Image *) NULL)
6464 (void) XBell(display,0);
6467 cache_image=undo_image;
6468 undo_image=GetPreviousImageInList(undo_image);
6469 windows->image.window_changes.width=(int) cache_image->columns;
6470 windows->image.window_changes.height=(int) cache_image->rows;
6471 (void) FormatLocaleString(image_geometry,MagickPathExtent,"%dx%d!",
6472 windows->image.ximage->width,windows->image.ximage->height);
6473 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6475 if (windows->image.crop_geometry != (char *) NULL)
6476 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6477 windows->image.crop_geometry);
6478 windows->image.crop_geometry=cache_image->geometry;
6479 if (redo_image != (Image *) NULL)
6480 redo_image=DestroyImage(redo_image);
6481 redo_image=(*image);
6482 *image=cache_image->list;
6483 cache_image=DestroyImage(cache_image);
6484 if (IfMagickTrue(windows->image.orphan) )
6486 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6487 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6493 case HalfSizeCommand:
6494 case OriginalSizeCommand:
6495 case DoubleSizeCommand:
6502 case RotateRightCommand:
6503 case RotateLeftCommand:
6508 case ContrastStretchCommand:
6509 case SigmoidalContrastCommand:
6510 case NormalizeCommand:
6511 case EqualizeCommand:
6513 case SaturationCommand:
6514 case BrightnessCommand:
6518 case GrayscaleCommand:
6520 case QuantizeCommand:
6521 case DespeckleCommand:
6523 case ReduceNoiseCommand:
6524 case AddNoiseCommand:
6525 case SharpenCommand:
6527 case ThresholdCommand:
6528 case EdgeDetectCommand:
6532 case SegmentCommand:
6533 case SolarizeCommand:
6534 case SepiaToneCommand:
6536 case ImplodeCommand:
6537 case VignetteCommand:
6539 case OilPaintCommand:
6540 case CharcoalDrawCommand:
6541 case AnnotateCommand:
6542 case AddBorderCommand:
6543 case AddFrameCommand:
6544 case CompositeCommand:
6545 case CommentCommand:
6547 case RegionofInterestCommand:
6548 case SaveToUndoBufferCommand:
6557 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6558 if (undo_image != (Image *) NULL)
6561 Ensure the undo cache has enough memory available.
6563 previous_image=undo_image;
6564 while (previous_image != (Image *) NULL)
6566 bytes+=previous_image->list->columns*previous_image->list->rows*
6568 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6570 previous_image=GetPreviousImageInList(previous_image);
6573 bytes-=previous_image->list->columns*previous_image->list->rows*
6575 if (previous_image == undo_image)
6576 undo_image=NewImageList();
6578 previous_image->next->previous=NewImageList();
6581 while (previous_image != (Image *) NULL)
6584 Delete any excess memory from undo cache.
6586 cache_image=previous_image;
6587 previous_image=GetPreviousImageInList(previous_image);
6588 cache_image->list=DestroyImage(cache_image->list);
6589 cache_image=DestroyImage(cache_image);
6592 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6595 Save image before transformations are applied.
6597 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6598 if (cache_image == (Image *) NULL)
6600 XSetCursorState(display,windows,MagickTrue);
6601 XCheckRefreshWindows(display,windows);
6602 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6603 XSetCursorState(display,windows,MagickFalse);
6604 if (cache_image->list == (Image *) NULL)
6606 cache_image=DestroyImage(cache_image);
6609 cache_image->columns=(size_t) windows->image.ximage->width;
6610 cache_image->rows=(size_t) windows->image.ximage->height;
6611 cache_image->geometry=windows->image.crop_geometry;
6612 if (windows->image.crop_geometry != (char *) NULL)
6614 cache_image->geometry=AcquireString((char *) NULL);
6615 (void) CopyMagickString(cache_image->geometry,
6616 windows->image.crop_geometry,MagickPathExtent);
6618 if (undo_image == (Image *) NULL)
6620 undo_image=cache_image;
6623 undo_image->next=cache_image;
6624 undo_image->next->previous=undo_image;
6625 undo_image=undo_image->next;
6631 if (command == RedoCommand)
6634 Redo the last image transformation.
6636 if (redo_image == (Image *) NULL)
6638 (void) XBell(display,0);
6641 windows->image.window_changes.width=(int) redo_image->columns;
6642 windows->image.window_changes.height=(int) redo_image->rows;
6643 if (windows->image.crop_geometry != (char *) NULL)
6644 windows->image.crop_geometry=(char *)
6645 RelinquishMagickMemory(windows->image.crop_geometry);
6646 windows->image.crop_geometry=redo_image->geometry;
6647 *image=DestroyImage(*image);
6649 redo_image=NewImageList();
6650 if (IfMagickTrue(windows->image.orphan) )
6652 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6653 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6656 if (command != InfoCommand)
6661 XSetCursorState(display,windows,MagickTrue);
6662 XCheckRefreshWindows(display,windows);
6663 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6664 XSetCursorState(display,windows,MagickFalse);
6668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6672 + X I m a g e W i n d o w C o m m a n d %
6676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6678 % XImageWindowCommand() makes a transform to the image or Image window as
6679 % specified by a user menu button or keyboard command.
6681 % The format of the XImageWindowCommand method is:
6683 % CommandType XImageWindowCommand(Display *display,
6684 % XResourceInfo *resource_info,XWindows *windows,
6685 % const MagickStatusType state,KeySym key_symbol,Image **image,
6686 % ExceptionInfo *exception)
6688 % A description of each parameter follows:
6690 % o nexus: Method XImageWindowCommand returns an image when the
6691 % user chooses 'Open Image' from the command menu. Otherwise a null
6692 % image is returned.
6694 % o display: Specifies a connection to an X server; returned from
6697 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6699 % o windows: Specifies a pointer to a XWindows structure.
6701 % o state: key mask.
6703 % o key_symbol: Specifies a command to perform.
6705 % o image: the image; XImageWIndowCommand may transform the image and
6706 % return a new image pointer.
6708 % o exception: return any errors or warnings in this structure.
6711 static CommandType XImageWindowCommand(Display *display,
6712 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6713 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6716 delta[MagickPathExtent] = "";
6719 Digits[] = "01234567890";
6724 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6726 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6729 resource_info->quantum=1;
6731 last_symbol=key_symbol;
6732 delta[strlen(delta)+1]='\0';
6733 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6734 resource_info->quantum=StringToLong(delta);
6735 return(NullCommand);
6737 last_symbol=key_symbol;
6738 if (resource_info->immutable)
6741 Virtual image window has a restricted command set.
6746 return(InfoCommand);
6749 return(PrintCommand);
6751 return(NextCommand);
6754 return(QuitCommand);
6758 return(NullCommand);
6760 switch ((int) key_symbol)
6764 if ((state & ControlMask) == 0)
6766 return(OpenCommand);
6769 return(NextCommand);
6771 return(FormerCommand);
6774 if ((state & Mod1Mask) != 0)
6775 return(SwirlCommand);
6776 if ((state & ControlMask) == 0)
6777 return(ShearCommand);
6778 return(SaveCommand);
6783 if ((state & Mod1Mask) != 0)
6784 return(OilPaintCommand);
6785 if ((state & Mod4Mask) != 0)
6786 return(ColorCommand);
6787 if ((state & ControlMask) == 0)
6788 return(NullCommand);
6789 return(PrintCommand);
6793 if ((state & Mod4Mask) != 0)
6794 return(DrawCommand);
6795 if ((state & ControlMask) == 0)
6796 return(NullCommand);
6797 return(DeleteCommand);
6801 if ((state & ControlMask) == 0)
6802 return(NullCommand);
6803 return(SelectCommand);
6807 if ((state & ControlMask) == 0)
6808 return(NullCommand);
6813 return(QuitCommand);
6817 if ((state & ControlMask) == 0)
6818 return(NullCommand);
6819 return(UndoCommand);
6824 if ((state & ControlMask) == 0)
6825 return(RollCommand);
6826 return(RedoCommand);
6830 if ((state & ControlMask) == 0)
6831 return(NullCommand);
6836 if ((state & Mod1Mask) != 0)
6837 return(CharcoalDrawCommand);
6838 if ((state & ControlMask) == 0)
6839 return(CropCommand);
6840 return(CopyCommand);
6845 if ((state & Mod4Mask) != 0)
6846 return(CompositeCommand);
6847 if ((state & ControlMask) == 0)
6848 return(FlipCommand);
6849 return(PasteCommand);
6852 return(HalfSizeCommand);
6854 return(OriginalSizeCommand);
6856 return(DoubleSizeCommand);
6858 return(ResizeCommand);
6860 return(RefreshCommand);
6861 case XK_bracketleft:
6862 return(ChopCommand);
6864 return(FlopCommand);
6866 return(RotateRightCommand);
6868 return(RotateLeftCommand);
6870 return(RotateCommand);
6872 return(TrimCommand);
6876 return(SaturationCommand);
6878 return(BrightnessCommand);
6880 return(GammaCommand);
6882 return(SpiffCommand);
6884 return(DullCommand);
6886 return(NormalizeCommand);
6888 return(EqualizeCommand);
6890 return(NegateCommand);
6892 return(GrayscaleCommand);
6894 return(QuantizeCommand);
6896 return(DespeckleCommand);
6898 return(EmbossCommand);
6900 return(ReduceNoiseCommand);
6902 return(AddNoiseCommand);
6904 return(SharpenCommand);
6906 return(BlurCommand);
6908 return(ThresholdCommand);
6910 return(EdgeDetectCommand);
6912 return(SpreadCommand);
6914 return(ShadeCommand);
6916 return(RaiseCommand);
6918 return(SegmentCommand);
6921 if ((state & Mod1Mask) == 0)
6922 return(NullCommand);
6923 return(ImplodeCommand);
6927 if ((state & Mod1Mask) == 0)
6928 return(NullCommand);
6929 return(WaveCommand);
6933 if ((state & Mod4Mask) == 0)
6934 return(NullCommand);
6935 return(MatteCommand);
6939 if ((state & Mod4Mask) == 0)
6940 return(NullCommand);
6941 return(AddBorderCommand);
6945 if ((state & Mod4Mask) == 0)
6946 return(NullCommand);
6947 return(AddFrameCommand);
6951 if ((state & Mod4Mask) == 0)
6952 return(NullCommand);
6953 return(CommentCommand);
6957 if ((state & Mod1Mask) != 0)
6958 return(ApplyCommand);
6959 if ((state & Mod4Mask) != 0)
6960 return(AnnotateCommand);
6961 if ((state & ControlMask) == 0)
6962 return(NullCommand);
6963 return(RegionofInterestCommand);
6966 return(InfoCommand);
6968 return(ZoomCommand);
6971 if ((state & ShiftMask) == 0)
6972 return(NullCommand);
6973 return(ShowPreviewCommand);
6976 return(LaunchCommand);
6978 return(HelpCommand);
6980 return(BrowseDocumentationCommand);
6983 (void) XMapRaised(display,windows->command.id);
6984 return(NullCommand);
6991 XTranslateImage(display,windows,*image,key_symbol);
6992 return(NullCommand);
7003 if ((state & Mod1Mask) != 0)
7009 Trim one pixel from edge of image.
7013 crop_info.width=(size_t) windows->image.ximage->width;
7014 crop_info.height=(size_t) windows->image.ximage->height;
7015 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7017 if (resource_info->quantum >= (int) crop_info.height)
7018 resource_info->quantum=(int) crop_info.height-1;
7019 crop_info.height-=resource_info->quantum;
7021 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7023 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7024 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7025 crop_info.y+=resource_info->quantum;
7026 crop_info.height-=resource_info->quantum;
7028 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7030 if (resource_info->quantum >= (int) crop_info.width)
7031 resource_info->quantum=(int) crop_info.width-1;
7032 crop_info.width-=resource_info->quantum;
7034 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7036 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7037 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7038 crop_info.x+=resource_info->quantum;
7039 crop_info.width-=resource_info->quantum;
7041 if ((int) (windows->image.x+windows->image.width) >
7042 (int) crop_info.width)
7043 windows->image.x=(int) (crop_info.width-windows->image.width);
7044 if ((int) (windows->image.y+windows->image.height) >
7045 (int) crop_info.height)
7046 windows->image.y=(int) (crop_info.height-windows->image.height);
7047 XSetCropGeometry(display,windows,&crop_info,*image);
7048 windows->image.window_changes.width=(int) crop_info.width;
7049 windows->image.window_changes.height=(int) crop_info.height;
7050 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7051 (void) XConfigureImage(display,resource_info,windows,*image,
7053 return(NullCommand);
7055 XTranslateImage(display,windows,*image,key_symbol);
7056 return(NullCommand);
7059 return(NullCommand);
7061 return(NullCommand);
7065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7069 + X M a g i c k C o m m a n d %
7073 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7075 % XMagickCommand() makes a transform to the image or Image window as
7076 % specified by a user menu button or keyboard command.
7078 % The format of the XMagickCommand method is:
7080 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7081 % XWindows *windows,const CommandType command,Image **image,
7082 % ExceptionInfo *exception)
7084 % A description of each parameter follows:
7086 % o display: Specifies a connection to an X server; returned from
7089 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7091 % o windows: Specifies a pointer to a XWindows structure.
7093 % o command: Specifies a command to perform.
7095 % o image: the image; XMagickCommand may transform the image and return a
7096 % new image pointer.
7098 % o exception: return any errors or warnings in this structure.
7101 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7102 XWindows *windows,const CommandType command,Image **image,
7103 ExceptionInfo *exception)
7106 filename[MagickPathExtent],
7107 geometry[MagickPathExtent],
7108 modulate_factors[MagickPathExtent];
7137 color[MagickPathExtent] = "gray";
7144 Process user command.
7146 XCheckRefreshWindows(display,windows);
7147 XImageCache(display,resource_info,windows,command,image,exception);
7148 nexus=NewImageList();
7149 windows->image.window_changes.width=windows->image.ximage->width;
7150 windows->image.window_changes.height=windows->image.ximage->height;
7151 image_info=CloneImageInfo(resource_info->image_info);
7152 SetGeometryInfo(&geometry_info);
7153 GetQuantizeInfo(&quantize_info);
7161 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7169 for (i=0; i < resource_info->quantum; i++)
7170 XClientMessage(display,windows->image.id,windows->im_protocols,
7171 windows->im_next_image,CurrentTime);
7177 Display former image.
7179 for (i=0; i < resource_info->quantum; i++)
7180 XClientMessage(display,windows->image.id,windows->im_protocols,
7181 windows->im_former_image,CurrentTime);
7192 if (*resource_info->home_directory == '\0')
7193 (void) CopyMagickString(resource_info->home_directory,".",
7195 status=chdir(resource_info->home_directory);
7197 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7198 "UnableToOpenFile","%s",resource_info->home_directory);
7199 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7207 status=XSaveImage(display,resource_info,windows,*image,exception);
7208 if (IfMagickFalse(status) )
7211 message[MagickPathExtent];
7213 (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
7214 exception->reason != (char *) NULL ? exception->reason : "",
7215 exception->description != (char *) NULL ? exception->description :
7217 XNoticeWidget(display,windows,"Unable to save file:",message);
7227 status=XPrintImage(display,resource_info,windows,*image,exception);
7228 if (IfMagickFalse(status) )
7231 message[MagickPathExtent];
7233 (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
7234 exception->reason != (char *) NULL ? exception->reason : "",
7235 exception->description != (char *) NULL ? exception->description :
7237 XNoticeWidget(display,windows,"Unable to print file:",message);
7245 filename[MagickPathExtent] = "\0";
7250 XFileBrowserWidget(display,windows,"Delete",filename);
7251 if (*filename == '\0')
7253 status=ShredFile(filename);
7254 if (IfMagickTrue(status) )
7255 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7264 color[MagickPathExtent] = "gray",
7265 geometry[MagickPathExtent] = "640x480";
7268 *format = "gradient";
7271 Query user for canvas geometry.
7273 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7275 if (*geometry == '\0')
7279 XColorBrowserWidget(display,windows,"Select",color);
7285 (void) FormatLocaleString(image_info->filename,MagickPathExtent,
7286 "%s:%s",format,color);
7287 (void) CloneString(&image_info->size,geometry);
7288 nexus=ReadImage(image_info,exception);
7289 CatchException(exception);
7290 XClientMessage(display,windows->image.id,windows->im_protocols,
7291 windows->im_next_image,CurrentTime);
7294 case VisualDirectoryCommand:
7297 Visual Image directory.
7299 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7307 if (IfMagickFalse(resource_info->confirm_exit) )
7308 XClientMessage(display,windows->image.id,windows->im_protocols,
7309 windows->im_exit,CurrentTime);
7316 Confirm program exit.
7318 status=XConfirmWidget(display,windows,"Do you really want to exit",
7319 resource_info->client_name);
7321 XClientMessage(display,windows->image.id,windows->im_protocols,
7322 windows->im_exit,CurrentTime);
7331 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7339 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7348 status=XPasteImage(display,resource_info,windows,*image,exception);
7349 if (IfMagickFalse(status) )
7351 XNoticeWidget(display,windows,"Unable to paste X image",
7352 (*image)->filename);
7357 case HalfSizeCommand:
7362 windows->image.window_changes.width=windows->image.ximage->width/2;
7363 windows->image.window_changes.height=windows->image.ximage->height/2;
7364 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7367 case OriginalSizeCommand:
7370 Original image size.
7372 windows->image.window_changes.width=(int) (*image)->columns;
7373 windows->image.window_changes.height=(int) (*image)->rows;
7374 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7377 case DoubleSizeCommand:
7380 Double the image size.
7382 windows->image.window_changes.width=windows->image.ximage->width << 1;
7383 windows->image.window_changes.height=windows->image.ximage->height << 1;
7384 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7403 width=(size_t) windows->image.ximage->width;
7404 height=(size_t) windows->image.ximage->height;
7407 (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g+0+0",
7408 (double) width,(double) height);
7409 status=XDialogWidget(display,windows,"Resize",
7410 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7411 if (*geometry == '\0')
7414 (void) ConcatenateMagickString(geometry,"!",MagickPathExtent);
7415 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7416 windows->image.window_changes.width=(int) width;
7417 windows->image.window_changes.height=(int) height;
7418 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7424 image_geometry[MagickPathExtent];
7426 if ((windows->image.crop_geometry == (char *) NULL) &&
7427 ((int) (*image)->columns == windows->image.ximage->width) &&
7428 ((int) (*image)->rows == windows->image.ximage->height))
7431 Apply size transforms to image.
7433 XSetCursorState(display,windows,MagickTrue);
7434 XCheckRefreshWindows(display,windows);
7436 Crop and/or scale displayed image.
7438 (void) FormatLocaleString(image_geometry,MagickPathExtent,"%dx%d!",
7439 windows->image.ximage->width,windows->image.ximage->height);
7440 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7442 if (windows->image.crop_geometry != (char *) NULL)
7443 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7444 windows->image.crop_geometry);
7447 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7448 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7451 case RefreshCommand:
7453 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7456 case RestoreCommand:
7459 Restore Image window to its original size.
7461 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7462 (windows->image.height == (unsigned int) (*image)->rows) &&
7463 (windows->image.crop_geometry == (char *) NULL))
7465 (void) XBell(display,0);
7468 windows->image.window_changes.width=(int) (*image)->columns;
7469 windows->image.window_changes.height=(int) (*image)->rows;
7470 if (windows->image.crop_geometry != (char *) NULL)
7472 windows->image.crop_geometry=(char *)
7473 RelinquishMagickMemory(windows->image.crop_geometry);
7474 windows->image.crop_geometry=(char *) NULL;
7478 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7479 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7487 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7496 status=XChopImage(display,resource_info,windows,image,exception);
7497 if (IfMagickFalse(status) )
7499 XNoticeWidget(display,windows,"Unable to cut X image",
7500 (*image)->filename);
7511 Flop image scanlines.
7513 XSetCursorState(display,windows,MagickTrue);
7514 XCheckRefreshWindows(display,windows);
7515 flop_image=FlopImage(*image,exception);
7516 if (flop_image != (Image *) NULL)
7518 *image=DestroyImage(*image);
7521 CatchException(exception);
7522 XSetCursorState(display,windows,MagickFalse);
7523 if (windows->image.crop_geometry != (char *) NULL)
7528 width=(unsigned int) (*image)->columns;
7529 height=(unsigned int) (*image)->rows;
7530 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7532 (void) FormatLocaleString(windows->image.crop_geometry,MagickPathExtent,
7533 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7535 if (IfMagickTrue(windows->image.orphan) )
7537 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7546 Flip image scanlines.
7548 XSetCursorState(display,windows,MagickTrue);
7549 XCheckRefreshWindows(display,windows);
7550 flip_image=FlipImage(*image,exception);
7551 if (flip_image != (Image *) NULL)
7553 *image=DestroyImage(*image);
7556 CatchException(exception);
7557 XSetCursorState(display,windows,MagickFalse);
7558 if (windows->image.crop_geometry != (char *) NULL)
7563 width=(unsigned int) (*image)->columns;
7564 height=(unsigned int) (*image)->rows;
7565 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7567 (void) FormatLocaleString(windows->image.crop_geometry,MagickPathExtent,
7568 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7570 if (IfMagickTrue(windows->image.orphan) )
7572 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7575 case RotateRightCommand:
7578 Rotate image 90 degrees clockwise.
7580 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7581 if (IfMagickFalse(status) )
7583 XNoticeWidget(display,windows,"Unable to rotate X image",
7584 (*image)->filename);
7589 case RotateLeftCommand:
7592 Rotate image 90 degrees counter-clockwise.
7594 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7595 if (IfMagickFalse(status) )
7597 XNoticeWidget(display,windows,"Unable to rotate X image",
7598 (*image)->filename);
7608 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7609 if (IfMagickFalse(status) )
7611 XNoticeWidget(display,windows,"Unable to rotate X image",
7612 (*image)->filename);
7623 geometry[MagickPathExtent] = "45.0x45.0";
7626 Query user for shear color and geometry.
7628 XColorBrowserWidget(display,windows,"Select",color);
7631 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7633 if (*geometry == '\0')
7638 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7640 XSetCursorState(display,windows,MagickTrue);
7641 XCheckRefreshWindows(display,windows);
7642 (void) QueryColorCompliance(color,AllCompliance,
7643 &(*image)->background_color,exception);
7644 flags=ParseGeometry(geometry,&geometry_info);
7645 if ((flags & SigmaValue) == 0)
7646 geometry_info.sigma=geometry_info.rho;
7647 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7649 if (shear_image != (Image *) NULL)
7651 *image=DestroyImage(*image);
7654 CatchException(exception);
7655 XSetCursorState(display,windows,MagickFalse);
7656 if (IfMagickTrue(windows->image.orphan) )
7658 windows->image.window_changes.width=(int) (*image)->columns;
7659 windows->image.window_changes.height=(int) (*image)->rows;
7660 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7661 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7670 geometry[MagickPathExtent] = "+2+2";
7673 Query user for the roll geometry.
7675 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7677 if (*geometry == '\0')
7682 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7684 XSetCursorState(display,windows,MagickTrue);
7685 XCheckRefreshWindows(display,windows);
7686 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7688 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7690 if (roll_image != (Image *) NULL)
7692 *image=DestroyImage(*image);
7695 CatchException(exception);
7696 XSetCursorState(display,windows,MagickFalse);
7697 if (IfMagickTrue(windows->image.orphan) )
7699 windows->image.window_changes.width=(int) (*image)->columns;
7700 windows->image.window_changes.height=(int) (*image)->rows;
7701 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7702 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7708 fuzz[MagickPathExtent];
7711 Query user for the fuzz factor.
7713 (void) FormatLocaleString(fuzz,MagickPathExtent,"%g%%",100.0*
7714 (*image)->fuzz/(QuantumRange+1.0));
7715 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7718 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+1.0);
7722 status=XTrimImage(display,resource_info,windows,*image,exception);
7723 if (IfMagickFalse(status) )
7725 XNoticeWidget(display,windows,"Unable to trim X image",
7726 (*image)->filename);
7734 hue_percent[MagickPathExtent] = "110";
7737 Query user for percent hue change.
7739 (void) XDialogWidget(display,windows,"Apply",
7740 "Enter percent change in image hue (0-200):",hue_percent);
7741 if (*hue_percent == '\0')
7746 XSetCursorState(display,windows,MagickTrue);
7747 XCheckRefreshWindows(display,windows);
7748 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MagickPathExtent);
7749 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7751 (void) ModulateImage(*image,modulate_factors,exception);
7752 XSetCursorState(display,windows,MagickFalse);
7753 if (IfMagickTrue(windows->image.orphan) )
7755 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7756 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7759 case SaturationCommand:
7762 saturation_percent[MagickPathExtent] = "110";
7765 Query user for percent saturation change.
7767 (void) XDialogWidget(display,windows,"Apply",
7768 "Enter percent change in color saturation (0-200):",saturation_percent);
7769 if (*saturation_percent == '\0')
7772 Vary color saturation.
7774 XSetCursorState(display,windows,MagickTrue);
7775 XCheckRefreshWindows(display,windows);
7776 (void) CopyMagickString(modulate_factors,"100.0/",MagickPathExtent);
7777 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7779 (void) ModulateImage(*image,modulate_factors,exception);
7780 XSetCursorState(display,windows,MagickFalse);
7781 if (IfMagickTrue(windows->image.orphan) )
7783 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7784 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7787 case BrightnessCommand:
7790 brightness_percent[MagickPathExtent] = "110";
7793 Query user for percent brightness change.
7795 (void) XDialogWidget(display,windows,"Apply",
7796 "Enter percent change in color brightness (0-200):",brightness_percent);
7797 if (*brightness_percent == '\0')
7800 Vary the color brightness.
7802 XSetCursorState(display,windows,MagickTrue);
7803 XCheckRefreshWindows(display,windows);
7804 (void) CopyMagickString(modulate_factors,brightness_percent,
7806 (void) ModulateImage(*image,modulate_factors,exception);
7807 XSetCursorState(display,windows,MagickFalse);
7808 if (IfMagickTrue(windows->image.orphan) )
7810 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7811 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7817 factor[MagickPathExtent] = "1.6";
7820 Query user for gamma value.
7822 (void) XDialogWidget(display,windows,"Gamma",
7823 "Enter gamma value (e.g. 1.2):",factor);
7824 if (*factor == '\0')
7827 Gamma correct image.
7829 XSetCursorState(display,windows,MagickTrue);
7830 XCheckRefreshWindows(display,windows);
7831 (void) GammaImage(*image,strtod(factor,(char **) NULL),exception);
7832 XSetCursorState(display,windows,MagickFalse);
7833 if (IfMagickTrue(windows->image.orphan) )
7835 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7836 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7842 Sharpen the image contrast.
7844 XSetCursorState(display,windows,MagickTrue);
7845 XCheckRefreshWindows(display,windows);
7846 (void) ContrastImage(*image,MagickTrue,exception);
7847 XSetCursorState(display,windows,MagickFalse);
7848 if (IfMagickTrue(windows->image.orphan) )
7850 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7851 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7857 Dull the image contrast.
7859 XSetCursorState(display,windows,MagickTrue);
7860 XCheckRefreshWindows(display,windows);
7861 (void) ContrastImage(*image,MagickFalse,exception);
7862 XSetCursorState(display,windows,MagickFalse);
7863 if (IfMagickTrue(windows->image.orphan) )
7865 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7866 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7869 case ContrastStretchCommand:
7876 levels[MagickPathExtent] = "1%";
7879 Query user for gamma value.
7881 (void) XDialogWidget(display,windows,"Contrast Stretch",
7882 "Enter black and white points:",levels);
7883 if (*levels == '\0')
7886 Contrast stretch image.
7888 XSetCursorState(display,windows,MagickTrue);
7889 XCheckRefreshWindows(display,windows);
7890 flags=ParseGeometry(levels,&geometry_info);
7891 black_point=geometry_info.rho;
7892 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7893 if ((flags & PercentValue) != 0)
7895 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7896 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7898 white_point=(double) (*image)->columns*(*image)->rows-white_point;
7899 (void) ContrastStretchImage(*image,black_point,white_point,
7901 XSetCursorState(display,windows,MagickFalse);
7902 if (IfMagickTrue(windows->image.orphan) )
7904 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7905 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7908 case SigmoidalContrastCommand:
7917 levels[MagickPathExtent] = "3x50%";
7920 Query user for gamma value.
7922 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7923 "Enter contrast and midpoint:",levels);
7924 if (*levels == '\0')
7927 Contrast stretch image.
7929 XSetCursorState(display,windows,MagickTrue);
7930 XCheckRefreshWindows(display,windows);
7931 flags=ParseGeometry(levels,&geometry_info);
7932 if ((flags & SigmaValue) == 0)
7933 geometry_info.sigma=1.0*QuantumRange/2.0;
7934 if ((flags & PercentValue) != 0)
7935 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7936 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7937 geometry_info.sigma,exception);
7938 XSetCursorState(display,windows,MagickFalse);
7939 if (IfMagickTrue(windows->image.orphan) )
7941 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7942 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7945 case NormalizeCommand:
7948 Perform histogram normalization on the image.
7950 XSetCursorState(display,windows,MagickTrue);
7951 XCheckRefreshWindows(display,windows);
7952 (void) NormalizeImage(*image,exception);
7953 XSetCursorState(display,windows,MagickFalse);
7954 if (IfMagickTrue(windows->image.orphan) )
7956 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7957 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7960 case EqualizeCommand:
7963 Perform histogram equalization on the image.
7965 XSetCursorState(display,windows,MagickTrue);
7966 XCheckRefreshWindows(display,windows);
7967 (void) EqualizeImage(*image,exception);
7968 XSetCursorState(display,windows,MagickFalse);
7969 if (IfMagickTrue(windows->image.orphan) )
7971 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7972 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7978 Negate colors in image.
7980 XSetCursorState(display,windows,MagickTrue);
7981 XCheckRefreshWindows(display,windows);
7982 (void) NegateImage(*image,MagickFalse,exception);
7983 XSetCursorState(display,windows,MagickFalse);
7984 if (IfMagickTrue(windows->image.orphan) )
7986 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7987 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7990 case GrayscaleCommand:
7993 Convert image to grayscale.
7995 XSetCursorState(display,windows,MagickTrue);
7996 XCheckRefreshWindows(display,windows);
7997 (void) SetImageType(*image,(*image)->alpha_trait == UndefinedPixelTrait ?
7998 GrayscaleType : GrayscaleAlphaType,exception);
7999 XSetCursorState(display,windows,MagickFalse);
8000 if (IfMagickTrue(windows->image.orphan) )
8002 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8003 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8012 filename[MagickPathExtent] = "\0";
8015 Request image file name from user.
8017 XFileBrowserWidget(display,windows,"Map",filename);
8018 if (*filename == '\0')
8023 XSetCursorState(display,windows,MagickTrue);
8024 XCheckRefreshWindows(display,windows);
8025 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
8026 affinity_image=ReadImage(image_info,exception);
8027 if (affinity_image != (Image *) NULL)
8029 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8030 affinity_image=DestroyImage(affinity_image);
8032 CatchException(exception);
8033 XSetCursorState(display,windows,MagickFalse);
8034 if (IfMagickTrue(windows->image.orphan) )
8036 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8037 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8040 case QuantizeCommand:
8046 colors[MagickPathExtent] = "256";
8049 Query user for maximum number of colors.
8051 status=XDialogWidget(display,windows,"Quantize",
8052 "Maximum number of colors:",colors);
8053 if (*colors == '\0')
8056 Color reduce the image.
8058 XSetCursorState(display,windows,MagickTrue);
8059 XCheckRefreshWindows(display,windows);
8060 quantize_info.number_colors=StringToUnsignedLong(colors);
8061 quantize_info.dither_method=status != 0 ? RiemersmaDitherMethod :
8063 (void) QuantizeImage(&quantize_info,*image,exception);
8064 XSetCursorState(display,windows,MagickFalse);
8065 if (IfMagickTrue(windows->image.orphan) )
8067 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8068 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8071 case DespeckleCommand:
8079 XSetCursorState(display,windows,MagickTrue);
8080 XCheckRefreshWindows(display,windows);
8081 despeckle_image=DespeckleImage(*image,exception);
8082 if (despeckle_image != (Image *) NULL)
8084 *image=DestroyImage(*image);
8085 *image=despeckle_image;
8087 CatchException(exception);
8088 XSetCursorState(display,windows,MagickFalse);
8089 if (IfMagickTrue(windows->image.orphan) )
8091 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8092 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8101 radius[MagickPathExtent] = "0.0x1.0";
8104 Query user for emboss radius.
8106 (void) XDialogWidget(display,windows,"Emboss",
8107 "Enter the emboss radius and standard deviation:",radius);
8108 if (*radius == '\0')
8111 Reduce noise in the image.
8113 XSetCursorState(display,windows,MagickTrue);
8114 XCheckRefreshWindows(display,windows);
8115 flags=ParseGeometry(radius,&geometry_info);
8116 if ((flags & SigmaValue) == 0)
8117 geometry_info.sigma=1.0;
8118 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8120 if (emboss_image != (Image *) NULL)
8122 *image=DestroyImage(*image);
8123 *image=emboss_image;
8125 CatchException(exception);
8126 XSetCursorState(display,windows,MagickFalse);
8127 if (IfMagickTrue(windows->image.orphan) )
8129 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8130 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8133 case ReduceNoiseCommand:
8139 radius[MagickPathExtent] = "0";
8142 Query user for noise radius.
8144 (void) XDialogWidget(display,windows,"Reduce Noise",
8145 "Enter the noise radius:",radius);
8146 if (*radius == '\0')
8149 Reduce noise in the image.
8151 XSetCursorState(display,windows,MagickTrue);
8152 XCheckRefreshWindows(display,windows);
8153 flags=ParseGeometry(radius,&geometry_info);
8154 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8155 geometry_info.rho,(size_t) geometry_info.rho,exception);
8156 if (noise_image != (Image *) NULL)
8158 *image=DestroyImage(*image);
8161 CatchException(exception);
8162 XSetCursorState(display,windows,MagickFalse);
8163 if (IfMagickTrue(windows->image.orphan) )
8165 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8166 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8169 case AddNoiseCommand:
8178 noise_type[MagickPathExtent] = "Gaussian";
8181 Add noise to the image.
8183 noises=GetCommandOptions(MagickNoiseOptions);
8184 if (noises == (char **) NULL)
8186 XListBrowserWidget(display,windows,&windows->widget,
8187 (const char **) noises,"Add Noise",
8188 "Select a type of noise to add to your image:",noise_type);
8189 noises=DestroyStringList(noises);
8190 if (*noise_type == '\0')
8192 XSetCursorState(display,windows,MagickTrue);
8193 XCheckRefreshWindows(display,windows);
8194 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8195 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8196 if (noise_image != (Image *) NULL)
8198 *image=DestroyImage(*image);
8201 CatchException(exception);
8202 XSetCursorState(display,windows,MagickFalse);
8203 if (IfMagickTrue(windows->image.orphan) )
8205 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8206 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8209 case SharpenCommand:
8215 radius[MagickPathExtent] = "0.0x1.0";
8218 Query user for sharpen radius.
8220 (void) XDialogWidget(display,windows,"Sharpen",
8221 "Enter the sharpen radius and standard deviation:",radius);
8222 if (*radius == '\0')
8225 Sharpen image scanlines.
8227 XSetCursorState(display,windows,MagickTrue);
8228 XCheckRefreshWindows(display,windows);
8229 flags=ParseGeometry(radius,&geometry_info);
8230 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8232 if (sharp_image != (Image *) NULL)
8234 *image=DestroyImage(*image);
8237 CatchException(exception);
8238 XSetCursorState(display,windows,MagickFalse);
8239 if (IfMagickTrue(windows->image.orphan) )
8241 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8242 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8251 radius[MagickPathExtent] = "0.0x1.0";
8254 Query user for blur radius.
8256 (void) XDialogWidget(display,windows,"Blur",
8257 "Enter the blur radius and standard deviation:",radius);
8258 if (*radius == '\0')
8263 XSetCursorState(display,windows,MagickTrue);
8264 XCheckRefreshWindows(display,windows);
8265 flags=ParseGeometry(radius,&geometry_info);
8266 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8268 if (blur_image != (Image *) NULL)
8270 *image=DestroyImage(*image);
8273 CatchException(exception);
8274 XSetCursorState(display,windows,MagickFalse);
8275 if (IfMagickTrue(windows->image.orphan) )
8277 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8278 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8281 case ThresholdCommand:
8287 factor[MagickPathExtent] = "128";
8290 Query user for threshold value.
8292 (void) XDialogWidget(display,windows,"Threshold",
8293 "Enter threshold value:",factor);
8294 if (*factor == '\0')
8297 Gamma correct image.
8299 XSetCursorState(display,windows,MagickTrue);
8300 XCheckRefreshWindows(display,windows);
8301 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8302 (void) BilevelImage(*image,threshold,exception);
8303 XSetCursorState(display,windows,MagickFalse);
8304 if (IfMagickTrue(windows->image.orphan) )
8306 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8307 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8310 case EdgeDetectCommand:
8316 radius[MagickPathExtent] = "0";
8319 Query user for edge factor.
8321 (void) XDialogWidget(display,windows,"Detect Edges",
8322 "Enter the edge detect radius:",radius);
8323 if (*radius == '\0')
8326 Detect edge in image.
8328 XSetCursorState(display,windows,MagickTrue);
8329 XCheckRefreshWindows(display,windows);
8330 flags=ParseGeometry(radius,&geometry_info);
8331 edge_image=EdgeImage(*image,geometry_info.rho,exception);
8332 if (edge_image != (Image *) NULL)
8334 *image=DestroyImage(*image);
8337 CatchException(exception);
8338 XSetCursorState(display,windows,MagickFalse);
8339 if (IfMagickTrue(windows->image.orphan) )
8341 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8342 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8351 amount[MagickPathExtent] = "2";
8354 Query user for spread amount.
8356 (void) XDialogWidget(display,windows,"Spread",
8357 "Enter the displacement amount:",amount);
8358 if (*amount == '\0')
8361 Displace image pixels by a random amount.
8363 XSetCursorState(display,windows,MagickTrue);
8364 XCheckRefreshWindows(display,windows);
8365 flags=ParseGeometry(amount,&geometry_info);
8366 spread_image=EdgeImage(*image,geometry_info.rho,exception);
8367 if (spread_image != (Image *) NULL)
8369 *image=DestroyImage(*image);
8370 *image=spread_image;
8372 CatchException(exception);
8373 XSetCursorState(display,windows,MagickFalse);
8374 if (IfMagickTrue(windows->image.orphan) )
8376 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8377 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8389 geometry[MagickPathExtent] = "30x30";
8392 Query user for the shade geometry.
8394 status=XDialogWidget(display,windows,"Shade",
8395 "Enter the azimuth and elevation of the light source:",geometry);
8396 if (*geometry == '\0')
8401 XSetCursorState(display,windows,MagickTrue);
8402 XCheckRefreshWindows(display,windows);
8403 flags=ParseGeometry(geometry,&geometry_info);
8404 if ((flags & SigmaValue) == 0)
8405 geometry_info.sigma=1.0;
8406 shade_image=ShadeImage(*image,IsMagickTrue(status),
8407 geometry_info.rho,geometry_info.sigma,exception);
8408 if (shade_image != (Image *) NULL)
8410 *image=DestroyImage(*image);
8413 CatchException(exception);
8414 XSetCursorState(display,windows,MagickFalse);
8415 if (IfMagickTrue(windows->image.orphan) )
8417 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8418 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8424 bevel_width[MagickPathExtent] = "10";
8427 Query user for bevel width.
8429 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8430 if (*bevel_width == '\0')
8435 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8437 XSetCursorState(display,windows,MagickTrue);
8438 XCheckRefreshWindows(display,windows);
8439 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8441 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8442 XSetCursorState(display,windows,MagickFalse);
8443 if (IfMagickTrue(windows->image.orphan) )
8445 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8446 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8449 case SegmentCommand:
8452 threshold[MagickPathExtent] = "1.0x1.5";
8455 Query user for smoothing threshold.
8457 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8459 if (*threshold == '\0')
8464 XSetCursorState(display,windows,MagickTrue);
8465 XCheckRefreshWindows(display,windows);
8466 flags=ParseGeometry(threshold,&geometry_info);
8467 if ((flags & SigmaValue) == 0)
8468 geometry_info.sigma=1.0;
8469 (void) SegmentImage(*image,sRGBColorspace,MagickFalse,geometry_info.rho,
8470 geometry_info.sigma,exception);
8471 XSetCursorState(display,windows,MagickFalse);
8472 if (IfMagickTrue(windows->image.orphan) )
8474 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8475 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8478 case SepiaToneCommand:
8487 factor[MagickPathExtent] = "80%";
8490 Query user for sepia-tone factor.
8492 (void) XDialogWidget(display,windows,"Sepia Tone",
8493 "Enter the sepia tone factor (0 - 99.9%):",factor);
8494 if (*factor == '\0')
8497 Sepia tone image pixels.
8499 XSetCursorState(display,windows,MagickTrue);
8500 XCheckRefreshWindows(display,windows);
8501 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8502 sepia_image=SepiaToneImage(*image,threshold,exception);
8503 if (sepia_image != (Image *) NULL)
8505 *image=DestroyImage(*image);
8508 CatchException(exception);
8509 XSetCursorState(display,windows,MagickFalse);
8510 if (IfMagickTrue(windows->image.orphan) )
8512 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8513 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8516 case SolarizeCommand:
8522 factor[MagickPathExtent] = "60%";
8525 Query user for solarize factor.
8527 (void) XDialogWidget(display,windows,"Solarize",
8528 "Enter the solarize factor (0 - 99.9%):",factor);
8529 if (*factor == '\0')
8532 Solarize image pixels.
8534 XSetCursorState(display,windows,MagickTrue);
8535 XCheckRefreshWindows(display,windows);
8536 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8537 (void) SolarizeImage(*image,threshold,exception);
8538 XSetCursorState(display,windows,MagickFalse);
8539 if (IfMagickTrue(windows->image.orphan) )
8541 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8542 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8551 degrees[MagickPathExtent] = "60";
8554 Query user for swirl angle.
8556 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8558 if (*degrees == '\0')
8561 Swirl image pixels about the center.
8563 XSetCursorState(display,windows,MagickTrue);
8564 XCheckRefreshWindows(display,windows);
8565 flags=ParseGeometry(degrees,&geometry_info);
8566 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8568 if (swirl_image != (Image *) NULL)
8570 *image=DestroyImage(*image);
8573 CatchException(exception);
8574 XSetCursorState(display,windows,MagickFalse);
8575 if (IfMagickTrue(windows->image.orphan) )
8577 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8578 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8581 case ImplodeCommand:
8587 factor[MagickPathExtent] = "0.3";
8590 Query user for implode factor.
8592 (void) XDialogWidget(display,windows,"Implode",
8593 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8594 if (*factor == '\0')
8597 Implode image pixels about the center.
8599 XSetCursorState(display,windows,MagickTrue);
8600 XCheckRefreshWindows(display,windows);
8601 flags=ParseGeometry(factor,&geometry_info);
8602 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8604 if (implode_image != (Image *) NULL)
8606 *image=DestroyImage(*image);
8607 *image=implode_image;
8609 CatchException(exception);
8610 XSetCursorState(display,windows,MagickFalse);
8611 if (IfMagickTrue(windows->image.orphan) )
8613 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8614 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8617 case VignetteCommand:
8623 geometry[MagickPathExtent] = "0x20";
8626 Query user for the vignette geometry.
8628 (void) XDialogWidget(display,windows,"Vignette",
8629 "Enter the radius, sigma, and x and y offsets:",geometry);
8630 if (*geometry == '\0')
8633 Soften the edges of the image in vignette style
8635 XSetCursorState(display,windows,MagickTrue);
8636 XCheckRefreshWindows(display,windows);
8637 flags=ParseGeometry(geometry,&geometry_info);
8638 if ((flags & SigmaValue) == 0)
8639 geometry_info.sigma=1.0;
8640 if ((flags & XiValue) == 0)
8641 geometry_info.xi=0.1*(*image)->columns;
8642 if ((flags & PsiValue) == 0)
8643 geometry_info.psi=0.1*(*image)->rows;
8644 vignette_image=VignetteImage(*image,geometry_info.rho,0.0,(ssize_t)
8645 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
8647 if (vignette_image != (Image *) NULL)
8649 *image=DestroyImage(*image);
8650 *image=vignette_image;
8652 CatchException(exception);
8653 XSetCursorState(display,windows,MagickFalse);
8654 if (IfMagickTrue(windows->image.orphan) )
8656 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8657 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8666 geometry[MagickPathExtent] = "25x150";
8669 Query user for the wave geometry.
8671 (void) XDialogWidget(display,windows,"Wave",
8672 "Enter the amplitude and length of the wave:",geometry);
8673 if (*geometry == '\0')
8676 Alter an image along a sine wave.
8678 XSetCursorState(display,windows,MagickTrue);
8679 XCheckRefreshWindows(display,windows);
8680 flags=ParseGeometry(geometry,&geometry_info);
8681 if ((flags & SigmaValue) == 0)
8682 geometry_info.sigma=1.0;
8683 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8684 (*image)->interpolate,exception);
8685 if (wave_image != (Image *) NULL)
8687 *image=DestroyImage(*image);
8690 CatchException(exception);
8691 XSetCursorState(display,windows,MagickFalse);
8692 if (IfMagickTrue(windows->image.orphan) )
8694 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8695 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8698 case OilPaintCommand:
8704 radius[MagickPathExtent] = "0";
8707 Query user for circular neighborhood radius.
8709 (void) XDialogWidget(display,windows,"Oil Paint",
8710 "Enter the mask radius:",radius);
8711 if (*radius == '\0')
8714 OilPaint image scanlines.
8716 XSetCursorState(display,windows,MagickTrue);
8717 XCheckRefreshWindows(display,windows);
8718 flags=ParseGeometry(radius,&geometry_info);
8719 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8721 if (paint_image != (Image *) NULL)
8723 *image=DestroyImage(*image);
8726 CatchException(exception);
8727 XSetCursorState(display,windows,MagickFalse);
8728 if (IfMagickTrue(windows->image.orphan) )
8730 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8731 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8734 case CharcoalDrawCommand:
8740 radius[MagickPathExtent] = "0x1";
8743 Query user for charcoal radius.
8745 (void) XDialogWidget(display,windows,"Charcoal Draw",
8746 "Enter the charcoal radius and sigma:",radius);
8747 if (*radius == '\0')
8752 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8754 XSetCursorState(display,windows,MagickTrue);
8755 XCheckRefreshWindows(display,windows);
8756 flags=ParseGeometry(radius,&geometry_info);
8757 if ((flags & SigmaValue) == 0)
8758 geometry_info.sigma=geometry_info.rho;
8759 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8761 if (charcoal_image != (Image *) NULL)
8763 *image=DestroyImage(*image);
8764 *image=charcoal_image;
8766 CatchException(exception);
8767 XSetCursorState(display,windows,MagickFalse);
8768 if (IfMagickTrue(windows->image.orphan) )
8770 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8771 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8774 case AnnotateCommand:
8777 Annotate the image with text.
8779 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8780 if (IfMagickFalse(status) )
8782 XNoticeWidget(display,windows,"Unable to annotate X image",
8783 (*image)->filename);
8793 status=XDrawEditImage(display,resource_info,windows,image,exception);
8794 if (IfMagickFalse(status) )
8796 XNoticeWidget(display,windows,"Unable to draw on the X image",
8797 (*image)->filename);
8807 status=XColorEditImage(display,resource_info,windows,image,exception);
8808 if (IfMagickFalse(status) )
8810 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8811 (*image)->filename);
8821 status=XMatteEditImage(display,resource_info,windows,image,exception);
8822 if (IfMagickFalse(status) )
8824 XNoticeWidget(display,windows,"Unable to matte edit X image",
8825 (*image)->filename);
8830 case CompositeCommand:
8835 status=XCompositeImage(display,resource_info,windows,*image,
8837 if (IfMagickFalse(status) )
8839 XNoticeWidget(display,windows,"Unable to composite X image",
8840 (*image)->filename);
8845 case AddBorderCommand:
8851 geometry[MagickPathExtent] = "6x6";
8854 Query user for border color and geometry.
8856 XColorBrowserWidget(display,windows,"Select",color);
8859 (void) XDialogWidget(display,windows,"Add Border",
8860 "Enter border geometry:",geometry);
8861 if (*geometry == '\0')
8864 Add a border to the image.
8866 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8868 XSetCursorState(display,windows,MagickTrue);
8869 XCheckRefreshWindows(display,windows);
8870 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8872 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8874 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8876 if (border_image != (Image *) NULL)
8878 *image=DestroyImage(*image);
8879 *image=border_image;
8881 CatchException(exception);
8882 XSetCursorState(display,windows,MagickFalse);
8883 if (IfMagickTrue(windows->image.orphan) )
8885 windows->image.window_changes.width=(int) (*image)->columns;
8886 windows->image.window_changes.height=(int) (*image)->rows;
8887 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8888 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8891 case AddFrameCommand:
8900 geometry[MagickPathExtent] = "6x6";
8903 Query user for frame color and geometry.
8905 XColorBrowserWidget(display,windows,"Select",color);
8908 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8910 if (*geometry == '\0')
8913 Surround image with an ornamental border.
8915 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8917 XSetCursorState(display,windows,MagickTrue);
8918 XCheckRefreshWindows(display,windows);
8919 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8921 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8923 frame_info.width=page_geometry.width;
8924 frame_info.height=page_geometry.height;
8925 frame_info.outer_bevel=page_geometry.x;
8926 frame_info.inner_bevel=page_geometry.y;
8927 frame_info.x=(ssize_t) frame_info.width;
8928 frame_info.y=(ssize_t) frame_info.height;
8929 frame_info.width=(*image)->columns+2*frame_info.width;
8930 frame_info.height=(*image)->rows+2*frame_info.height;
8931 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8932 if (frame_image != (Image *) NULL)
8934 *image=DestroyImage(*image);
8937 CatchException(exception);
8938 XSetCursorState(display,windows,MagickFalse);
8939 if (IfMagickTrue(windows->image.orphan) )
8941 windows->image.window_changes.width=(int) (*image)->columns;
8942 windows->image.window_changes.height=(int) (*image)->rows;
8943 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8944 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8947 case CommentCommand:
8961 unique_file=AcquireUniqueFileResource(image_info->filename);
8962 if (unique_file == -1)
8963 XNoticeWidget(display,windows,"Unable to edit image comment",
8964 image_info->filename);
8965 value=GetImageProperty(*image,"comment",exception);
8966 if (value == (char *) NULL)
8967 unique_file=close(unique_file)-1;
8973 file=fdopen(unique_file,"w");
8974 if (file == (FILE *) NULL)
8976 XNoticeWidget(display,windows,"Unable to edit image comment",
8977 image_info->filename);
8980 for (p=value; *p != '\0'; p++)
8981 (void) fputc((int) *p,file);
8982 (void) fputc('\n',file);
8983 (void) fclose(file);
8985 XSetCursorState(display,windows,MagickTrue);
8986 XCheckRefreshWindows(display,windows);
8987 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
8989 if (IfMagickFalse(status) )
8990 XNoticeWidget(display,windows,"Unable to edit image comment",
8997 comment=FileToString(image_info->filename,~0UL,exception);
8998 if (comment != (char *) NULL)
9000 (void) SetImageProperty(*image,"comment",comment,exception);
9001 (*image)->taint=MagickTrue;
9004 (void) RelinquishUniqueFileResource(image_info->filename);
9005 XSetCursorState(display,windows,MagickFalse);
9013 XSetCursorState(display,windows,MagickTrue);
9014 XCheckRefreshWindows(display,windows);
9015 (void) AcquireUniqueFilename(filename);
9016 (void) FormatLocaleString((*image)->filename,MagickPathExtent,"launch:%s",
9018 status=WriteImage(image_info,*image,exception);
9019 if (IfMagickFalse(status) )
9020 XNoticeWidget(display,windows,"Unable to launch image editor",
9024 nexus=ReadImage(resource_info->image_info,exception);
9025 CatchException(exception);
9026 XClientMessage(display,windows->image.id,windows->im_protocols,
9027 windows->im_next_image,CurrentTime);
9029 (void) RelinquishUniqueFileResource(filename);
9030 XSetCursorState(display,windows,MagickFalse);
9033 case RegionofInterestCommand:
9036 Apply an image processing technique to a region of interest.
9038 (void) XROIImage(display,resource_info,windows,image,exception);
9048 if (IfMagickTrue(windows->magnify.mapped) )
9049 (void) XRaiseWindow(display,windows->magnify.id);
9055 XSetCursorState(display,windows,MagickTrue);
9056 (void) XMapRaised(display,windows->magnify.id);
9057 XSetCursorState(display,windows,MagickFalse);
9061 case ShowPreviewCommand:
9070 preview_type[MagickPathExtent] = "Gamma";
9073 Select preview type from menu.
9075 previews=GetCommandOptions(MagickPreviewOptions);
9076 if (previews == (char **) NULL)
9078 XListBrowserWidget(display,windows,&windows->widget,
9079 (const char **) previews,"Preview",
9080 "Select an enhancement, effect, or F/X:",preview_type);
9081 previews=DestroyStringList(previews);
9082 if (*preview_type == '\0')
9087 XSetCursorState(display,windows,MagickTrue);
9088 XCheckRefreshWindows(display,windows);
9089 image_info->preview_type=(PreviewType)
9090 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9091 image_info->group=(ssize_t) windows->image.id;
9092 (void) DeleteImageProperty(*image,"label");
9093 (void) SetImageProperty(*image,"label","Preview",exception);
9094 (void) AcquireUniqueFilename(filename);
9095 (void) FormatLocaleString((*image)->filename,MagickPathExtent,"preview:%s",
9097 status=WriteImage(image_info,*image,exception);
9098 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
9099 preview_image=ReadImage(image_info,exception);
9100 (void) RelinquishUniqueFileResource(filename);
9101 if (preview_image == (Image *) NULL)
9103 (void) FormatLocaleString(preview_image->filename,MagickPathExtent,"show:%s",
9105 status=WriteImage(image_info,preview_image,exception);
9106 preview_image=DestroyImage(preview_image);
9107 if (IfMagickFalse(status) )
9108 XNoticeWidget(display,windows,"Unable to show image preview",
9109 (*image)->filename);
9110 XDelay(display,1500);
9111 XSetCursorState(display,windows,MagickFalse);
9114 case ShowHistogramCommand:
9120 Show image histogram.
9122 XSetCursorState(display,windows,MagickTrue);
9123 XCheckRefreshWindows(display,windows);
9124 image_info->group=(ssize_t) windows->image.id;
9125 (void) DeleteImageProperty(*image,"label");
9126 (void) SetImageProperty(*image,"label","Histogram",exception);
9127 (void) AcquireUniqueFilename(filename);
9128 (void) FormatLocaleString((*image)->filename,MagickPathExtent,"histogram:%s",
9130 status=WriteImage(image_info,*image,exception);
9131 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
9132 histogram_image=ReadImage(image_info,exception);
9133 (void) RelinquishUniqueFileResource(filename);
9134 if (histogram_image == (Image *) NULL)
9136 (void) FormatLocaleString(histogram_image->filename,MagickPathExtent,
9137 "show:%s",filename);
9138 status=WriteImage(image_info,histogram_image,exception);
9139 histogram_image=DestroyImage(histogram_image);
9140 if (IfMagickFalse(status) )
9141 XNoticeWidget(display,windows,"Unable to show histogram",
9142 (*image)->filename);
9143 XDelay(display,1500);
9144 XSetCursorState(display,windows,MagickFalse);
9147 case ShowMatteCommand:
9152 if ((*image)->alpha_trait == UndefinedPixelTrait)
9154 XNoticeWidget(display,windows,
9155 "Image does not have any matte information",(*image)->filename);
9161 XSetCursorState(display,windows,MagickTrue);
9162 XCheckRefreshWindows(display,windows);
9163 image_info->group=(ssize_t) windows->image.id;
9164 (void) DeleteImageProperty(*image,"label");
9165 (void) SetImageProperty(*image,"label","Matte",exception);
9166 (void) AcquireUniqueFilename(filename);
9167 (void) FormatLocaleString((*image)->filename,MagickPathExtent,"matte:%s",
9169 status=WriteImage(image_info,*image,exception);
9170 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
9171 matte_image=ReadImage(image_info,exception);
9172 (void) RelinquishUniqueFileResource(filename);
9173 if (matte_image == (Image *) NULL)
9175 (void) FormatLocaleString(matte_image->filename,MagickPathExtent,"show:%s",
9177 status=WriteImage(image_info,matte_image,exception);
9178 matte_image=DestroyImage(matte_image);
9179 if (IfMagickFalse(status) )
9180 XNoticeWidget(display,windows,"Unable to show matte",
9181 (*image)->filename);
9182 XDelay(display,1500);
9183 XSetCursorState(display,windows,MagickFalse);
9186 case BackgroundCommand:
9191 status=XBackgroundImage(display,resource_info,windows,image,exception);
9192 if (IfMagickFalse(status) )
9194 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9195 if (nexus != (Image *) NULL)
9196 XClientMessage(display,windows->image.id,windows->im_protocols,
9197 windows->im_next_image,CurrentTime);
9200 case SlideShowCommand:
9203 delay[MagickPathExtent] = "5";
9206 Display next image after pausing.
9208 (void) XDialogWidget(display,windows,"Slide Show",
9209 "Pause how many 1/100ths of a second between images:",delay);
9212 resource_info->delay=StringToUnsignedLong(delay);
9213 XClientMessage(display,windows->image.id,windows->im_protocols,
9214 windows->im_next_image,CurrentTime);
9217 case PreferencesCommand:
9220 Set user preferences.
9222 status=XPreferencesWidget(display,resource_info,windows);
9223 if (IfMagickFalse(status) )
9225 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9226 if (nexus != (Image *) NULL)
9227 XClientMessage(display,windows->image.id,windows->im_protocols,
9228 windows->im_next_image,CurrentTime);
9234 User requested help.
9236 XTextViewWidget(display,resource_info,windows,MagickFalse,
9237 "Help Viewer - Display",DisplayHelp);
9240 case BrowseDocumentationCommand:
9250 Browse the ImageMagick documentation.
9252 root_window=XRootWindow(display,XDefaultScreen(display));
9253 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9254 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9255 if (mozilla_window != (Window) NULL)
9258 command[MagickPathExtent],
9262 Display documentation using Netscape remote control.
9264 url=GetMagickHomeURL();
9265 (void) FormatLocaleString(command,MagickPathExtent,
9266 "openurl(%s,new-tab)",url);
9267 url=DestroyString(url);
9268 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9269 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9270 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9271 XSetCursorState(display,windows,MagickFalse);
9274 XSetCursorState(display,windows,MagickTrue);
9275 XCheckRefreshWindows(display,windows);
9276 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9278 if (IfMagickFalse(status) )
9279 XNoticeWidget(display,windows,"Unable to browse documentation",
9281 XDelay(display,1500);
9282 XSetCursorState(display,windows,MagickFalse);
9285 case VersionCommand:
9287 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9288 GetMagickCopyright());
9291 case SaveToUndoBufferCommand:
9295 (void) XBell(display,0);
9299 image_info=DestroyImageInfo(image_info);
9304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9308 + X M a g n i f y I m a g e %
9312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9314 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9315 % The magnified portion is displayed in a separate window.
9317 % The format of the XMagnifyImage method is:
9319 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9320 % ExceptionInfo *exception)
9322 % A description of each parameter follows:
9324 % o display: Specifies a connection to an X server; returned from
9327 % o windows: Specifies a pointer to a XWindows structure.
9329 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9330 % the entire image is refreshed.
9332 % o exception: return any errors or warnings in this structure.
9335 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9336 ExceptionInfo *exception)
9339 text[MagickPathExtent];
9349 Update magnified image until the mouse button is released.
9351 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9355 windows->magnify.x=(int) windows->image.x+x;
9356 windows->magnify.y=(int) windows->image.y+y;
9360 Map and unmap Info widget as text cursor crosses its boundaries.
9362 if (IfMagickTrue(windows->info.mapped) )
9364 if ((x < (int) (windows->info.x+windows->info.width)) &&
9365 (y < (int) (windows->info.y+windows->info.height)))
9366 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9369 if ((x > (int) (windows->info.x+windows->info.width)) ||
9370 (y > (int) (windows->info.y+windows->info.height)))
9371 (void) XMapWindow(display,windows->info.id);
9372 if (IfMagickTrue(windows->info.mapped) )
9375 Display pointer position.
9377 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
9378 windows->magnify.x,windows->magnify.y);
9379 XInfoWidget(display,windows,text);
9382 Wait for next event.
9384 XScreenEvent(display,windows,event,exception);
9385 switch (event->type)
9392 User has finished magnifying image.
9411 Check boundary conditions.
9416 if (x >= (int) windows->image.width)
9417 x=(int) windows->image.width-1;
9421 if (y >= (int) windows->image.height)
9422 y=(int) windows->image.height-1;
9423 } while ((state & ExitState) == 0);
9425 Display magnified image.
9427 XSetCursorState(display,windows,MagickFalse);
9431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9435 + X M a g n i f y W i n d o w C o m m a n d %
9439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9441 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9442 % pixel as specified by the key symbol.
9444 % The format of the XMagnifyWindowCommand method is:
9446 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9447 % const MagickStatusType state,const KeySym key_symbol,
9448 % ExceptionInfo *exception)
9450 % A description of each parameter follows:
9452 % o display: Specifies a connection to an X server; returned from
9455 % o windows: Specifies a pointer to a XWindows structure.
9457 % o state: key mask.
9459 % o key_symbol: Specifies a KeySym which indicates which side of the image
9462 % o exception: return any errors or warnings in this structure.
9465 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9466 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9472 User specified a magnify factor or position.
9475 if ((state & Mod1Mask) != 0)
9477 switch ((int) key_symbol)
9481 (void) XWithdrawWindow(display,windows->magnify.id,
9482 windows->magnify.screen);
9488 windows->magnify.x=(int) windows->image.width/2;
9489 windows->magnify.y=(int) windows->image.height/2;
9495 if (windows->magnify.x > 0)
9496 windows->magnify.x-=quantum;
9502 if (windows->magnify.y > 0)
9503 windows->magnify.y-=quantum;
9509 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9510 windows->magnify.x+=quantum;
9516 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9517 windows->magnify.y+=quantum;
9531 windows->magnify.data=(key_symbol-XK_0);
9545 windows->magnify.data=(key_symbol-XK_KP_0);
9551 XMakeMagnifyImage(display,windows,exception);
9555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9559 + X M a k e P a n I m a g e %
9563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9565 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9568 % The format of the XMakePanImage method is:
9570 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9571 % XWindows *windows,Image *image,ExceptionInfo *exception)
9573 % A description of each parameter follows:
9575 % o display: Specifies a connection to an X server; returned from
9578 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9580 % o windows: Specifies a pointer to a XWindows structure.
9582 % o image: the image.
9584 % o exception: return any errors or warnings in this structure.
9587 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9588 XWindows *windows,Image *image,ExceptionInfo *exception)
9594 Create and display image for panning icon.
9596 XSetCursorState(display,windows,MagickTrue);
9597 XCheckRefreshWindows(display,windows);
9598 windows->pan.x=(int) windows->image.x;
9599 windows->pan.y=(int) windows->image.y;
9600 status=XMakeImage(display,resource_info,&windows->pan,image,
9601 windows->pan.width,windows->pan.height,exception);
9602 if (IfMagickFalse(status) )
9603 ThrowXWindowException(ResourceLimitError,
9604 "MemoryAllocationFailed",image->filename);
9605 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9606 windows->pan.pixmap);
9607 (void) XClearWindow(display,windows->pan.id);
9608 XDrawPanRectangle(display,windows);
9609 XSetCursorState(display,windows,MagickFalse);
9613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9617 + X M a t t a E d i t I m a g e %
9621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9623 % XMatteEditImage() allows the user to interactively change the Matte channel
9624 % of an image. If the image is PseudoClass it is promoted to DirectClass
9625 % before the matte information is stored.
9627 % The format of the XMatteEditImage method is:
9629 % MagickBooleanType XMatteEditImage(Display *display,
9630 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9631 % ExceptionInfo *exception)
9633 % A description of each parameter follows:
9635 % o display: Specifies a connection to an X server; returned from
9638 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9640 % o windows: Specifies a pointer to a XWindows structure.
9642 % o image: the image; returned from ReadImage.
9644 % o exception: return any errors or warnings in this structure.
9647 static MagickBooleanType XMatteEditImage(Display *display,
9648 XResourceInfo *resource_info,XWindows *windows,Image **image,
9649 ExceptionInfo *exception)
9652 matte[MagickPathExtent] = "0";
9667 static const ModeType
9668 MatteEditCommands[] =
9671 MatteEditBorderCommand,
9672 MatteEditFuzzCommand,
9673 MatteEditValueCommand,
9674 MatteEditUndoCommand,
9675 MatteEditHelpCommand,
9676 MatteEditDismissCommand
9680 method = PointMethod;
9683 border_color = { 0, 0, 0, 0, 0, 0 };
9686 command[MagickPathExtent],
9687 text[MagickPathExtent];
9719 (void) CloneString(&windows->command.name,"Matte Edit");
9720 windows->command.data=4;
9721 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9722 (void) XMapRaised(display,windows->command.id);
9723 XClientMessage(display,windows->image.id,windows->im_protocols,
9724 windows->im_update_widget,CurrentTime);
9728 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9729 resource_info->background_color,resource_info->foreground_color);
9730 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9732 Track pointer until button 1 is pressed.
9734 XQueryPosition(display,windows->image.id,&x,&y);
9735 (void) XSelectInput(display,windows->image.id,
9736 windows->image.attributes.event_mask | PointerMotionMask);
9740 if (IfMagickTrue(windows->info.mapped) )
9743 Display pointer position.
9745 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
9746 x+windows->image.x,y+windows->image.y);
9747 XInfoWidget(display,windows,text);
9750 Wait for next event.
9752 XScreenEvent(display,windows,&event,exception);
9753 if (event.xany.window == windows->command.id)
9756 Select a command from the Command widget.
9758 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9761 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9764 switch (MatteEditCommands[id])
9766 case MatteEditMethod:
9772 Select a method from the pop-up menu.
9774 methods=GetCommandOptions(MagickMethodOptions);
9775 if (methods == (char **) NULL)
9777 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9778 (const char **) methods,command);
9780 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9781 MagickFalse,methods[entry]);
9782 methods=DestroyStringList(methods);
9785 case MatteEditBorderCommand:
9788 *ColorMenu[MaxNumberPens];
9794 Initialize menu selections.
9796 for (i=0; i < (int) (MaxNumberPens-2); i++)
9797 ColorMenu[i]=resource_info->pen_colors[i];
9798 ColorMenu[MaxNumberPens-2]="Browser...";
9799 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9801 Select a pen color from the pop-up menu.
9803 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9804 (const char **) ColorMenu,command);
9807 if (pen_number == (MaxNumberPens-2))
9810 color_name[MagickPathExtent] = "gray";
9813 Select a pen color from a dialog.
9815 resource_info->pen_colors[pen_number]=color_name;
9816 XColorBrowserWidget(display,windows,"Select",color_name);
9817 if (*color_name == '\0')
9823 (void) XParseColor(display,windows->map_info->colormap,
9824 resource_info->pen_colors[pen_number],&border_color);
9827 case MatteEditFuzzCommand:
9830 fuzz[MagickPathExtent];
9845 Select a command from the pop-up menu.
9847 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9853 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9857 (void) CopyMagickString(fuzz,"20%",MagickPathExtent);
9858 (void) XDialogWidget(display,windows,"Ok",
9859 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9862 (void) ConcatenateMagickString(fuzz,"%",MagickPathExtent);
9863 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9867 case MatteEditValueCommand:
9870 message[MagickPathExtent];
9882 Select a command from the pop-up menu.
9884 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9890 (void) FormatLocaleString(matte,MagickPathExtent,QuantumFormat,
9892 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9893 (void) FormatLocaleString(matte,MagickPathExtent,QuantumFormat,
9894 (Quantum) TransparentAlpha);
9897 (void) FormatLocaleString(message,MagickPathExtent,
9898 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9900 (void) XDialogWidget(display,windows,"Matte",message,matte);
9905 case MatteEditUndoCommand:
9907 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9911 case MatteEditHelpCommand:
9913 XTextViewWidget(display,resource_info,windows,MagickFalse,
9914 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9917 case MatteEditDismissCommand:
9929 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9936 if (event.xbutton.button != Button1)
9938 if ((event.xbutton.window != windows->image.id) &&
9939 (event.xbutton.window != windows->magnify.id))
9946 (void) XMagickCommand(display,resource_info,windows,
9947 SaveToUndoBufferCommand,image,exception);
9948 state|=UpdateConfigurationState;
9953 if (event.xbutton.button != Button1)
9955 if ((event.xbutton.window != windows->image.id) &&
9956 (event.xbutton.window != windows->magnify.id))
9959 Update colormap information.
9963 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9964 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9965 XInfoWidget(display,windows,text);
9966 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9967 state&=(~UpdateConfigurationState);
9975 command[MagickPathExtent];
9980 if (event.xkey.window == windows->magnify.id)
9985 window=windows->magnify.id;
9986 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
9988 if (event.xkey.window != windows->image.id)
9991 Respond to a user key press.
9993 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
9994 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9995 switch ((int) key_symbol)
10009 XTextViewWidget(display,resource_info,windows,MagickFalse,
10010 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10015 (void) XBell(display,0);
10024 Map and unmap Info widget as cursor crosses its boundaries.
10028 if (IfMagickTrue(windows->info.mapped) )
10030 if ((x < (int) (windows->info.x+windows->info.width)) &&
10031 (y < (int) (windows->info.y+windows->info.height)))
10032 (void) XWithdrawWindow(display,windows->info.id,
10033 windows->info.screen);
10036 if ((x > (int) (windows->info.x+windows->info.width)) ||
10037 (y > (int) (windows->info.y+windows->info.height)))
10038 (void) XMapWindow(display,windows->info.id);
10044 if (event.xany.window == windows->magnify.id)
10046 x=windows->magnify.x-windows->image.x;
10047 y=windows->magnify.y-windows->image.y;
10051 if ((state & UpdateConfigurationState) != 0)
10061 Matte edit is relative to image configuration.
10063 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10065 XPutPixel(windows->image.ximage,x_offset,y_offset,
10066 windows->pixel_info->background_color.pixel);
10067 width=(unsigned int) (*image)->columns;
10068 height=(unsigned int) (*image)->rows;
10071 if (windows->image.crop_geometry != (char *) NULL)
10072 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10074 x_offset=(int) (width*(windows->image.x+x_offset)/
10075 windows->image.ximage->width+x);
10076 y_offset=(int) (height*(windows->image.y+y_offset)/
10077 windows->image.ximage->height+y);
10078 if ((x_offset < 0) || (y_offset < 0))
10080 if ((x_offset >= (int) (*image)->columns) ||
10081 (y_offset >= (int) (*image)->rows))
10083 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
10084 return(MagickFalse);
10085 if ((*image)->alpha_trait == UndefinedPixelTrait)
10086 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10087 image_view=AcquireAuthenticCacheView(*image,exception);
10094 Update matte information using point algorithm.
10096 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10097 (ssize_t) y_offset,1,1,exception);
10098 if (q == (Quantum *) NULL)
10100 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10101 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10104 case ReplaceMethod:
10111 Update matte information using replace algorithm.
10113 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
10114 x_offset,(ssize_t) y_offset,&target,exception);
10115 for (y=0; y < (int) (*image)->rows; y++)
10117 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10118 (*image)->columns,1,exception);
10119 if (q == (Quantum *) NULL)
10121 for (x=0; x < (int) (*image)->columns; x++)
10123 GetPixelInfoPixel(*image,q,&pixel);
10124 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10125 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10126 q+=GetPixelChannels(*image);
10128 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
10133 case FloodfillMethod:
10134 case FillToBorderMethod:
10146 Update matte information using floodfill algorithm.
10148 (void) GetOneVirtualPixelInfo(*image,
10149 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10150 y_offset,&target,exception);
10151 if (method == FillToBorderMethod)
10153 target.red=(double) ScaleShortToQuantum(
10155 target.green=(double) ScaleShortToQuantum(
10156 border_color.green);
10157 target.blue=(double) ScaleShortToQuantum(
10158 border_color.blue);
10160 draw_info=CloneDrawInfo(resource_info->image_info,
10161 (DrawInfo *) NULL);
10162 draw_info->fill.alpha=(double) ClampToQuantum(
10163 StringToDouble(matte,(char **) NULL));
10164 channel_mask=SetImageChannelMask(*image,AlphaChannel);
10165 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10166 x_offset,(ssize_t) y_offset,
10167 IsMagickFalse(method == FloodfillMethod),exception);
10168 (void) SetPixelChannelMask(*image,channel_mask);
10169 draw_info=DestroyDrawInfo(draw_info);
10175 Update matte information using reset algorithm.
10177 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
10178 return(MagickFalse);
10179 for (y=0; y < (int) (*image)->rows; y++)
10181 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10182 (*image)->columns,1,exception);
10183 if (q == (Quantum *) NULL)
10185 for (x=0; x < (int) (*image)->columns; x++)
10187 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10188 q+=GetPixelChannels(*image);
10190 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
10193 if (StringToLong(matte) == (long) OpaqueAlpha)
10194 (*image)->alpha_trait=UndefinedPixelTrait;
10198 image_view=DestroyCacheView(image_view);
10199 state&=(~UpdateConfigurationState);
10201 } while ((state & ExitState) == 0);
10202 (void) XSelectInput(display,windows->image.id,
10203 windows->image.attributes.event_mask);
10204 XSetCursorState(display,windows,MagickFalse);
10205 (void) XFreeCursor(display,cursor);
10206 return(MagickTrue);
10210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10214 + X O p e n I m a g e %
10218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10220 % XOpenImage() loads an image from a file.
10222 % The format of the XOpenImage method is:
10224 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10225 % XWindows *windows,const unsigned int command)
10227 % A description of each parameter follows:
10229 % o display: Specifies a connection to an X server; returned from
10232 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10234 % o windows: Specifies a pointer to a XWindows structure.
10236 % o command: A value other than zero indicates that the file is selected
10237 % from the command line argument list.
10240 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10241 XWindows *windows,const MagickBooleanType command)
10256 filename[MagickPathExtent] = "\0";
10259 Request file name from user.
10261 if (IfMagickFalse(command) )
10262 XFileBrowserWidget(display,windows,"Open",filename);
10278 Select next image from the command line.
10280 status=XGetCommand(display,windows->image.id,&files,&count);
10283 ThrowXWindowException(XServerError,"UnableToGetProperty","...");
10284 return((Image *) NULL);
10286 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10287 if (filelist == (char **) NULL)
10289 ThrowXWindowException(ResourceLimitError,
10290 "MemoryAllocationFailed","...");
10291 (void) XFreeStringList(files);
10292 return((Image *) NULL);
10295 for (i=1; i < count; i++)
10296 if (*files[i] != '-')
10297 filelist[j++]=files[i];
10298 filelist[j]=(char *) NULL;
10299 XListBrowserWidget(display,windows,&windows->widget,
10300 (const char **) filelist,"Load","Select Image to Load:",filename);
10301 filelist=(char **) RelinquishMagickMemory(filelist);
10302 (void) XFreeStringList(files);
10304 if (*filename == '\0')
10305 return((Image *) NULL);
10306 image_info=CloneImageInfo(resource_info->image_info);
10307 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10309 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
10310 exception=AcquireExceptionInfo();
10311 (void) SetImageInfo(image_info,0,exception);
10312 if (LocaleCompare(image_info->magick,"X") == 0)
10315 seconds[MagickPathExtent];
10318 User may want to delay the X server screen grab.
10320 (void) CopyMagickString(seconds,"0",MagickPathExtent);
10321 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10323 if (*seconds == '\0')
10324 return((Image *) NULL);
10325 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10327 magick_info=GetMagickInfo(image_info->magick,exception);
10328 if ((magick_info != (const MagickInfo *) NULL) &&
10329 GetMagickRawSupport(magick_info) == MagickTrue)
10332 geometry[MagickPathExtent];
10335 Request image size from the user.
10337 (void) CopyMagickString(geometry,"512x512",MagickPathExtent);
10338 if (image_info->size != (char *) NULL)
10339 (void) CopyMagickString(geometry,image_info->size,MagickPathExtent);
10340 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10342 (void) CloneString(&image_info->size,geometry);
10347 XSetCursorState(display,windows,MagickTrue);
10348 XCheckRefreshWindows(display,windows);
10349 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
10350 nexus=ReadImage(image_info,exception);
10351 CatchException(exception);
10352 XSetCursorState(display,windows,MagickFalse);
10353 if (nexus != (Image *) NULL)
10354 XClientMessage(display,windows->image.id,windows->im_protocols,
10355 windows->im_next_image,CurrentTime);
10363 Unknown image format.
10365 text=FileToString(filename,~0UL,exception);
10366 if (text == (char *) NULL)
10367 return((Image *) NULL);
10368 textlist=StringToList(text);
10369 if (textlist != (char **) NULL)
10372 title[MagickPathExtent];
10377 (void) FormatLocaleString(title,MagickPathExtent,
10378 "Unknown format: %s",filename);
10379 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10380 (const char **) textlist);
10381 for (i=0; textlist[i] != (char *) NULL; i++)
10382 textlist[i]=DestroyString(textlist[i]);
10383 textlist=(char **) RelinquishMagickMemory(textlist);
10385 text=DestroyString(text);
10387 exception=DestroyExceptionInfo(exception);
10388 image_info=DestroyImageInfo(image_info);
10393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10397 + X P a n I m a g e %
10401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10403 % XPanImage() pans the image until the mouse button is released.
10405 % The format of the XPanImage method is:
10407 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10408 % ExceptionInfo *exception)
10410 % A description of each parameter follows:
10412 % o display: Specifies a connection to an X server; returned from
10415 % o windows: Specifies a pointer to a XWindows structure.
10417 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10418 % the entire image is refreshed.
10420 % o exception: return any errors or warnings in this structure.
10423 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10424 ExceptionInfo *exception)
10427 text[MagickPathExtent];
10445 if ((windows->image.ximage->width > (int) windows->image.width) &&
10446 (windows->image.ximage->height > (int) windows->image.height))
10447 cursor=XCreateFontCursor(display,XC_fleur);
10449 if (windows->image.ximage->width > (int) windows->image.width)
10450 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10452 if (windows->image.ximage->height > (int) windows->image.height)
10453 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10455 cursor=XCreateFontCursor(display,XC_arrow);
10456 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10458 Pan image as pointer moves until the mouse button is released.
10460 x_factor=(double) windows->image.ximage->width/windows->pan.width;
10461 y_factor=(double) windows->image.ximage->height/windows->pan.height;
10462 pan_info.width=windows->pan.width*windows->image.width/
10463 windows->image.ximage->width;
10464 pan_info.height=windows->pan.height*windows->image.height/
10465 windows->image.ximage->height;
10468 state=UpdateConfigurationState;
10471 switch (event->type)
10476 User choose an initial pan location.
10478 pan_info.x=(ssize_t) event->xbutton.x;
10479 pan_info.y=(ssize_t) event->xbutton.y;
10480 state|=UpdateConfigurationState;
10483 case ButtonRelease:
10486 User has finished panning the image.
10488 pan_info.x=(ssize_t) event->xbutton.x;
10489 pan_info.y=(ssize_t) event->xbutton.y;
10490 state|=UpdateConfigurationState | ExitState;
10495 pan_info.x=(ssize_t) event->xmotion.x;
10496 pan_info.y=(ssize_t) event->xmotion.y;
10497 state|=UpdateConfigurationState;
10502 if ((state & UpdateConfigurationState) != 0)
10505 Check boundary conditions.
10507 if (pan_info.x < (ssize_t) (pan_info.width/2))
10510 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10511 if (pan_info.x < 0)
10514 if ((int) (pan_info.x+windows->image.width) >
10515 windows->image.ximage->width)
10516 pan_info.x=(ssize_t)
10517 (windows->image.ximage->width-windows->image.width);
10518 if (pan_info.y < (ssize_t) (pan_info.height/2))
10521 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10522 if (pan_info.y < 0)
10525 if ((int) (pan_info.y+windows->image.height) >
10526 windows->image.ximage->height)
10527 pan_info.y=(ssize_t)
10528 (windows->image.ximage->height-windows->image.height);
10529 if ((windows->image.x != (int) pan_info.x) ||
10530 (windows->image.y != (int) pan_info.y))
10533 Display image pan offset.
10535 windows->image.x=(int) pan_info.x;
10536 windows->image.y=(int) pan_info.y;
10537 (void) FormatLocaleString(text,MagickPathExtent," %ux%u%+d%+d ",
10538 windows->image.width,windows->image.height,windows->image.x,
10540 XInfoWidget(display,windows,text);
10542 Refresh Image window.
10544 XDrawPanRectangle(display,windows);
10545 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10547 state&=(~UpdateConfigurationState);
10550 Wait for next event.
10552 if ((state & ExitState) == 0)
10553 XScreenEvent(display,windows,event,exception);
10554 } while ((state & ExitState) == 0);
10558 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10559 (void) XFreeCursor(display,cursor);
10560 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10568 + X P a s t e I m a g e %
10572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10574 % XPasteImage() pastes an image previously saved with XCropImage in the X
10575 % window image at a location the user chooses with the pointer.
10577 % The format of the XPasteImage method is:
10579 % MagickBooleanType XPasteImage(Display *display,
10580 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10581 % ExceptionInfo *exception)
10583 % A description of each parameter follows:
10585 % o display: Specifies a connection to an X server; returned from
10588 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10590 % o windows: Specifies a pointer to a XWindows structure.
10592 % o image: the image; returned from ReadImage.
10594 % o exception: return any errors or warnings in this structure.
10597 static MagickBooleanType XPasteImage(Display *display,
10598 XResourceInfo *resource_info,XWindows *windows,Image *image,
10599 ExceptionInfo *exception)
10610 static const ModeType
10613 PasteOperatorsCommand,
10615 PasteDismissCommand
10618 static CompositeOperator
10619 compose = CopyCompositeOp;
10622 text[MagickPathExtent];
10656 if (resource_info->copy_image == (Image *) NULL)
10657 return(MagickFalse);
10658 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10660 Map Command widget.
10662 (void) CloneString(&windows->command.name,"Paste");
10663 windows->command.data=1;
10664 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10665 (void) XMapRaised(display,windows->command.id);
10666 XClientMessage(display,windows->image.id,windows->im_protocols,
10667 windows->im_update_widget,CurrentTime);
10669 Track pointer until button 1 is pressed.
10671 XSetCursorState(display,windows,MagickFalse);
10672 XQueryPosition(display,windows->image.id,&x,&y);
10673 (void) XSelectInput(display,windows->image.id,
10674 windows->image.attributes.event_mask | PointerMotionMask);
10675 paste_info.x=(ssize_t) windows->image.x+x;
10676 paste_info.y=(ssize_t) windows->image.y+y;
10677 paste_info.width=0;
10678 paste_info.height=0;
10679 cursor=XCreateFontCursor(display,XC_ul_angle);
10680 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10681 state=DefaultState;
10684 if (IfMagickTrue(windows->info.mapped) )
10687 Display pointer position.
10689 (void) FormatLocaleString(text,MagickPathExtent," %+ld%+ld ",
10690 (long) paste_info.x,(long) paste_info.y);
10691 XInfoWidget(display,windows,text);
10693 highlight_info=paste_info;
10694 highlight_info.x=paste_info.x-windows->image.x;
10695 highlight_info.y=paste_info.y-windows->image.y;
10696 XHighlightRectangle(display,windows->image.id,
10697 windows->image.highlight_context,&highlight_info);
10699 Wait for next event.
10701 XScreenEvent(display,windows,&event,exception);
10702 XHighlightRectangle(display,windows->image.id,
10703 windows->image.highlight_context,&highlight_info);
10704 if (event.xany.window == windows->command.id)
10707 Select a command from the Command widget.
10709 id=XCommandWidget(display,windows,PasteMenu,&event);
10712 switch (PasteCommands[id])
10714 case PasteOperatorsCommand:
10717 command[MagickPathExtent],
10721 Select a command from the pop-up menu.
10723 operators=GetCommandOptions(MagickComposeOptions);
10724 if (operators == (char **) NULL)
10726 entry=XMenuWidget(display,windows,PasteMenu[id],
10727 (const char **) operators,command);
10729 compose=(CompositeOperator) ParseCommandOption(
10730 MagickComposeOptions,MagickFalse,operators[entry]);
10731 operators=DestroyStringList(operators);
10734 case PasteHelpCommand:
10736 XTextViewWidget(display,resource_info,windows,MagickFalse,
10737 "Help Viewer - Image Composite",ImagePasteHelp);
10740 case PasteDismissCommand:
10745 state|=EscapeState;
10754 switch (event.type)
10758 if (IfMagickTrue(image->debug) )
10759 (void) LogMagickEvent(X11Event,GetMagickModule(),
10760 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10761 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10762 if (event.xbutton.button != Button1)
10764 if (event.xbutton.window != windows->image.id)
10767 Paste rectangle is relative to image configuration.
10769 width=(unsigned int) image->columns;
10770 height=(unsigned int) image->rows;
10773 if (windows->image.crop_geometry != (char *) NULL)
10774 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10776 scale_factor=(double) windows->image.ximage->width/width;
10777 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10778 scale_factor=(double) windows->image.ximage->height/height;
10779 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10780 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10781 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10782 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10785 case ButtonRelease:
10787 if (IfMagickTrue(image->debug) )
10788 (void) LogMagickEvent(X11Event,GetMagickModule(),
10789 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10790 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10791 if (event.xbutton.button != Button1)
10793 if (event.xbutton.window != windows->image.id)
10795 if ((paste_info.width != 0) && (paste_info.height != 0))
10798 User has selected the location of the paste image.
10800 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10801 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10811 command[MagickPathExtent];
10819 if (event.xkey.window != windows->image.id)
10822 Respond to a user key press.
10824 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10825 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10826 *(command+length)='\0';
10827 if (IfMagickTrue(image->debug) )
10828 (void) LogMagickEvent(X11Event,GetMagickModule(),
10829 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10830 switch ((int) key_symbol)
10838 paste_image=DestroyImage(paste_image);
10839 state|=EscapeState;
10846 (void) XSetFunction(display,windows->image.highlight_context,
10848 XTextViewWidget(display,resource_info,windows,MagickFalse,
10849 "Help Viewer - Image Composite",ImagePasteHelp);
10850 (void) XSetFunction(display,windows->image.highlight_context,
10856 (void) XBell(display,0);
10865 Map and unmap Info widget as text cursor crosses its boundaries.
10869 if (IfMagickTrue(windows->info.mapped) )
10871 if ((x < (int) (windows->info.x+windows->info.width)) &&
10872 (y < (int) (windows->info.y+windows->info.height)))
10873 (void) XWithdrawWindow(display,windows->info.id,
10874 windows->info.screen);
10877 if ((x > (int) (windows->info.x+windows->info.width)) ||
10878 (y > (int) (windows->info.y+windows->info.height)))
10879 (void) XMapWindow(display,windows->info.id);
10880 paste_info.x=(ssize_t) windows->image.x+x;
10881 paste_info.y=(ssize_t) windows->image.y+y;
10886 if (IfMagickTrue(image->debug) )
10887 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10892 } while ((state & ExitState) == 0);
10893 (void) XSelectInput(display,windows->image.id,
10894 windows->image.attributes.event_mask);
10895 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10896 XSetCursorState(display,windows,MagickFalse);
10897 (void) XFreeCursor(display,cursor);
10898 if ((state & EscapeState) != 0)
10899 return(MagickTrue);
10901 Image pasting is relative to image configuration.
10903 XSetCursorState(display,windows,MagickTrue);
10904 XCheckRefreshWindows(display,windows);
10905 width=(unsigned int) image->columns;
10906 height=(unsigned int) image->rows;
10909 if (windows->image.crop_geometry != (char *) NULL)
10910 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10911 scale_factor=(double) width/windows->image.ximage->width;
10913 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10914 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10915 scale_factor=(double) height/windows->image.ximage->height;
10917 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10918 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10920 Paste image with X Image window.
10922 (void) CompositeImage(image,paste_image,compose,MagickTrue,paste_info.x,
10923 paste_info.y,exception);
10924 paste_image=DestroyImage(paste_image);
10925 XSetCursorState(display,windows,MagickFalse);
10927 Update image colormap.
10929 XConfigureImageColormap(display,resource_info,windows,image,exception);
10930 (void) XConfigureImage(display,resource_info,windows,image,exception);
10931 return(MagickTrue);
10935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10939 + X P r i n t I m a g e %
10943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10945 % XPrintImage() prints an image to a Postscript printer.
10947 % The format of the XPrintImage method is:
10949 % MagickBooleanType XPrintImage(Display *display,
10950 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10951 % ExceptionInfo *exception)
10953 % A description of each parameter follows:
10955 % o display: Specifies a connection to an X server; returned from
10958 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10960 % o windows: Specifies a pointer to a XWindows structure.
10962 % o image: the image.
10964 % o exception: return any errors or warnings in this structure.
10967 static MagickBooleanType XPrintImage(Display *display,
10968 XResourceInfo *resource_info,XWindows *windows,Image *image,
10969 ExceptionInfo *exception)
10972 filename[MagickPathExtent],
10973 geometry[MagickPathExtent];
10985 Request Postscript page geometry from user.
10987 image_info=CloneImageInfo(resource_info->image_info);
10988 (void) FormatLocaleString(geometry,MagickPathExtent,"Letter");
10989 if (image_info->page != (char *) NULL)
10990 (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
10991 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
10992 "Select Postscript Page Geometry:",geometry);
10993 if (*geometry == '\0')
10994 return(MagickTrue);
10995 image_info->page=GetPageGeometry(geometry);
10997 Apply image transforms.
10999 XSetCursorState(display,windows,MagickTrue);
11000 XCheckRefreshWindows(display,windows);
11001 print_image=CloneImage(image,0,0,MagickTrue,exception);
11002 if (print_image == (Image *) NULL)
11003 return(MagickFalse);
11004 (void) FormatLocaleString(geometry,MagickPathExtent,"%dx%d!",
11005 windows->image.ximage->width,windows->image.ximage->height);
11006 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11011 (void) AcquireUniqueFilename(filename);
11012 (void) FormatLocaleString(print_image->filename,MagickPathExtent,"print:%s",
11014 status=WriteImage(image_info,print_image,exception);
11015 (void) RelinquishUniqueFileResource(filename);
11016 print_image=DestroyImage(print_image);
11017 image_info=DestroyImageInfo(image_info);
11018 XSetCursorState(display,windows,MagickFalse);
11019 return(IsMagickTrue(status));
11023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11027 + X R O I I m a g e %
11031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11033 % XROIImage() applies an image processing technique to a region of interest.
11035 % The format of the XROIImage method is:
11037 % MagickBooleanType XROIImage(Display *display,
11038 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11039 % ExceptionInfo *exception)
11041 % A description of each parameter follows:
11043 % o display: Specifies a connection to an X server; returned from
11046 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11048 % o windows: Specifies a pointer to a XWindows structure.
11050 % o image: the image; returned from ReadImage.
11052 % o exception: return any errors or warnings in this structure.
11055 static MagickBooleanType XROIImage(Display *display,
11056 XResourceInfo *resource_info,XWindows *windows,Image **image,
11057 ExceptionInfo *exception)
11059 #define ApplyMenus 7
11109 "Contrast Stretch...",
11110 "Sigmoidal Contrast...",
11144 "Charcoal Draw...",
11147 *MiscellanyMenu[] =
11158 **Menus[ApplyMenus] =
11169 static const CommandType
11192 TransformCommands[] =
11196 RotateRightCommand,
11199 EnhanceCommands[] =
11207 ContrastStretchCommand,
11208 SigmoidalContrastCommand,
11216 EffectsCommands[] =
11220 ReduceNoiseCommand,
11239 CharcoalDrawCommand
11241 MiscellanyCommands[] =
11245 ShowPreviewCommand,
11246 ShowHistogramCommand,
11255 static const CommandType
11256 *Commands[ApplyMenus] =
11268 command[MagickPathExtent],
11269 text[MagickPathExtent];
11289 MagickProgressMonitor
11308 Map Command widget.
11310 (void) CloneString(&windows->command.name,"ROI");
11311 windows->command.data=0;
11312 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11313 (void) XMapRaised(display,windows->command.id);
11314 XClientMessage(display,windows->image.id,windows->im_protocols,
11315 windows->im_update_widget,CurrentTime);
11317 Track pointer until button 1 is pressed.
11319 XQueryPosition(display,windows->image.id,&x,&y);
11320 (void) XSelectInput(display,windows->image.id,
11321 windows->image.attributes.event_mask | PointerMotionMask);
11322 roi_info.x=(ssize_t) windows->image.x+x;
11323 roi_info.y=(ssize_t) windows->image.y+y;
11326 cursor=XCreateFontCursor(display,XC_fleur);
11327 state=DefaultState;
11330 if (IfMagickTrue(windows->info.mapped) )
11333 Display pointer position.
11335 (void) FormatLocaleString(text,MagickPathExtent," %+ld%+ld ",
11336 (long) roi_info.x,(long) roi_info.y);
11337 XInfoWidget(display,windows,text);
11340 Wait for next event.
11342 XScreenEvent(display,windows,&event,exception);
11343 if (event.xany.window == windows->command.id)
11346 Select a command from the Command widget.
11348 id=XCommandWidget(display,windows,ROIMenu,&event);
11351 switch (ROICommands[id])
11353 case ROIHelpCommand:
11355 XTextViewWidget(display,resource_info,windows,MagickFalse,
11356 "Help Viewer - Region of Interest",ImageROIHelp);
11359 case ROIDismissCommand:
11364 state|=EscapeState;
11373 switch (event.type)
11377 if (event.xbutton.button != Button1)
11379 if (event.xbutton.window != windows->image.id)
11382 Note first corner of region of interest rectangle-- exit loop.
11384 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11385 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11386 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11390 case ButtonRelease:
11399 if (event.xkey.window != windows->image.id)
11402 Respond to a user key press.
11404 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11405 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11406 switch ((int) key_symbol)
11414 state|=EscapeState;
11421 XTextViewWidget(display,resource_info,windows,MagickFalse,
11422 "Help Viewer - Region of Interest",ImageROIHelp);
11427 (void) XBell(display,0);
11436 Map and unmap Info widget as text cursor crosses its boundaries.
11440 if (IfMagickTrue(windows->info.mapped) )
11442 if ((x < (int) (windows->info.x+windows->info.width)) &&
11443 (y < (int) (windows->info.y+windows->info.height)))
11444 (void) XWithdrawWindow(display,windows->info.id,
11445 windows->info.screen);
11448 if ((x > (int) (windows->info.x+windows->info.width)) ||
11449 (y > (int) (windows->info.y+windows->info.height)))
11450 (void) XMapWindow(display,windows->info.id);
11451 roi_info.x=(ssize_t) windows->image.x+x;
11452 roi_info.y=(ssize_t) windows->image.y+y;
11458 } while ((state & ExitState) == 0);
11459 (void) XSelectInput(display,windows->image.id,
11460 windows->image.attributes.event_mask);
11461 if ((state & EscapeState) != 0)
11464 User want to exit without region of interest.
11466 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11467 (void) XFreeCursor(display,cursor);
11468 return(MagickTrue);
11470 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11474 Size rectangle as pointer moves until the mouse button is released.
11476 x=(int) roi_info.x;
11477 y=(int) roi_info.y;
11480 state=DefaultState;
11483 highlight_info=roi_info;
11484 highlight_info.x=roi_info.x-windows->image.x;
11485 highlight_info.y=roi_info.y-windows->image.y;
11486 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11489 Display info and draw region of interest rectangle.
11491 if (IfMagickFalse(windows->info.mapped) )
11492 (void) XMapWindow(display,windows->info.id);
11493 (void) FormatLocaleString(text,MagickPathExtent,
11494 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11495 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11496 XInfoWidget(display,windows,text);
11497 XHighlightRectangle(display,windows->image.id,
11498 windows->image.highlight_context,&highlight_info);
11501 if (IfMagickTrue(windows->info.mapped) )
11502 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11504 Wait for next event.
11506 XScreenEvent(display,windows,&event,exception);
11507 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11508 XHighlightRectangle(display,windows->image.id,
11509 windows->image.highlight_context,&highlight_info);
11510 switch (event.type)
11514 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11515 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11518 case ButtonRelease:
11521 User has committed to region of interest rectangle.
11523 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11524 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11525 XSetCursorState(display,windows,MagickFalse);
11527 if (LocaleCompare(windows->command.name,"Apply") == 0)
11529 (void) CloneString(&windows->command.name,"Apply");
11530 windows->command.data=ApplyMenus;
11531 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11538 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11539 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11544 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11545 ((state & ExitState) != 0))
11548 Check boundary conditions.
11550 if (roi_info.x < 0)
11553 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11554 roi_info.x=(ssize_t) windows->image.ximage->width;
11555 if ((int) roi_info.x < x)
11556 roi_info.width=(unsigned int) (x-roi_info.x);
11559 roi_info.width=(unsigned int) (roi_info.x-x);
11560 roi_info.x=(ssize_t) x;
11562 if (roi_info.y < 0)
11565 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11566 roi_info.y=(ssize_t) windows->image.ximage->height;
11567 if ((int) roi_info.y < y)
11568 roi_info.height=(unsigned int) (y-roi_info.y);
11571 roi_info.height=(unsigned int) (roi_info.y-y);
11572 roi_info.y=(ssize_t) y;
11575 } while ((state & ExitState) == 0);
11577 Wait for user to grab a corner of the rectangle or press return.
11579 state=DefaultState;
11580 command_type=NullCommand;
11583 (void) XMapWindow(display,windows->info.id);
11586 if (IfMagickTrue(windows->info.mapped) )
11589 Display pointer position.
11591 (void) FormatLocaleString(text,MagickPathExtent,
11592 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11593 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11594 XInfoWidget(display,windows,text);
11596 highlight_info=roi_info;
11597 highlight_info.x=roi_info.x-windows->image.x;
11598 highlight_info.y=roi_info.y-windows->image.y;
11599 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11601 state|=EscapeState;
11605 if ((state & UpdateRegionState) != 0)
11607 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11608 switch (command_type)
11613 (void) XMagickCommand(display,resource_info,windows,command_type,
11620 Region of interest is relative to image configuration.
11622 progress_monitor=SetImageProgressMonitor(*image,
11623 (MagickProgressMonitor) NULL,(*image)->client_data);
11624 crop_info=roi_info;
11625 width=(unsigned int) (*image)->columns;
11626 height=(unsigned int) (*image)->rows;
11629 if (windows->image.crop_geometry != (char *) NULL)
11630 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11632 scale_factor=(double) width/windows->image.ximage->width;
11634 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11635 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11636 scale_factor=(double)
11637 height/windows->image.ximage->height;
11639 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11640 crop_info.height=(unsigned int)
11641 (scale_factor*crop_info.height+0.5);
11642 roi_image=CropImage(*image,&crop_info,exception);
11643 (void) SetImageProgressMonitor(*image,progress_monitor,
11644 (*image)->client_data);
11645 if (roi_image == (Image *) NULL)
11648 Apply image processing technique to the region of interest.
11650 windows->image.orphan=MagickTrue;
11651 (void) XMagickCommand(display,resource_info,windows,command_type,
11652 &roi_image,exception);
11653 progress_monitor=SetImageProgressMonitor(*image,
11654 (MagickProgressMonitor) NULL,(*image)->client_data);
11655 (void) XMagickCommand(display,resource_info,windows,
11656 SaveToUndoBufferCommand,image,exception);
11657 windows->image.orphan=MagickFalse;
11658 (void) CompositeImage(*image,roi_image,CopyCompositeOp,
11659 MagickTrue,crop_info.x,crop_info.y,exception);
11660 roi_image=DestroyImage(roi_image);
11661 (void) SetImageProgressMonitor(*image,progress_monitor,
11662 (*image)->client_data);
11666 if (command_type != InfoCommand)
11668 XConfigureImageColormap(display,resource_info,windows,*image,
11670 (void) XConfigureImage(display,resource_info,windows,*image,
11673 XCheckRefreshWindows(display,windows);
11674 XInfoWidget(display,windows,text);
11675 (void) XSetFunction(display,windows->image.highlight_context,
11677 state&=(~UpdateRegionState);
11679 XHighlightRectangle(display,windows->image.id,
11680 windows->image.highlight_context,&highlight_info);
11681 XScreenEvent(display,windows,&event,exception);
11682 if (event.xany.window == windows->command.id)
11685 Select a command from the Command widget.
11687 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11688 command_type=NullCommand;
11689 id=XCommandWidget(display,windows,ApplyMenu,&event);
11692 (void) CopyMagickString(command,ApplyMenu[id],MagickPathExtent);
11693 command_type=ApplyCommands[id];
11694 if (id < ApplyMenus)
11697 Select a command from a pop-up menu.
11699 entry=XMenuWidget(display,windows,ApplyMenu[id],
11700 (const char **) Menus[id],command);
11703 (void) CopyMagickString(command,Menus[id][entry],
11705 command_type=Commands[id][entry];
11709 (void) XSetFunction(display,windows->image.highlight_context,
11711 XHighlightRectangle(display,windows->image.id,
11712 windows->image.highlight_context,&highlight_info);
11713 if (command_type == HelpCommand)
11715 (void) XSetFunction(display,windows->image.highlight_context,
11717 XTextViewWidget(display,resource_info,windows,MagickFalse,
11718 "Help Viewer - Region of Interest",ImageROIHelp);
11719 (void) XSetFunction(display,windows->image.highlight_context,
11723 if (command_type == QuitCommand)
11728 state|=EscapeState;
11732 if (command_type != NullCommand)
11733 state|=UpdateRegionState;
11736 XHighlightRectangle(display,windows->image.id,
11737 windows->image.highlight_context,&highlight_info);
11738 switch (event.type)
11742 x=windows->image.x;
11743 y=windows->image.y;
11744 if (event.xbutton.button != Button1)
11746 if (event.xbutton.window != windows->image.id)
11748 x=windows->image.x+event.xbutton.x;
11749 y=windows->image.y+event.xbutton.y;
11750 if ((x < (int) (roi_info.x+RoiDelta)) &&
11751 (x > (int) (roi_info.x-RoiDelta)) &&
11752 (y < (int) (roi_info.y+RoiDelta)) &&
11753 (y > (int) (roi_info.y-RoiDelta)))
11755 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11756 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11757 state|=UpdateConfigurationState;
11760 if ((x < (int) (roi_info.x+RoiDelta)) &&
11761 (x > (int) (roi_info.x-RoiDelta)) &&
11762 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11763 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11765 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11766 state|=UpdateConfigurationState;
11769 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11770 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11771 (y < (int) (roi_info.y+RoiDelta)) &&
11772 (y > (int) (roi_info.y-RoiDelta)))
11774 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11775 state|=UpdateConfigurationState;
11778 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11779 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11780 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11781 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11783 state|=UpdateConfigurationState;
11787 case ButtonRelease:
11789 if (event.xbutton.window == windows->pan.id)
11790 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11791 (highlight_info.y != crop_info.y-windows->image.y))
11792 XHighlightRectangle(display,windows->image.id,
11793 windows->image.highlight_context,&highlight_info);
11794 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11795 event.xbutton.time);
11800 if (event.xexpose.window == windows->image.id)
11801 if (event.xexpose.count == 0)
11803 event.xexpose.x=(int) highlight_info.x;
11804 event.xexpose.y=(int) highlight_info.y;
11805 event.xexpose.width=(int) highlight_info.width;
11806 event.xexpose.height=(int) highlight_info.height;
11807 XRefreshWindow(display,&windows->image,&event);
11809 if (event.xexpose.window == windows->info.id)
11810 if (event.xexpose.count == 0)
11811 XInfoWidget(display,windows,text);
11819 if (event.xkey.window != windows->image.id)
11822 Respond to a user key press.
11824 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11825 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11826 switch ((int) key_symbol)
11833 state|=EscapeState;
11842 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11843 roi_info.y=(ssize_t) (windows->image.height/2L-
11844 roi_info.height/2L);
11876 (void) XSetFunction(display,windows->image.highlight_context,
11878 XTextViewWidget(display,resource_info,windows,MagickFalse,
11879 "Help Viewer - Region of Interest",ImageROIHelp);
11880 (void) XSetFunction(display,windows->image.highlight_context,
11886 command_type=XImageWindowCommand(display,resource_info,windows,
11887 event.xkey.state,key_symbol,image,exception);
11888 if (command_type != NullCommand)
11889 state|=UpdateRegionState;
11893 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11901 if (event.xbutton.window != windows->image.id)
11904 Map and unmap Info widget as text cursor crosses its boundaries.
11908 if (IfMagickTrue(windows->info.mapped) )
11910 if ((x < (int) (windows->info.x+windows->info.width)) &&
11911 (y < (int) (windows->info.y+windows->info.height)))
11912 (void) XWithdrawWindow(display,windows->info.id,
11913 windows->info.screen);
11916 if ((x > (int) (windows->info.x+windows->info.width)) ||
11917 (y > (int) (windows->info.y+windows->info.height)))
11918 (void) XMapWindow(display,windows->info.id);
11919 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11920 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11923 case SelectionRequest:
11928 XSelectionRequestEvent
11932 Set primary selection.
11934 (void) FormatLocaleString(text,MagickPathExtent,
11935 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11936 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11937 request=(&(event.xselectionrequest));
11938 (void) XChangeProperty(request->display,request->requestor,
11939 request->property,request->target,8,PropModeReplace,
11940 (unsigned char *) text,(int) strlen(text));
11941 notify.type=SelectionNotify;
11942 notify.display=request->display;
11943 notify.requestor=request->requestor;
11944 notify.selection=request->selection;
11945 notify.target=request->target;
11946 notify.time=request->time;
11947 if (request->property == None)
11948 notify.property=request->target;
11950 notify.property=request->property;
11951 (void) XSendEvent(request->display,request->requestor,False,0,
11952 (XEvent *) ¬ify);
11957 if ((state & UpdateConfigurationState) != 0)
11959 (void) XPutBackEvent(display,&event);
11960 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11963 } while ((state & ExitState) == 0);
11964 } while ((state & ExitState) == 0);
11965 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11966 XSetCursorState(display,windows,MagickFalse);
11967 if ((state & EscapeState) != 0)
11968 return(MagickTrue);
11969 return(MagickTrue);
11973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11977 + X R o t a t e I m a g e %
11981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11983 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11984 % rotation angle is computed from the slope of a line drawn by the user.
11986 % The format of the XRotateImage method is:
11988 % MagickBooleanType XRotateImage(Display *display,
11989 % XResourceInfo *resource_info,XWindows *windows,double degrees,
11990 % Image **image,ExceptionInfo *exception)
11992 % A description of each parameter follows:
11994 % o display: Specifies a connection to an X server; returned from
11997 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11999 % o windows: Specifies a pointer to a XWindows structure.
12001 % o degrees: Specifies the number of degrees to rotate the image.
12003 % o image: the image.
12005 % o exception: return any errors or warnings in this structure.
12008 static MagickBooleanType XRotateImage(Display *display,
12009 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12010 ExceptionInfo *exception)
12023 direction = HorizontalRotateCommand;
12025 static const ModeType
12026 DirectionCommands[] =
12028 HorizontalRotateCommand,
12029 VerticalRotateCommand
12033 RotateColorCommand,
12034 RotateDirectionCommand,
12036 RotateDismissCommand
12039 static unsigned int
12043 command[MagickPathExtent],
12044 text[MagickPathExtent];
12055 normalized_degrees;
12065 if (degrees == 0.0)
12080 Map Command widget.
12082 (void) CloneString(&windows->command.name,"Rotate");
12083 windows->command.data=2;
12084 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12085 (void) XMapRaised(display,windows->command.id);
12086 XClientMessage(display,windows->image.id,windows->im_protocols,
12087 windows->im_update_widget,CurrentTime);
12089 Wait for first button press.
12091 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12092 XQueryPosition(display,windows->image.id,&x,&y);
12097 state=DefaultState;
12100 XHighlightLine(display,windows->image.id,
12101 windows->image.highlight_context,&rotate_info);
12103 Wait for next event.
12105 XScreenEvent(display,windows,&event,exception);
12106 XHighlightLine(display,windows->image.id,
12107 windows->image.highlight_context,&rotate_info);
12108 if (event.xany.window == windows->command.id)
12111 Select a command from the Command widget.
12113 id=XCommandWidget(display,windows,RotateMenu,&event);
12116 (void) XSetFunction(display,windows->image.highlight_context,
12118 switch (RotateCommands[id])
12120 case RotateColorCommand:
12123 *ColorMenu[MaxNumberPens];
12132 Initialize menu selections.
12134 for (i=0; i < (int) (MaxNumberPens-2); i++)
12135 ColorMenu[i]=resource_info->pen_colors[i];
12136 ColorMenu[MaxNumberPens-2]="Browser...";
12137 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12139 Select a pen color from the pop-up menu.
12141 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12142 (const char **) ColorMenu,command);
12143 if (pen_number < 0)
12145 if (pen_number == (MaxNumberPens-2))
12148 color_name[MagickPathExtent] = "gray";
12151 Select a pen color from a dialog.
12153 resource_info->pen_colors[pen_number]=color_name;
12154 XColorBrowserWidget(display,windows,"Select",color_name);
12155 if (*color_name == '\0')
12161 (void) XParseColor(display,windows->map_info->colormap,
12162 resource_info->pen_colors[pen_number],&color);
12163 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12164 (unsigned int) MaxColors,&color);
12165 windows->pixel_info->pen_colors[pen_number]=color;
12166 pen_id=(unsigned int) pen_number;
12169 case RotateDirectionCommand:
12180 Select a command from the pop-up menu.
12182 id=XMenuWidget(display,windows,RotateMenu[id],
12183 Directions,command);
12185 direction=DirectionCommands[id];
12188 case RotateHelpCommand:
12190 XTextViewWidget(display,resource_info,windows,MagickFalse,
12191 "Help Viewer - Image Rotation",ImageRotateHelp);
12194 case RotateDismissCommand:
12199 state|=EscapeState;
12206 (void) XSetFunction(display,windows->image.highlight_context,
12210 switch (event.type)
12214 if (event.xbutton.button != Button1)
12216 if (event.xbutton.window != windows->image.id)
12221 (void) XSetFunction(display,windows->image.highlight_context,
12223 rotate_info.x1=event.xbutton.x;
12224 rotate_info.y1=event.xbutton.y;
12228 case ButtonRelease:
12235 command[MagickPathExtent];
12240 if (event.xkey.window != windows->image.id)
12243 Respond to a user key press.
12245 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12246 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12247 switch ((int) key_symbol)
12255 state|=EscapeState;
12262 (void) XSetFunction(display,windows->image.highlight_context,
12264 XTextViewWidget(display,resource_info,windows,MagickFalse,
12265 "Help Viewer - Image Rotation",ImageRotateHelp);
12266 (void) XSetFunction(display,windows->image.highlight_context,
12272 (void) XBell(display,0);
12280 rotate_info.x1=event.xmotion.x;
12281 rotate_info.y1=event.xmotion.y;
12284 rotate_info.x2=rotate_info.x1;
12285 rotate_info.y2=rotate_info.y1;
12286 if (direction == HorizontalRotateCommand)
12287 rotate_info.x2+=32;
12289 rotate_info.y2-=32;
12290 } while ((state & ExitState) == 0);
12291 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12292 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12293 if ((state & EscapeState) != 0)
12294 return(MagickTrue);
12296 Draw line as pointer moves until the mouse button is released.
12299 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12300 state=DefaultState;
12306 Display info and draw rotation line.
12308 if (IfMagickFalse(windows->info.mapped) )
12309 (void) XMapWindow(display,windows->info.id);
12310 (void) FormatLocaleString(text,MagickPathExtent," %g",
12311 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12312 XInfoWidget(display,windows,text);
12313 XHighlightLine(display,windows->image.id,
12314 windows->image.highlight_context,&rotate_info);
12317 if (IfMagickTrue(windows->info.mapped) )
12318 (void) XWithdrawWindow(display,windows->info.id,
12319 windows->info.screen);
12321 Wait for next event.
12323 XScreenEvent(display,windows,&event,exception);
12325 XHighlightLine(display,windows->image.id,
12326 windows->image.highlight_context,&rotate_info);
12327 switch (event.type)
12331 case ButtonRelease:
12334 User has committed to rotation line.
12336 rotate_info.x2=event.xbutton.x;
12337 rotate_info.y2=event.xbutton.y;
12345 rotate_info.x2=event.xmotion.x;
12346 rotate_info.y2=event.xmotion.y;
12352 Check boundary conditions.
12354 if (rotate_info.x2 < 0)
12357 if (rotate_info.x2 > (int) windows->image.width)
12358 rotate_info.x2=(short) windows->image.width;
12359 if (rotate_info.y2 < 0)
12362 if (rotate_info.y2 > (int) windows->image.height)
12363 rotate_info.y2=(short) windows->image.height;
12365 Compute rotation angle from the slope of the line.
12368 distance=(unsigned int)
12369 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12370 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12372 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12373 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12374 } while ((state & ExitState) == 0);
12375 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12376 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12378 return(MagickTrue);
12380 if (direction == VerticalRotateCommand)
12382 if (degrees == 0.0)
12383 return(MagickTrue);
12387 normalized_degrees=degrees;
12388 while (normalized_degrees < -45.0)
12389 normalized_degrees+=360.0;
12390 for (rotations=0; normalized_degrees > 45.0; rotations++)
12391 normalized_degrees-=90.0;
12392 if (normalized_degrees != 0.0)
12393 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12395 XSetCursorState(display,windows,MagickTrue);
12396 XCheckRefreshWindows(display,windows);
12397 (*image)->background_color.red=(double) ScaleShortToQuantum(
12398 windows->pixel_info->pen_colors[pen_id].red);
12399 (*image)->background_color.green=(double) ScaleShortToQuantum(
12400 windows->pixel_info->pen_colors[pen_id].green);
12401 (*image)->background_color.blue=(double) ScaleShortToQuantum(
12402 windows->pixel_info->pen_colors[pen_id].blue);
12403 rotate_image=RotateImage(*image,degrees,exception);
12404 XSetCursorState(display,windows,MagickFalse);
12405 if (rotate_image == (Image *) NULL)
12406 return(MagickFalse);
12407 *image=DestroyImage(*image);
12408 *image=rotate_image;
12409 if (windows->image.crop_geometry != (char *) NULL)
12412 Rotate crop geometry.
12414 width=(unsigned int) (*image)->columns;
12415 height=(unsigned int) (*image)->rows;
12416 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12417 switch (rotations % 4)
12427 (void) FormatLocaleString(windows->image.crop_geometry,MagickPathExtent,
12428 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12435 Rotate 180 degrees.
12437 (void) FormatLocaleString(windows->image.crop_geometry,MagickPathExtent,
12438 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12444 Rotate 270 degrees.
12446 (void) FormatLocaleString(windows->image.crop_geometry,MagickPathExtent,
12447 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12452 if (IfMagickTrue(windows->image.orphan) )
12453 return(MagickTrue);
12454 if (normalized_degrees != 0.0)
12457 Update image colormap.
12459 windows->image.window_changes.width=(int) (*image)->columns;
12460 windows->image.window_changes.height=(int) (*image)->rows;
12461 if (windows->image.crop_geometry != (char *) NULL)
12464 Obtain dimensions of image from crop geometry.
12466 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12468 windows->image.window_changes.width=(int) width;
12469 windows->image.window_changes.height=(int) height;
12471 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12474 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12476 windows->image.window_changes.width=windows->image.ximage->height;
12477 windows->image.window_changes.height=windows->image.ximage->width;
12480 Update image configuration.
12482 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12483 return(MagickTrue);
12487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12491 + X S a v e I m a g e %
12495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12497 % XSaveImage() saves an image to a file.
12499 % The format of the XSaveImage method is:
12501 % MagickBooleanType XSaveImage(Display *display,
12502 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12503 % ExceptionInfo *exception)
12505 % A description of each parameter follows:
12507 % o display: Specifies a connection to an X server; returned from
12510 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12512 % o windows: Specifies a pointer to a XWindows structure.
12514 % o image: the image.
12516 % o exception: return any errors or warnings in this structure.
12519 static MagickBooleanType XSaveImage(Display *display,
12520 XResourceInfo *resource_info,XWindows *windows,Image *image,
12521 ExceptionInfo *exception)
12524 filename[MagickPathExtent],
12525 geometry[MagickPathExtent];
12537 Request file name from user.
12539 if (resource_info->write_filename != (char *) NULL)
12540 (void) CopyMagickString(filename,resource_info->write_filename,
12545 path[MagickPathExtent];
12550 GetPathComponent(image->filename,HeadPath,path);
12551 GetPathComponent(image->filename,TailPath,filename);
12554 status=chdir(path);
12556 (void) ThrowMagickException(exception,GetMagickModule(),
12557 FileOpenError,"UnableToOpenFile","%s",path);
12560 XFileBrowserWidget(display,windows,"Save",filename);
12561 if (*filename == '\0')
12562 return(MagickTrue);
12563 if (IfMagickTrue(IsPathAccessible(filename)) )
12569 File exists-- seek user's permission before overwriting.
12571 status=XConfirmWidget(display,windows,"Overwrite",filename);
12573 return(MagickTrue);
12575 image_info=CloneImageInfo(resource_info->image_info);
12576 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
12577 (void) SetImageInfo(image_info,1,exception);
12578 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12579 (LocaleCompare(image_info->magick,"JPG") == 0))
12582 quality[MagickPathExtent];
12588 Request JPEG quality from user.
12590 (void) FormatLocaleString(quality,MagickPathExtent,"%.20g",(double)
12592 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12594 if (*quality == '\0')
12595 return(MagickTrue);
12596 image->quality=StringToUnsignedLong(quality);
12597 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12599 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12600 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12601 (LocaleCompare(image_info->magick,"PS") == 0) ||
12602 (LocaleCompare(image_info->magick,"PS2") == 0))
12605 geometry[MagickPathExtent];
12608 Request page geometry from user.
12610 (void) CopyMagickString(geometry,PSPageGeometry,MagickPathExtent);
12611 if (LocaleCompare(image_info->magick,"PDF") == 0)
12612 (void) CopyMagickString(geometry,PSPageGeometry,MagickPathExtent);
12613 if (image_info->page != (char *) NULL)
12614 (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
12615 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12616 "Select page geometry:",geometry);
12617 if (*geometry != '\0')
12618 image_info->page=GetPageGeometry(geometry);
12621 Apply image transforms.
12623 XSetCursorState(display,windows,MagickTrue);
12624 XCheckRefreshWindows(display,windows);
12625 save_image=CloneImage(image,0,0,MagickTrue,exception);
12626 if (save_image == (Image *) NULL)
12627 return(MagickFalse);
12628 (void) FormatLocaleString(geometry,MagickPathExtent,"%dx%d!",
12629 windows->image.ximage->width,windows->image.ximage->height);
12630 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12635 (void) CopyMagickString(save_image->filename,filename,MagickPathExtent);
12636 status=WriteImage(image_info,save_image,exception);
12637 if (IfMagickTrue(status) )
12638 image->taint=MagickFalse;
12639 save_image=DestroyImage(save_image);
12640 image_info=DestroyImageInfo(image_info);
12641 XSetCursorState(display,windows,MagickFalse);
12642 return(IsMagickTrue(status));
12646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12650 + X S c r e e n E v e n t %
12654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12656 % XScreenEvent() handles global events associated with the Pan and Magnify
12659 % The format of the XScreenEvent function is:
12661 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12662 % ExceptionInfo *exception)
12664 % A description of each parameter follows:
12666 % o display: Specifies a pointer to the Display structure; returned from
12669 % o windows: Specifies a pointer to a XWindows structure.
12671 % o event: Specifies a pointer to a X11 XEvent structure.
12673 % o exception: return any errors or warnings in this structure.
12677 #if defined(__cplusplus) || defined(c_plusplus)
12681 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12686 windows=(XWindows *) data;
12687 if ((event->type == ClientMessage) &&
12688 (event->xclient.window == windows->image.id))
12689 return(MagickFalse);
12690 return(MagickTrue);
12693 #if defined(__cplusplus) || defined(c_plusplus)
12697 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12698 ExceptionInfo *exception)
12704 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12705 if (event->xany.window == windows->command.id)
12707 switch (event->type)
12710 case ButtonRelease:
12712 if ((event->xbutton.button == Button3) &&
12713 (event->xbutton.state & Mod1Mask))
12716 Convert Alt-Button3 to Button2.
12718 event->xbutton.button=Button2;
12719 event->xbutton.state&=(~Mod1Mask);
12721 if (event->xbutton.window == windows->backdrop.id)
12723 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12724 event->xbutton.time);
12727 if (event->xbutton.window == windows->pan.id)
12729 XPanImage(display,windows,event,exception);
12732 if (event->xbutton.window == windows->image.id)
12733 if (event->xbutton.button == Button2)
12736 Update magnified image.
12738 x=event->xbutton.x;
12739 y=event->xbutton.y;
12743 if (x >= (int) windows->image.width)
12744 x=(int) (windows->image.width-1);
12745 windows->magnify.x=(int) windows->image.x+x;
12749 if (y >= (int) windows->image.height)
12750 y=(int) (windows->image.height-1);
12751 windows->magnify.y=windows->image.y+y;
12752 if (IfMagickFalse(windows->magnify.mapped) )
12753 (void) XMapRaised(display,windows->magnify.id);
12754 XMakeMagnifyImage(display,windows,exception);
12755 if (event->type == ButtonRelease)
12756 (void) XWithdrawWindow(display,windows->info.id,
12757 windows->info.screen);
12762 case ClientMessage:
12765 If client window delete message, exit.
12767 if (event->xclient.message_type != windows->wm_protocols)
12769 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12771 if (event->xclient.window == windows->magnify.id)
12773 (void) XWithdrawWindow(display,windows->magnify.id,
12774 windows->magnify.screen);
12779 case ConfigureNotify:
12781 if (event->xconfigure.window == windows->magnify.id)
12787 Magnify window has a new configuration.
12789 windows->magnify.width=(unsigned int) event->xconfigure.width;
12790 windows->magnify.height=(unsigned int) event->xconfigure.height;
12791 if (IfMagickFalse(windows->magnify.mapped) )
12794 while ((int) magnify <= event->xconfigure.width)
12796 while ((int) magnify <= event->xconfigure.height)
12799 if (((int) magnify != event->xconfigure.width) ||
12800 ((int) magnify != event->xconfigure.height))
12805 window_changes.width=(int) magnify;
12806 window_changes.height=(int) magnify;
12807 (void) XReconfigureWMWindow(display,windows->magnify.id,
12808 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12812 XMakeMagnifyImage(display,windows,exception);
12819 if (event->xexpose.window == windows->image.id)
12821 XRefreshWindow(display,&windows->image,event);
12824 if (event->xexpose.window == windows->pan.id)
12825 if (event->xexpose.count == 0)
12827 XDrawPanRectangle(display,windows);
12830 if (event->xexpose.window == windows->magnify.id)
12831 if (event->xexpose.count == 0)
12833 XMakeMagnifyImage(display,windows,exception);
12841 command[MagickPathExtent];
12846 if (event->xkey.window != windows->magnify.id)
12849 Respond to a user key press.
12851 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12852 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12853 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12859 if (event->xmap.window == windows->magnify.id)
12861 windows->magnify.mapped=MagickTrue;
12862 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12865 if (event->xmap.window == windows->info.id)
12867 windows->info.mapped=MagickTrue;
12874 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12875 if (event->xmotion.window == windows->image.id)
12876 if (IfMagickTrue(windows->magnify.mapped) )
12879 Update magnified image.
12881 x=event->xmotion.x;
12882 y=event->xmotion.y;
12886 if (x >= (int) windows->image.width)
12887 x=(int) (windows->image.width-1);
12888 windows->magnify.x=(int) windows->image.x+x;
12892 if (y >= (int) windows->image.height)
12893 y=(int) (windows->image.height-1);
12894 windows->magnify.y=windows->image.y+y;
12895 XMakeMagnifyImage(display,windows,exception);
12901 if (event->xunmap.window == windows->magnify.id)
12903 windows->magnify.mapped=MagickFalse;
12906 if (event->xunmap.window == windows->info.id)
12908 windows->info.mapped=MagickFalse;
12919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12923 + X S e t C r o p G e o m e t r y %
12927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12929 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12930 % and translates it to a cropping geometry relative to the image.
12932 % The format of the XSetCropGeometry method is:
12934 % void XSetCropGeometry(Display *display,XWindows *windows,
12935 % RectangleInfo *crop_info,Image *image)
12937 % A description of each parameter follows:
12939 % o display: Specifies a connection to an X server; returned from
12942 % o windows: Specifies a pointer to a XWindows structure.
12944 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12945 % Image window to crop.
12947 % o image: the image.
12950 static void XSetCropGeometry(Display *display,XWindows *windows,
12951 RectangleInfo *crop_info,Image *image)
12954 text[MagickPathExtent];
12967 if (IfMagickTrue(windows->info.mapped) )
12970 Display info on cropping rectangle.
12972 (void) FormatLocaleString(text,MagickPathExtent," %.20gx%.20g%+.20g%+.20g",
12973 (double) crop_info->width,(double) crop_info->height,(double)
12974 crop_info->x,(double) crop_info->y);
12975 XInfoWidget(display,windows,text);
12978 Cropping geometry is relative to any previous crop geometry.
12982 width=(unsigned int) image->columns;
12983 height=(unsigned int) image->rows;
12984 if (windows->image.crop_geometry != (char *) NULL)
12985 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12987 windows->image.crop_geometry=AcquireString((char *) NULL);
12989 Define the crop geometry string from the cropping rectangle.
12991 scale_factor=(double) width/windows->image.ximage->width;
12992 if (crop_info->x > 0)
12993 x+=(int) (scale_factor*crop_info->x+0.5);
12994 width=(unsigned int) (scale_factor*crop_info->width+0.5);
12997 scale_factor=(double) height/windows->image.ximage->height;
12998 if (crop_info->y > 0)
12999 y+=(int) (scale_factor*crop_info->y+0.5);
13000 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13003 (void) FormatLocaleString(windows->image.crop_geometry,MagickPathExtent,
13004 "%ux%u%+d%+d",width,height,x,y);
13008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13012 + X T i l e I m a g e %
13016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13018 % XTileImage() loads or deletes a selected tile from a visual image directory.
13019 % The load or delete command is chosen from a menu.
13021 % The format of the XTileImage method is:
13023 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13024 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13026 % A description of each parameter follows:
13028 % o tile_image: XTileImage reads or deletes the tile image
13029 % and returns it. A null image is returned if an error occurs.
13031 % o display: Specifies a connection to an X server; returned from
13034 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13036 % o windows: Specifies a pointer to a XWindows structure.
13038 % o image: the image; returned from ReadImage.
13040 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13041 % the entire image is refreshed.
13043 % o exception: return any errors or warnings in this structure.
13046 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13047 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13060 static const ModeType
13071 command[MagickPathExtent],
13072 filename[MagickPathExtent];
13099 Tile image is relative to montage image configuration.
13103 width=(unsigned int) image->columns;
13104 height=(unsigned int) image->rows;
13105 if (windows->image.crop_geometry != (char *) NULL)
13106 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13107 scale_factor=(double) width/windows->image.ximage->width;
13108 event->xbutton.x+=windows->image.x;
13109 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13110 scale_factor=(double) height/windows->image.ximage->height;
13111 event->xbutton.y+=windows->image.y;
13112 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13114 Determine size and location of each tile in the visual image directory.
13116 width=(unsigned int) image->columns;
13117 height=(unsigned int) image->rows;
13120 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13121 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13122 (event->xbutton.x-x)/width;
13126 Button press is outside any tile.
13128 (void) XBell(display,0);
13129 return((Image *) NULL);
13132 Determine file name from the tile directory.
13134 p=image->directory;
13135 for (i=tile; (i != 0) && (*p != '\0'); )
13144 Button press is outside any tile.
13146 (void) XBell(display,0);
13147 return((Image *) NULL);
13150 Select a command from the pop-up menu.
13152 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13154 return((Image *) NULL);
13156 while ((*q != '\n') && (*q != '\0'))
13158 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13160 Perform command for the selected tile.
13162 XSetCursorState(display,windows,MagickTrue);
13163 XCheckRefreshWindows(display,windows);
13164 tile_image=NewImageList();
13165 switch (TileCommands[id])
13167 case TileLoadCommand:
13172 XCheckRefreshWindows(display,windows);
13173 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13175 (void) CopyMagickString(resource_info->image_info->filename,filename,
13177 tile_image=ReadImage(resource_info->image_info,exception);
13178 CatchException(exception);
13179 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13182 case TileNextCommand:
13185 Display next image.
13187 XClientMessage(display,windows->image.id,windows->im_protocols,
13188 windows->im_next_image,CurrentTime);
13191 case TileFormerCommand:
13194 Display former image.
13196 XClientMessage(display,windows->image.id,windows->im_protocols,
13197 windows->im_former_image,CurrentTime);
13200 case TileDeleteCommand:
13205 if (IfMagickFalse(IsPathAccessible(filename)) )
13207 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13210 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13213 status=ShredFile(filename);
13214 if (IfMagickTrue(status) )
13216 XNoticeWidget(display,windows,"Unable to delete image file:",
13221 case TileUpdateCommand:
13237 Ensure all the images exist.
13240 GetPixelInfo(image,&pixel);
13241 for (p=image->directory; *p != '\0'; p++)
13247 while ((*q != '\n') && (*q != '\0'))
13249 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13251 if (IfMagickTrue(IsPathAccessible(filename)) )
13257 Overwrite tile with background color.
13259 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13260 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13261 image_view=AcquireAuthenticCacheView(image,exception);
13262 (void) GetOneCacheViewVirtualPixelInfo(image_view,0,0,&pixel,exception);
13263 for (i=0; i < (int) height; i++)
13265 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13266 y_offset+i,width,1,exception);
13267 if (s == (Quantum *) NULL)
13269 for (j=0; j < (int) width; j++)
13271 SetPixelViaPixelInfo(image,&pixel,s);
13272 s+=GetPixelChannels(image);
13274 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
13277 image_view=DestroyCacheView(image_view);
13280 windows->image.window_changes.width=(int) image->columns;
13281 windows->image.window_changes.height=(int) image->rows;
13282 XConfigureImageColormap(display,resource_info,windows,image,exception);
13283 (void) XConfigureImage(display,resource_info,windows,image,exception);
13289 XSetCursorState(display,windows,MagickFalse);
13290 return(tile_image);
13294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13298 + X T r a n s l a t e I m a g e %
13302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13304 % XTranslateImage() translates the image within an Image window by one pixel
13305 % as specified by the key symbol. If the image has a montage string the
13306 % translation is respect to the width and height contained within the string.
13308 % The format of the XTranslateImage method is:
13310 % void XTranslateImage(Display *display,XWindows *windows,
13311 % Image *image,const KeySym key_symbol)
13313 % A description of each parameter follows:
13315 % o display: Specifies a connection to an X server; returned from
13318 % o windows: Specifies a pointer to a XWindows structure.
13320 % o image: the image.
13322 % o key_symbol: Specifies a KeySym which indicates which side of the image
13326 static void XTranslateImage(Display *display,XWindows *windows,
13327 Image *image,const KeySym key_symbol)
13330 text[MagickPathExtent];
13341 User specified a pan position offset.
13343 x_offset=windows->image.width;
13344 y_offset=windows->image.height;
13345 if (image->montage != (char *) NULL)
13346 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13347 switch ((int) key_symbol)
13352 windows->image.x=(int) windows->image.width/2;
13353 windows->image.y=(int) windows->image.height/2;
13359 windows->image.x-=x_offset;
13366 windows->image.y-=y_offset;
13372 windows->image.x+=x_offset;
13379 windows->image.y+=y_offset;
13386 Check boundary conditions.
13388 if (windows->image.x < 0)
13389 windows->image.x=0;
13391 if ((int) (windows->image.x+windows->image.width) >
13392 windows->image.ximage->width)
13393 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13394 if (windows->image.y < 0)
13395 windows->image.y=0;
13397 if ((int) (windows->image.y+windows->image.height) >
13398 windows->image.ximage->height)
13399 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13401 Refresh Image window.
13403 (void) FormatLocaleString(text,MagickPathExtent," %ux%u%+d%+d ",
13404 windows->image.width,windows->image.height,windows->image.x,
13406 XInfoWidget(display,windows,text);
13407 XCheckRefreshWindows(display,windows);
13408 XDrawPanRectangle(display,windows);
13409 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13410 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13418 + X T r i m I m a g e %
13422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13424 % XTrimImage() trims the edges from the Image window.
13426 % The format of the XTrimImage method is:
13428 % MagickBooleanType XTrimImage(Display *display,
13429 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13430 % ExceptionInfo *exception)
13432 % A description of each parameter follows:
13434 % o display: Specifies a connection to an X server; returned from
13437 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13439 % o windows: Specifies a pointer to a XWindows structure.
13441 % o image: the image.
13443 % o exception: return any errors or warnings in this structure.
13446 static MagickBooleanType XTrimImage(Display *display,
13447 XResourceInfo *resource_info,XWindows *windows,Image *image,
13448 ExceptionInfo *exception)
13462 Trim edges from image.
13464 XSetCursorState(display,windows,MagickTrue);
13465 XCheckRefreshWindows(display,windows);
13467 Crop the left edge.
13469 background=XGetPixel(windows->image.ximage,0,0);
13470 trim_info.width=(size_t) windows->image.ximage->width;
13471 for (x=0; x < windows->image.ximage->width; x++)
13473 for (y=0; y < windows->image.ximage->height; y++)
13475 pixel=XGetPixel(windows->image.ximage,x,y);
13476 if (pixel != background)
13479 if (y < windows->image.ximage->height)
13482 trim_info.x=(ssize_t) x;
13483 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13485 XSetCursorState(display,windows,MagickFalse);
13486 return(MagickFalse);
13489 Crop the right edge.
13491 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13492 for (x=windows->image.ximage->width-1; x != 0; x--)
13494 for (y=0; y < windows->image.ximage->height; y++)
13496 pixel=XGetPixel(windows->image.ximage,x,y);
13497 if (pixel != background)
13500 if (y < windows->image.ximage->height)
13503 trim_info.width=(size_t) (x-trim_info.x+1);
13507 background=XGetPixel(windows->image.ximage,0,0);
13508 trim_info.height=(size_t) windows->image.ximage->height;
13509 for (y=0; y < windows->image.ximage->height; y++)
13511 for (x=0; x < windows->image.ximage->width; x++)
13513 pixel=XGetPixel(windows->image.ximage,x,y);
13514 if (pixel != background)
13517 if (x < windows->image.ximage->width)
13520 trim_info.y=(ssize_t) y;
13522 Crop the bottom edge.
13524 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13525 for (y=windows->image.ximage->height-1; y != 0; y--)
13527 for (x=0; x < windows->image.ximage->width; x++)
13529 pixel=XGetPixel(windows->image.ximage,x,y);
13530 if (pixel != background)
13533 if (x < windows->image.ximage->width)
13536 trim_info.height=(size_t) y-trim_info.y+1;
13537 if (((unsigned int) trim_info.width != windows->image.width) ||
13538 ((unsigned int) trim_info.height != windows->image.height))
13541 Reconfigure Image window as defined by the trimming rectangle.
13543 XSetCropGeometry(display,windows,&trim_info,image);
13544 windows->image.window_changes.width=(int) trim_info.width;
13545 windows->image.window_changes.height=(int) trim_info.height;
13546 (void) XConfigureImage(display,resource_info,windows,image,exception);
13548 XSetCursorState(display,windows,MagickFalse);
13549 return(MagickTrue);
13553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13557 + X V i s u a l D i r e c t o r y I m a g e %
13561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13563 % XVisualDirectoryImage() creates a Visual Image Directory.
13565 % The format of the XVisualDirectoryImage method is:
13567 % Image *XVisualDirectoryImage(Display *display,
13568 % XResourceInfo *resource_info,XWindows *windows,
13569 % ExceptionInfo *exception)
13571 % A description of each parameter follows:
13573 % o display: Specifies a connection to an X server; returned from
13576 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13578 % o windows: Specifies a pointer to a XWindows structure.
13580 % o exception: return any errors or warnings in this structure.
13583 static Image *XVisualDirectoryImage(Display *display,
13584 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13586 #define TileImageTag "Scale/Image"
13587 #define XClientName "montage"
13620 filename[MagickPathExtent] = "\0",
13621 filenames[MagickPathExtent] = "*";
13624 background_resources;
13627 Request file name from user.
13629 XFileBrowserWidget(display,windows,"Directory",filenames);
13630 if (*filenames == '\0')
13631 return((Image *) NULL);
13633 Expand the filenames.
13635 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13636 if (filelist == (char **) NULL)
13638 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
13640 return((Image *) NULL);
13643 filelist[0]=filenames;
13644 status=ExpandFilenames(&number_files,&filelist);
13645 if (IfMagickFalse(status) || (number_files == 0))
13647 if (number_files == 0)
13648 ThrowXWindowException(ImageError,"NoImagesWereFound",filenames)
13650 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
13652 return((Image *) NULL);
13655 Set image background resources.
13657 background_resources=(*resource_info);
13658 background_resources.window_id=AcquireString("");
13659 (void) FormatLocaleString(background_resources.window_id,MagickPathExtent,
13660 "0x%lx",windows->image.id);
13661 background_resources.backdrop=MagickTrue;
13663 Read each image and convert them to a tile.
13665 backdrop=IsMagickTrue( (windows->visual_info->klass == TrueColor) ||
13666 (windows->visual_info->klass == DirectColor) );
13667 read_info=CloneImageInfo(resource_info->image_info);
13668 (void) SetImageOption(read_info,"jpeg:size","120x120");
13669 (void) CloneString(&read_info->size,DefaultTileGeometry);
13670 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13672 images=NewImageList();
13673 XSetCursorState(display,windows,MagickTrue);
13674 XCheckRefreshWindows(display,windows);
13675 for (i=0; i < (int) number_files; i++)
13677 (void) CopyMagickString(read_info->filename,filelist[i],MagickPathExtent);
13678 filelist[i]=DestroyString(filelist[i]);
13679 *read_info->magick='\0';
13680 next_image=ReadImage(read_info,exception);
13681 CatchException(exception);
13682 if (next_image != (Image *) NULL)
13684 (void) DeleteImageProperty(next_image,"label");
13685 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13686 read_info,next_image,DefaultTileLabel,exception),exception);
13687 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13689 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13690 geometry.height,exception);
13691 if (thumbnail_image != (Image *) NULL)
13693 next_image=DestroyImage(next_image);
13694 next_image=thumbnail_image;
13698 (void) XDisplayBackgroundImage(display,&background_resources,
13699 next_image,exception);
13700 XSetCursorState(display,windows,MagickTrue);
13702 AppendImageToList(&images,next_image);
13703 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13708 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13709 (MagickSizeType) number_files);
13710 if (IfMagickFalse(proceed) )
13715 filelist=(char **) RelinquishMagickMemory(filelist);
13716 if (images == (Image *) NULL)
13718 read_info=DestroyImageInfo(read_info);
13719 XSetCursorState(display,windows,MagickFalse);
13720 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
13721 return((Image *) NULL);
13724 Create the Visual Image Directory.
13726 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13727 montage_info->pointsize=10;
13728 if (resource_info->font != (char *) NULL)
13729 (void) CloneString(&montage_info->font,resource_info->font);
13730 (void) CopyMagickString(montage_info->filename,filename,MagickPathExtent);
13731 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13732 images),exception);
13733 images=DestroyImageList(images);
13734 montage_info=DestroyMontageInfo(montage_info);
13735 read_info=DestroyImageInfo(read_info);
13736 XSetCursorState(display,windows,MagickFalse);
13737 if (montage_image == (Image *) NULL)
13738 return(montage_image);
13739 XClientMessage(display,windows->image.id,windows->im_protocols,
13740 windows->im_next_image,CurrentTime);
13741 return(montage_image);
13745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13749 % X D i s p l a y B a c k g r o u n d I m a g e %
13753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13755 % XDisplayBackgroundImage() displays an image in the background of a window.
13757 % The format of the XDisplayBackgroundImage method is:
13759 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13760 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13762 % A description of each parameter follows:
13764 % o display: Specifies a connection to an X server; returned from
13767 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13769 % o image: the image.
13771 % o exception: return any errors or warnings in this structure.
13774 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13775 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13778 geometry[MagickPathExtent],
13779 visual_type[MagickPathExtent];
13792 static XStandardColormap
13796 *visual_info = (XVisualInfo *) NULL;
13817 Determine target window.
13819 assert(image != (Image *) NULL);
13820 assert(image->signature == MagickSignature);
13821 if (IfMagickTrue(image->debug) )
13822 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13823 resources=(*resource_info);
13824 window_info.id=(Window) NULL;
13825 root_window=XRootWindow(display,XDefaultScreen(display));
13826 if (LocaleCompare(resources.window_id,"root") == 0)
13827 window_info.id=root_window;
13830 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
13831 window_info.id=XWindowByID(display,root_window,
13832 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13833 if (window_info.id == (Window) NULL)
13834 window_info.id=XWindowByName(display,root_window,resources.window_id);
13836 if (window_info.id == (Window) NULL)
13838 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
13839 resources.window_id);
13840 return(MagickFalse);
13843 Determine window visual id.
13845 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13846 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13847 (void) CopyMagickString(visual_type,"default",MagickPathExtent);
13848 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13850 (void) FormatLocaleString(visual_type,MagickPathExtent,"0x%lx",
13851 XVisualIDFromVisual(window_attributes.visual));
13852 if (visual_info == (XVisualInfo *) NULL)
13855 Allocate standard colormap.
13857 map_info=XAllocStandardColormap();
13858 if (map_info == (XStandardColormap *) NULL)
13859 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13861 map_info->colormap=(Colormap) NULL;
13862 pixel.pixels=(unsigned long *) NULL;
13864 Initialize visual info.
13866 resources.map_type=(char *) NULL;
13867 resources.visual_type=visual_type;
13868 visual_info=XBestVisualInfo(display,map_info,&resources);
13869 if (visual_info == (XVisualInfo *) NULL)
13870 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13871 resources.visual_type);
13873 Initialize window info.
13875 window_info.ximage=(XImage *) NULL;
13876 window_info.matte_image=(XImage *) NULL;
13877 window_info.pixmap=(Pixmap) NULL;
13878 window_info.matte_pixmap=(Pixmap) NULL;
13881 Free previous root colors.
13883 if (window_info.id == root_window)
13884 (void) XDestroyWindowColors(display,root_window);
13886 Initialize Standard Colormap.
13888 resources.colormap=SharedColormap;
13889 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13892 Graphic context superclass.
13894 context_values.background=pixel.background_color.pixel;
13895 context_values.foreground=pixel.foreground_color.pixel;
13896 pixel.annotate_context=XCreateGC(display,window_info.id,
13897 (size_t) (GCBackground | GCForeground),&context_values);
13898 if (pixel.annotate_context == (GC) NULL)
13899 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13902 Initialize Image window attributes.
13904 window_info.name=AcquireString("\0");
13905 window_info.icon_name=AcquireString("\0");
13906 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13907 &resources,&window_info);
13909 Create the X image.
13911 window_info.width=(unsigned int) image->columns;
13912 window_info.height=(unsigned int) image->rows;
13913 if ((image->columns != window_info.width) ||
13914 (image->rows != window_info.height))
13915 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13917 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>",
13918 window_attributes.width,window_attributes.height);
13919 geometry_info.width=window_info.width;
13920 geometry_info.height=window_info.height;
13921 geometry_info.x=(ssize_t) window_info.x;
13922 geometry_info.y=(ssize_t) window_info.y;
13923 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13924 &geometry_info.width,&geometry_info.height);
13925 window_info.width=(unsigned int) geometry_info.width;
13926 window_info.height=(unsigned int) geometry_info.height;
13927 window_info.x=(int) geometry_info.x;
13928 window_info.y=(int) geometry_info.y;
13929 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13930 window_info.height,exception);
13931 if (IfMagickFalse(status) )
13932 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13936 if (IfMagickTrue(image->debug) )
13938 (void) LogMagickEvent(X11Event,GetMagickModule(),
13939 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13940 (double) image->columns,(double) image->rows);
13941 if (image->colors != 0)
13942 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13944 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13947 Adjust image dimensions as specified by backdrop or geometry options.
13949 width=(int) window_info.width;
13950 height=(int) window_info.height;
13951 if (IfMagickTrue(resources.backdrop) )
13954 Center image on window.
13956 window_info.x=(window_attributes.width/2)-
13957 (window_info.ximage->width/2);
13958 window_info.y=(window_attributes.height/2)-
13959 (window_info.ximage->height/2);
13960 width=window_attributes.width;
13961 height=window_attributes.height;
13963 if ((resources.image_geometry != (char *) NULL) &&
13964 (*resources.image_geometry != '\0'))
13967 default_geometry[MagickPathExtent];
13977 User specified geometry.
13979 size_hints=XAllocSizeHints();
13980 if (size_hints == (XSizeHints *) NULL)
13981 ThrowXWindowFatalException(ResourceLimitFatalError,
13982 "MemoryAllocationFailed",image->filename);
13983 size_hints->flags=0L;
13984 (void) FormatLocaleString(default_geometry,MagickPathExtent,"%dx%d",
13986 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13987 default_geometry,window_info.border_width,size_hints,&window_info.x,
13988 &window_info.y,&width,&height,&gravity);
13989 if (flags & (XValue | YValue))
13991 width=window_attributes.width;
13992 height=window_attributes.height;
13994 (void) XFree((void *) size_hints);
13997 Create the X pixmap.
13999 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14000 (unsigned int) height,window_info.depth);
14001 if (window_info.pixmap == (Pixmap) NULL)
14002 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14005 Display pixmap on the window.
14007 if (((unsigned int) width > window_info.width) ||
14008 ((unsigned int) height > window_info.height))
14009 (void) XFillRectangle(display,window_info.pixmap,
14010 window_info.annotate_context,0,0,(unsigned int) width,
14011 (unsigned int) height);
14012 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14013 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14014 window_info.width,(unsigned int) window_info.height);
14015 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14016 (void) XClearWindow(display,window_info.id);
14017 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14018 XDelay(display,delay == 0UL ? 10UL : delay);
14019 (void) XSync(display,MagickFalse);
14020 return(IsMagickTrue(window_info.id == root_window));
14024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14028 + X D i s p l a y I m a g e %
14032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14034 % XDisplayImage() displays an image via X11. A new image is created and
14035 % returned if the user interactively transforms the displayed image.
14037 % The format of the XDisplayImage method is:
14039 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14040 % char **argv,int argc,Image **image,size_t *state,
14041 % ExceptionInfo *exception)
14043 % A description of each parameter follows:
14045 % o nexus: Method XDisplayImage returns an image when the
14046 % user chooses 'Open Image' from the command menu or picks a tile
14047 % from the image directory. Otherwise a null image is returned.
14049 % o display: Specifies a connection to an X server; returned from
14052 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14054 % o argv: Specifies the application's argument list.
14056 % o argc: Specifies the number of arguments.
14058 % o image: Specifies an address to an address of an Image structure;
14060 % o exception: return any errors or warnings in this structure.
14063 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14064 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14066 #define MagnifySize 256 /* must be a power of 2 */
14067 #define MagickMenus 10
14068 #define MagickTitle "Commands"
14095 "Visual Directory...",
14141 "Contrast Stretch...",
14142 "Sigmoidal Contrast...",
14176 "Charcoal Draw...",
14190 "Region of Interest...",
14193 *MiscellanyMenu[] =
14208 "Browse Documentation",
14235 **Menus[MagickMenus] =
14273 VisualDirectoryCommand,
14287 OriginalSizeCommand,
14294 TransformCommands[] =
14300 RotateRightCommand,
14307 EnhanceCommands[] =
14315 ContrastStretchCommand,
14316 SigmoidalContrastCommand,
14324 EffectsCommands[] =
14328 ReduceNoiseCommand,
14348 CharcoalDrawCommand
14350 ImageEditCommands[] =
14361 RegionofInterestCommand
14363 MiscellanyCommands[] =
14367 ShowPreviewCommand,
14368 ShowHistogramCommand,
14377 BrowseDocumentationCommand,
14380 ShortCutsCommands[] =
14392 VirtualCommands[] =
14401 *Commands[MagickMenus] =
14411 MiscellanyCommands,
14416 command[MagickPathExtent],
14418 geometry[MagickPathExtent],
14419 resource_name[MagickPathExtent];
14446 working_directory[MagickPathExtent];
14452 *magick_windows[MaxXWindows];
14454 static unsigned int
14514 assert(image != (Image **) NULL);
14515 assert((*image)->signature == MagickSignature);
14516 if (IfMagickTrue((*image)->debug) )
14517 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14518 display_image=(*image);
14519 warning_handler=(WarningHandler) NULL;
14520 windows=XSetWindows((XWindows *) ~0);
14521 if (windows != (XWindows *) NULL)
14526 if (*working_directory == '\0')
14527 (void) CopyMagickString(working_directory,".",MagickPathExtent);
14528 status=chdir(working_directory);
14530 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14531 "UnableToOpenFile","%s",working_directory);
14532 warning_handler=resource_info->display_warnings ?
14533 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14534 warning_handler=resource_info->display_warnings ?
14535 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14540 Allocate windows structure.
14542 resource_info->colors=display_image->colors;
14543 windows=XSetWindows(XInitializeWindows(display,resource_info));
14544 if (windows == (XWindows *) NULL)
14545 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14546 (*image)->filename);
14548 Initialize window id's.
14551 magick_windows[number_windows++]=(&windows->icon);
14552 magick_windows[number_windows++]=(&windows->backdrop);
14553 magick_windows[number_windows++]=(&windows->image);
14554 magick_windows[number_windows++]=(&windows->info);
14555 magick_windows[number_windows++]=(&windows->command);
14556 magick_windows[number_windows++]=(&windows->widget);
14557 magick_windows[number_windows++]=(&windows->popup);
14558 magick_windows[number_windows++]=(&windows->magnify);
14559 magick_windows[number_windows++]=(&windows->pan);
14560 for (i=0; i < (int) number_windows; i++)
14561 magick_windows[i]->id=(Window) NULL;
14566 Initialize font info.
14568 if (windows->font_info != (XFontStruct *) NULL)
14569 (void) XFreeFont(display,windows->font_info);
14570 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14571 if (windows->font_info == (XFontStruct *) NULL)
14572 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14573 resource_info->font);
14575 Initialize Standard Colormap.
14577 map_info=windows->map_info;
14578 icon_map=windows->icon_map;
14579 visual_info=windows->visual_info;
14580 icon_visual=windows->icon_visual;
14581 pixel=windows->pixel_info;
14582 icon_pixel=windows->icon_pixel;
14583 font_info=windows->font_info;
14584 icon_resources=windows->icon_resources;
14585 class_hints=windows->class_hints;
14586 manager_hints=windows->manager_hints;
14587 root_window=XRootWindow(display,visual_info->screen);
14588 nexus=NewImageList();
14589 if (IfMagickTrue(display_image->debug) )
14591 (void) LogMagickEvent(X11Event,GetMagickModule(),
14592 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14593 (double) display_image->scene,(double) display_image->columns,
14594 (double) display_image->rows);
14595 if (display_image->colors != 0)
14596 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14597 display_image->colors);
14598 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14599 display_image->magick);
14601 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14602 map_info,pixel,exception);
14603 display_image->taint=MagickFalse;
14605 Initialize graphic context.
14607 windows->context.id=(Window) NULL;
14608 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14609 resource_info,&windows->context);
14610 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14611 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14612 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14613 manager_hints->flags=InputHint | StateHint;
14614 manager_hints->input=MagickFalse;
14615 manager_hints->initial_state=WithdrawnState;
14616 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14617 &windows->context);
14618 if (IfMagickTrue(display_image->debug) )
14619 (void) LogMagickEvent(X11Event,GetMagickModule(),
14620 "Window id: 0x%lx (context)",windows->context.id);
14621 context_values.background=pixel->background_color.pixel;
14622 context_values.font=font_info->fid;
14623 context_values.foreground=pixel->foreground_color.pixel;
14624 context_values.graphics_exposures=MagickFalse;
14625 context_mask=(MagickStatusType)
14626 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14627 if (pixel->annotate_context != (GC) NULL)
14628 (void) XFreeGC(display,pixel->annotate_context);
14629 pixel->annotate_context=XCreateGC(display,windows->context.id,
14630 context_mask,&context_values);
14631 if (pixel->annotate_context == (GC) NULL)
14632 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14633 display_image->filename);
14634 context_values.background=pixel->depth_color.pixel;
14635 if (pixel->widget_context != (GC) NULL)
14636 (void) XFreeGC(display,pixel->widget_context);
14637 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14639 if (pixel->widget_context == (GC) NULL)
14640 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14641 display_image->filename);
14642 context_values.background=pixel->foreground_color.pixel;
14643 context_values.foreground=pixel->background_color.pixel;
14644 context_values.plane_mask=context_values.background ^
14645 context_values.foreground;
14646 if (pixel->highlight_context != (GC) NULL)
14647 (void) XFreeGC(display,pixel->highlight_context);
14648 pixel->highlight_context=XCreateGC(display,windows->context.id,
14649 (size_t) (context_mask | GCPlaneMask),&context_values);
14650 if (pixel->highlight_context == (GC) NULL)
14651 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14652 display_image->filename);
14653 (void) XDestroyWindow(display,windows->context.id);
14655 Initialize icon window.
14657 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14658 icon_resources,&windows->icon);
14659 windows->icon.geometry=resource_info->icon_geometry;
14660 XBestIconSize(display,&windows->icon,display_image);
14661 windows->icon.attributes.colormap=XDefaultColormap(display,
14662 icon_visual->screen);
14663 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14664 manager_hints->flags=InputHint | StateHint;
14665 manager_hints->input=MagickFalse;
14666 manager_hints->initial_state=IconicState;
14667 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14669 if (IfMagickTrue(display_image->debug) )
14670 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14673 Initialize graphic context for icon window.
14675 if (icon_pixel->annotate_context != (GC) NULL)
14676 (void) XFreeGC(display,icon_pixel->annotate_context);
14677 context_values.background=icon_pixel->background_color.pixel;
14678 context_values.foreground=icon_pixel->foreground_color.pixel;
14679 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14680 (size_t) (GCBackground | GCForeground),&context_values);
14681 if (icon_pixel->annotate_context == (GC) NULL)
14682 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14683 display_image->filename);
14684 windows->icon.annotate_context=icon_pixel->annotate_context;
14686 Initialize Image window.
14688 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14690 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14691 if (IfMagickFalse(resource_info->use_shared_memory) )
14692 windows->image.shared_memory=MagickFalse;
14693 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14698 title=InterpretImageProperties(resource_info->image_info,display_image,
14699 resource_info->title,exception);
14700 (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
14701 (void) CopyMagickString(windows->image.icon_name,title,MagickPathExtent);
14702 title=DestroyString(title);
14707 filename[MagickPathExtent];
14710 Window name is the base of the filename.
14712 GetPathComponent(display_image->magick_filename,TailPath,filename);
14713 if (display_image->scene == 0)
14714 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
14715 "%s: %s",MagickPackageName,filename);
14717 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
14718 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14719 (double) display_image->scene,(double) GetImageListLength(
14721 (void) CopyMagickString(windows->image.icon_name,filename,MagickPathExtent);
14723 if (resource_info->immutable)
14724 windows->image.immutable=MagickTrue;
14725 windows->image.use_pixmap=resource_info->use_pixmap;
14726 windows->image.geometry=resource_info->image_geometry;
14727 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
14728 XDisplayWidth(display,visual_info->screen),
14729 XDisplayHeight(display,visual_info->screen));
14730 geometry_info.width=display_image->columns;
14731 geometry_info.height=display_image->rows;
14734 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14735 &geometry_info.width,&geometry_info.height);
14736 windows->image.width=(unsigned int) geometry_info.width;
14737 windows->image.height=(unsigned int) geometry_info.height;
14738 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14739 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14740 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14741 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14742 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14743 resource_info,&windows->backdrop);
14744 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14747 Initialize backdrop window.
14749 windows->backdrop.x=0;
14750 windows->backdrop.y=0;
14751 (void) CloneString(&windows->backdrop.name,"Backdrop");
14752 windows->backdrop.flags=(size_t) (USSize | USPosition);
14753 windows->backdrop.width=(unsigned int)
14754 XDisplayWidth(display,visual_info->screen);
14755 windows->backdrop.height=(unsigned int)
14756 XDisplayHeight(display,visual_info->screen);
14757 windows->backdrop.border_width=0;
14758 windows->backdrop.immutable=MagickTrue;
14759 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14761 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14762 StructureNotifyMask;
14763 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14764 manager_hints->icon_window=windows->icon.id;
14765 manager_hints->input=MagickTrue;
14766 manager_hints->initial_state=resource_info->iconic ? IconicState :
14768 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14769 &windows->backdrop);
14770 if (IfMagickTrue(display_image->debug) )
14771 (void) LogMagickEvent(X11Event,GetMagickModule(),
14772 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14773 (void) XMapWindow(display,windows->backdrop.id);
14774 (void) XClearWindow(display,windows->backdrop.id);
14775 if (windows->image.id != (Window) NULL)
14777 (void) XDestroyWindow(display,windows->image.id);
14778 windows->image.id=(Window) NULL;
14781 Position image in the center the backdrop.
14783 windows->image.flags|=USPosition;
14784 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14785 (windows->image.width/2);
14786 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14787 (windows->image.height/2);
14789 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14790 manager_hints->icon_window=windows->icon.id;
14791 manager_hints->input=MagickTrue;
14792 manager_hints->initial_state=resource_info->iconic ? IconicState :
14794 if (windows->group_leader.id != (Window) NULL)
14799 manager_hints->flags|=WindowGroupHint;
14800 manager_hints->window_group=windows->group_leader.id;
14801 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14802 if (IfMagickTrue(display_image->debug) )
14803 (void) LogMagickEvent(X11Event,GetMagickModule(),
14804 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14806 XMakeWindow(display,
14807 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14808 argv,argc,class_hints,manager_hints,&windows->image);
14809 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14810 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14811 if (windows->group_leader.id != (Window) NULL)
14812 (void) XSetTransientForHint(display,windows->image.id,
14813 windows->group_leader.id);
14814 if (IfMagickTrue(display_image->debug) )
14815 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14816 windows->image.id);
14818 Initialize Info widget.
14820 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14822 (void) CloneString(&windows->info.name,"Info");
14823 (void) CloneString(&windows->info.icon_name,"Info");
14824 windows->info.border_width=1;
14827 windows->info.flags|=PPosition;
14828 windows->info.attributes.win_gravity=UnmapGravity;
14829 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14830 StructureNotifyMask;
14831 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14832 manager_hints->input=MagickFalse;
14833 manager_hints->initial_state=NormalState;
14834 manager_hints->window_group=windows->image.id;
14835 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14837 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14838 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14839 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14840 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14841 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14842 if (IfMagickTrue(windows->image.mapped) )
14843 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14844 if (IfMagickTrue(display_image->debug) )
14845 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14848 Initialize Command widget.
14850 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14851 resource_info,&windows->command);
14852 windows->command.data=MagickMenus;
14853 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14854 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.command",
14855 resource_info->client_name);
14856 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14857 resource_name,"geometry",(char *) NULL);
14858 (void) CloneString(&windows->command.name,MagickTitle);
14859 windows->command.border_width=0;
14860 windows->command.flags|=PPosition;
14861 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14862 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14863 OwnerGrabButtonMask | StructureNotifyMask;
14864 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14865 manager_hints->input=MagickTrue;
14866 manager_hints->initial_state=NormalState;
14867 manager_hints->window_group=windows->image.id;
14868 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14869 &windows->command);
14870 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14871 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14873 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14874 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14875 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14876 if (IfMagickTrue(windows->command.mapped) )
14877 (void) XMapRaised(display,windows->command.id);
14878 if (IfMagickTrue(display_image->debug) )
14879 (void) LogMagickEvent(X11Event,GetMagickModule(),
14880 "Window id: 0x%lx (command)",windows->command.id);
14882 Initialize Widget window.
14884 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14885 resource_info,&windows->widget);
14886 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.widget",
14887 resource_info->client_name);
14888 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14889 resource_name,"geometry",(char *) NULL);
14890 windows->widget.border_width=0;
14891 windows->widget.flags|=PPosition;
14892 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14893 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14894 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14895 StructureNotifyMask;
14896 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14897 manager_hints->input=MagickTrue;
14898 manager_hints->initial_state=NormalState;
14899 manager_hints->window_group=windows->image.id;
14900 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14902 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14903 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14904 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14905 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14906 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14907 if (IfMagickTrue(display_image->debug) )
14908 (void) LogMagickEvent(X11Event,GetMagickModule(),
14909 "Window id: 0x%lx (widget)",windows->widget.id);
14911 Initialize popup window.
14913 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14914 resource_info,&windows->popup);
14915 windows->popup.border_width=0;
14916 windows->popup.flags|=PPosition;
14917 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14918 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14919 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14920 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14921 manager_hints->input=MagickTrue;
14922 manager_hints->initial_state=NormalState;
14923 manager_hints->window_group=windows->image.id;
14924 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14926 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14927 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14928 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14929 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14930 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14931 if (IfMagickTrue(display_image->debug) )
14932 (void) LogMagickEvent(X11Event,GetMagickModule(),
14933 "Window id: 0x%lx (pop up)",windows->popup.id);
14935 Initialize Magnify window and cursor.
14937 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14938 resource_info,&windows->magnify);
14939 if (IfMagickFalse(resource_info->use_shared_memory) )
14940 windows->magnify.shared_memory=MagickFalse;
14941 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.magnify",
14942 resource_info->client_name);
14943 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14944 resource_name,"geometry",(char *) NULL);
14945 (void) FormatLocaleString(windows->magnify.name,MagickPathExtent,"Magnify %uX",
14946 resource_info->magnify);
14947 if (windows->magnify.cursor != (Cursor) NULL)
14948 (void) XFreeCursor(display,windows->magnify.cursor);
14949 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14950 map_info->colormap,resource_info->background_color,
14951 resource_info->foreground_color);
14952 if (windows->magnify.cursor == (Cursor) NULL)
14953 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14954 display_image->filename);
14955 windows->magnify.width=MagnifySize;
14956 windows->magnify.height=MagnifySize;
14957 windows->magnify.flags|=PPosition;
14958 windows->magnify.min_width=MagnifySize;
14959 windows->magnify.min_height=MagnifySize;
14960 windows->magnify.width_inc=MagnifySize;
14961 windows->magnify.height_inc=MagnifySize;
14962 windows->magnify.data=resource_info->magnify;
14963 windows->magnify.attributes.cursor=windows->magnify.cursor;
14964 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14965 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14966 StructureNotifyMask;
14967 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14968 manager_hints->input=MagickTrue;
14969 manager_hints->initial_state=NormalState;
14970 manager_hints->window_group=windows->image.id;
14971 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14972 &windows->magnify);
14973 if (IfMagickTrue(display_image->debug) )
14974 (void) LogMagickEvent(X11Event,GetMagickModule(),
14975 "Window id: 0x%lx (magnify)",windows->magnify.id);
14976 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14978 Initialize panning window.
14980 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14981 resource_info,&windows->pan);
14982 (void) CloneString(&windows->pan.name,"Pan Icon");
14983 windows->pan.width=windows->icon.width;
14984 windows->pan.height=windows->icon.height;
14985 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.pan",
14986 resource_info->client_name);
14987 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14988 resource_name,"geometry",(char *) NULL);
14989 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14990 &windows->pan.width,&windows->pan.height);
14991 windows->pan.flags|=PPosition;
14992 windows->pan.immutable=MagickTrue;
14993 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14994 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
14995 StructureNotifyMask;
14996 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14997 manager_hints->input=MagickFalse;
14998 manager_hints->initial_state=NormalState;
14999 manager_hints->window_group=windows->image.id;
15000 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15002 if (IfMagickTrue(display_image->debug) )
15003 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15005 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15006 if (IfMagickTrue(windows->info.mapped) )
15007 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15008 if (IfMagickFalse(windows->image.mapped) ||
15009 (windows->backdrop.id != (Window) NULL))
15010 (void) XMapWindow(display,windows->image.id);
15012 Set our progress monitor and warning handlers.
15014 if (warning_handler == (WarningHandler) NULL)
15016 warning_handler=resource_info->display_warnings ?
15017 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15018 warning_handler=resource_info->display_warnings ?
15019 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15022 Initialize Image and Magnify X images.
15024 windows->image.x=0;
15025 windows->image.y=0;
15026 windows->magnify.shape=MagickFalse;
15027 width=(unsigned int) display_image->columns;
15028 height=(unsigned int) display_image->rows;
15029 if ((display_image->columns != width) || (display_image->rows != height))
15030 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15031 display_image->filename);
15032 status=XMakeImage(display,resource_info,&windows->image,display_image,
15033 width,height,exception);
15034 if (IfMagickFalse(status) )
15035 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15036 display_image->filename);
15037 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15038 windows->magnify.width,windows->magnify.height,exception);
15039 if (IfMagickFalse(status))
15040 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15041 display_image->filename);
15042 if (IfMagickTrue(windows->magnify.mapped) )
15043 (void) XMapRaised(display,windows->magnify.id);
15044 if (IfMagickTrue(windows->pan.mapped) )
15045 (void) XMapRaised(display,windows->pan.id);
15046 windows->image.window_changes.width=(int) display_image->columns;
15047 windows->image.window_changes.height=(int) display_image->rows;
15048 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15049 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15050 (void) XSync(display,MagickFalse);
15054 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15055 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15057 if (IfMagickTrue(resource_info->update) )
15063 Determine when file data was last modified.
15065 status=GetPathAttributes(display_image->filename,&attributes);
15066 if (IfMagickTrue(status) )
15067 update_time=attributes.st_mtime;
15069 *state&=(~FormerImageState);
15070 *state&=(~MontageImageState);
15071 *state&=(~NextImageState);
15075 Handle a window event.
15077 if (IfMagickTrue(windows->image.mapped) )
15078 if ((display_image->delay != 0) || (resource_info->update != 0))
15080 if (timer < time((time_t *) NULL))
15082 if (IfMagickFalse(resource_info->update) )
15083 *state|=NextImageState | ExitState;
15090 Determine if image file was modified.
15092 status=GetPathAttributes(display_image->filename,&attributes);
15093 if (IfMagickTrue(status) )
15094 if (update_time != attributes.st_mtime)
15099 (void) FormatLocaleString(
15100 resource_info->image_info->filename,MagickPathExtent,
15101 "%s:%s",display_image->magick,
15102 display_image->filename);
15103 nexus=ReadImage(resource_info->image_info,exception);
15104 if (nexus != (Image *) NULL)
15106 nexus=DestroyImage(nexus);
15107 *state|=NextImageState | ExitState;
15110 delay=display_image->delay/MagickMax(
15111 display_image->ticks_per_second,1L);
15112 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15115 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15118 Do not block if delay > 0.
15120 XDelay(display,SuspendTime << 2);
15124 timestamp=time((time_t *) NULL);
15125 (void) XNextEvent(display,&event);
15126 if (IfMagickFalse(windows->image.stasis) )
15127 windows->image.stasis=IsMagickTrue((time((time_t *) NULL)-timestamp) > 0);
15128 if (IfMagickFalse(windows->magnify.stasis) )
15129 windows->magnify.stasis=IsMagickTrue((time((time_t *) NULL)-timestamp) > 0);
15130 if (event.xany.window == windows->command.id)
15133 Select a command from the Command widget.
15135 id=XCommandWidget(display,windows,CommandMenu,&event);
15138 (void) CopyMagickString(command,CommandMenu[id],MagickPathExtent);
15139 command_type=CommandMenus[id];
15140 if (id < MagickMenus)
15143 Select a command from a pop-up menu.
15145 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15149 (void) CopyMagickString(command,Menus[id][entry],MagickPathExtent);
15150 command_type=Commands[id][entry];
15152 if (command_type != NullCommand)
15153 nexus=XMagickCommand(display,resource_info,windows,command_type,
15154 &display_image,exception);
15157 switch (event.type)
15161 if (IfMagickTrue(display_image->debug) )
15162 (void) LogMagickEvent(X11Event,GetMagickModule(),
15163 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15164 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15165 if ((event.xbutton.button == Button3) &&
15166 (event.xbutton.state & Mod1Mask))
15169 Convert Alt-Button3 to Button2.
15171 event.xbutton.button=Button2;
15172 event.xbutton.state&=(~Mod1Mask);
15174 if (event.xbutton.window == windows->backdrop.id)
15176 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15177 event.xbutton.time);
15180 if (event.xbutton.window == windows->image.id)
15182 switch (event.xbutton.button)
15186 if (resource_info->immutable)
15189 Select a command from the Virtual menu.
15191 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15194 nexus=XMagickCommand(display,resource_info,windows,
15195 VirtualCommands[entry],&display_image,exception);
15199 Map/unmap Command widget.
15201 if (IfMagickTrue(windows->command.mapped) )
15202 (void) XWithdrawWindow(display,windows->command.id,
15203 windows->command.screen);
15206 (void) XCommandWidget(display,windows,CommandMenu,
15208 (void) XMapRaised(display,windows->command.id);
15215 User pressed the image magnify button.
15217 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15218 &display_image,exception);
15219 XMagnifyImage(display,windows,&event,exception);
15224 if (resource_info->immutable)
15227 Select a command from the Virtual menu.
15229 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15232 nexus=XMagickCommand(display,resource_info,windows,
15233 VirtualCommands[entry],&display_image,exception);
15236 if (display_image->montage != (char *) NULL)
15239 Open or delete a tile from a visual image directory.
15241 nexus=XTileImage(display,resource_info,windows,
15242 display_image,&event,exception);
15243 if (nexus != (Image *) NULL)
15244 *state|=MontageImageState | NextImageState | ExitState;
15245 vid_info.x=(short int) windows->image.x;
15246 vid_info.y=(short int) windows->image.y;
15250 Select a command from the Short Cuts menu.
15252 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15255 nexus=XMagickCommand(display,resource_info,windows,
15256 ShortCutsCommands[entry],&display_image,exception);
15264 XTranslateImage(display,windows,*image,XK_Up);
15272 XTranslateImage(display,windows,*image,XK_Down);
15280 if (event.xbutton.window == windows->magnify.id)
15300 MagnifyCommands[] =
15313 Select a magnify factor from the pop-up menu.
15315 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15317 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15321 if (event.xbutton.window == windows->pan.id)
15323 switch (event.xbutton.button)
15330 XTranslateImage(display,windows,*image,XK_Up);
15338 XTranslateImage(display,windows,*image,XK_Down);
15343 XPanImage(display,windows,&event,exception);
15349 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15351 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15354 case ButtonRelease:
15356 if (IfMagickTrue(display_image->debug) )
15357 (void) LogMagickEvent(X11Event,GetMagickModule(),
15358 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15359 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15362 case ClientMessage:
15364 if (IfMagickTrue(display_image->debug) )
15365 (void) LogMagickEvent(X11Event,GetMagickModule(),
15366 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15367 event.xclient.message_type,event.xclient.format,(unsigned long)
15368 event.xclient.data.l[0]);
15369 if (event.xclient.message_type == windows->im_protocols)
15371 if (*event.xclient.data.l == (long) windows->im_update_widget)
15373 (void) CloneString(&windows->command.name,MagickTitle);
15374 windows->command.data=MagickMenus;
15375 (void) XCommandWidget(display,windows,CommandMenu,
15379 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15382 Update graphic context and window colormap.
15384 for (i=0; i < (int) number_windows; i++)
15386 if (magick_windows[i]->id == windows->icon.id)
15388 context_values.background=pixel->background_color.pixel;
15389 context_values.foreground=pixel->foreground_color.pixel;
15390 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15391 context_mask,&context_values);
15392 (void) XChangeGC(display,magick_windows[i]->widget_context,
15393 context_mask,&context_values);
15394 context_values.background=pixel->foreground_color.pixel;
15395 context_values.foreground=pixel->background_color.pixel;
15396 context_values.plane_mask=context_values.background ^
15397 context_values.foreground;
15398 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15399 (size_t) (context_mask | GCPlaneMask),
15401 magick_windows[i]->attributes.background_pixel=
15402 pixel->background_color.pixel;
15403 magick_windows[i]->attributes.border_pixel=
15404 pixel->border_color.pixel;
15405 magick_windows[i]->attributes.colormap=map_info->colormap;
15406 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15407 (unsigned long) magick_windows[i]->mask,
15408 &magick_windows[i]->attributes);
15410 if (IfMagickTrue(windows->pan.mapped) )
15412 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15413 windows->pan.pixmap);
15414 (void) XClearWindow(display,windows->pan.id);
15415 XDrawPanRectangle(display,windows);
15417 if (windows->backdrop.id != (Window) NULL)
15418 (void) XInstallColormap(display,map_info->colormap);
15421 if (*event.xclient.data.l == (long) windows->im_former_image)
15423 *state|=FormerImageState | ExitState;
15426 if (*event.xclient.data.l == (long) windows->im_next_image)
15428 *state|=NextImageState | ExitState;
15431 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15433 *state|=RetainColorsState;
15436 if (*event.xclient.data.l == (long) windows->im_exit)
15443 if (event.xclient.message_type == windows->dnd_protocols)
15461 Display image named by the Drag-and-Drop selection.
15463 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15465 selection=XInternAtom(display,"DndSelection",MagickFalse);
15466 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15467 MagickPathExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15468 &length,&after,&data);
15469 if ((status != Success) || (length == 0))
15471 if (*event.xclient.data.l == 2)
15476 (void) CopyMagickString(resource_info->image_info->filename,
15477 (char *) data,MagickPathExtent);
15484 if (strncmp((char *) data, "file:", 5) != 0)
15486 (void) XFree((void *) data);
15489 (void) CopyMagickString(resource_info->image_info->filename,
15490 ((char *) data)+5,MagickPathExtent);
15492 nexus=ReadImage(resource_info->image_info,exception);
15493 CatchException(exception);
15494 if (nexus != (Image *) NULL)
15495 *state|=NextImageState | ExitState;
15496 (void) XFree((void *) data);
15500 If client window delete message, exit.
15502 if (event.xclient.message_type != windows->wm_protocols)
15504 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15506 (void) XWithdrawWindow(display,event.xclient.window,
15507 visual_info->screen);
15508 if (event.xclient.window == windows->image.id)
15513 if (event.xclient.window == windows->pan.id)
15516 Restore original image size when pan window is deleted.
15518 windows->image.window_changes.width=windows->image.ximage->width;
15519 windows->image.window_changes.height=windows->image.ximage->height;
15520 (void) XConfigureImage(display,resource_info,windows,
15521 display_image,exception);
15525 case ConfigureNotify:
15527 if (IfMagickTrue(display_image->debug) )
15528 (void) LogMagickEvent(X11Event,GetMagickModule(),
15529 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15530 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15531 event.xconfigure.y,event.xconfigure.send_event);
15532 if (event.xconfigure.window == windows->image.id)
15535 Image window has a new configuration.
15537 if (event.xconfigure.send_event != 0)
15543 Position the transient windows relative of the Image window.
15545 if (windows->command.geometry == (char *) NULL)
15546 if (IfMagickFalse(windows->command.mapped) )
15548 windows->command.x=event.xconfigure.x-
15549 windows->command.width-25;
15550 windows->command.y=event.xconfigure.y;
15551 XConstrainWindowPosition(display,&windows->command);
15552 window_changes.x=windows->command.x;
15553 window_changes.y=windows->command.y;
15554 (void) XReconfigureWMWindow(display,windows->command.id,
15555 windows->command.screen,(unsigned int) (CWX | CWY),
15558 if (windows->widget.geometry == (char *) NULL)
15559 if (IfMagickFalse(windows->widget.mapped) )
15561 windows->widget.x=event.xconfigure.x+
15562 event.xconfigure.width/10;
15563 windows->widget.y=event.xconfigure.y+
15564 event.xconfigure.height/10;
15565 XConstrainWindowPosition(display,&windows->widget);
15566 window_changes.x=windows->widget.x;
15567 window_changes.y=windows->widget.y;
15568 (void) XReconfigureWMWindow(display,windows->widget.id,
15569 windows->widget.screen,(unsigned int) (CWX | CWY),
15572 if (windows->magnify.geometry == (char *) NULL)
15573 if (IfMagickFalse(windows->magnify.mapped) )
15575 windows->magnify.x=event.xconfigure.x+
15576 event.xconfigure.width+25;
15577 windows->magnify.y=event.xconfigure.y;
15578 XConstrainWindowPosition(display,&windows->magnify);
15579 window_changes.x=windows->magnify.x;
15580 window_changes.y=windows->magnify.y;
15581 (void) XReconfigureWMWindow(display,windows->magnify.id,
15582 windows->magnify.screen,(unsigned int) (CWX | CWY),
15585 if (windows->pan.geometry == (char *) NULL)
15586 if (IfMagickFalse(windows->pan.mapped) )
15588 windows->pan.x=event.xconfigure.x+
15589 event.xconfigure.width+25;
15590 windows->pan.y=event.xconfigure.y+
15591 windows->magnify.height+50;
15592 XConstrainWindowPosition(display,&windows->pan);
15593 window_changes.x=windows->pan.x;
15594 window_changes.y=windows->pan.y;
15595 (void) XReconfigureWMWindow(display,windows->pan.id,
15596 windows->pan.screen,(unsigned int) (CWX | CWY),
15600 if ((event.xconfigure.width == (int) windows->image.width) &&
15601 (event.xconfigure.height == (int) windows->image.height))
15603 windows->image.width=(unsigned int) event.xconfigure.width;
15604 windows->image.height=(unsigned int) event.xconfigure.height;
15605 windows->image.x=0;
15606 windows->image.y=0;
15607 if (display_image->montage != (char *) NULL)
15609 windows->image.x=vid_info.x;
15610 windows->image.y=vid_info.y;
15612 if (IfMagickTrue(windows->image.mapped) &&
15613 IfMagickTrue(windows->image.stasis) )
15616 Update image window configuration.
15618 windows->image.window_changes.width=event.xconfigure.width;
15619 windows->image.window_changes.height=event.xconfigure.height;
15620 (void) XConfigureImage(display,resource_info,windows,
15621 display_image,exception);
15624 Update pan window configuration.
15626 if ((event.xconfigure.width < windows->image.ximage->width) ||
15627 (event.xconfigure.height < windows->image.ximage->height))
15629 (void) XMapRaised(display,windows->pan.id);
15630 XDrawPanRectangle(display,windows);
15633 if (IfMagickTrue(windows->pan.mapped) )
15634 (void) XWithdrawWindow(display,windows->pan.id,
15635 windows->pan.screen);
15638 if (event.xconfigure.window == windows->magnify.id)
15644 Magnify window has a new configuration.
15646 windows->magnify.width=(unsigned int) event.xconfigure.width;
15647 windows->magnify.height=(unsigned int) event.xconfigure.height;
15648 if (IfMagickFalse(windows->magnify.mapped) )
15651 while ((int) magnify <= event.xconfigure.width)
15653 while ((int) magnify <= event.xconfigure.height)
15656 if (((int) magnify != event.xconfigure.width) ||
15657 ((int) magnify != event.xconfigure.height))
15659 window_changes.width=(int) magnify;
15660 window_changes.height=(int) magnify;
15661 (void) XReconfigureWMWindow(display,windows->magnify.id,
15662 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15666 if (IfMagickTrue(windows->magnify.mapped) &&
15667 IfMagickTrue(windows->magnify.stasis) )
15669 status=XMakeImage(display,resource_info,&windows->magnify,
15670 display_image,windows->magnify.width,windows->magnify.height,
15672 XMakeMagnifyImage(display,windows,exception);
15676 if (IfMagickTrue(windows->magnify.mapped) &&
15677 (event.xconfigure.window == windows->pan.id))
15680 Pan icon window has a new configuration.
15682 if (event.xconfigure.send_event != 0)
15684 windows->pan.x=event.xconfigure.x;
15685 windows->pan.y=event.xconfigure.y;
15687 windows->pan.width=(unsigned int) event.xconfigure.width;
15688 windows->pan.height=(unsigned int) event.xconfigure.height;
15691 if (event.xconfigure.window == windows->icon.id)
15694 Icon window has a new configuration.
15696 windows->icon.width=(unsigned int) event.xconfigure.width;
15697 windows->icon.height=(unsigned int) event.xconfigure.height;
15702 case DestroyNotify:
15705 Group leader has exited.
15707 if (IfMagickTrue(display_image->debug) )
15708 (void) LogMagickEvent(X11Event,GetMagickModule(),
15709 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15710 if (event.xdestroywindow.window == windows->group_leader.id)
15720 Selectively install colormap.
15722 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15723 if (event.xcrossing.mode != NotifyUngrab)
15724 XInstallColormap(display,map_info->colormap);
15729 if (IfMagickTrue(display_image->debug) )
15730 (void) LogMagickEvent(X11Event,GetMagickModule(),
15731 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15732 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15735 Refresh windows that are now exposed.
15737 if ((event.xexpose.window == windows->image.id) &&
15738 IfMagickTrue(windows->image.mapped) )
15740 XRefreshWindow(display,&windows->image,&event);
15741 delay=display_image->delay/MagickMax(
15742 display_image->ticks_per_second,1L);
15743 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15746 if ((event.xexpose.window == windows->magnify.id) &&
15747 IfMagickTrue(windows->magnify.mapped))
15749 XMakeMagnifyImage(display,windows,exception);
15752 if (event.xexpose.window == windows->pan.id)
15754 XDrawPanRectangle(display,windows);
15757 if (event.xexpose.window == windows->icon.id)
15759 XRefreshWindow(display,&windows->icon,&event);
15770 Respond to a user key press.
15772 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15773 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15774 *(command+length)='\0';
15775 if (IfMagickTrue(display_image->debug) )
15776 (void) LogMagickEvent(X11Event,GetMagickModule(),
15777 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15778 key_symbol,command);
15779 if (event.xkey.window == windows->image.id)
15781 command_type=XImageWindowCommand(display,resource_info,windows,
15782 event.xkey.state,key_symbol,&display_image,exception);
15783 if (command_type != NullCommand)
15784 nexus=XMagickCommand(display,resource_info,windows,command_type,
15785 &display_image,exception);
15787 if (event.xkey.window == windows->magnify.id)
15788 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15790 if (event.xkey.window == windows->pan.id)
15792 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15793 (void) XWithdrawWindow(display,windows->pan.id,
15794 windows->pan.screen);
15796 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15797 XTextViewWidget(display,resource_info,windows,MagickFalse,
15798 "Help Viewer - Image Pan",ImagePanHelp);
15800 XTranslateImage(display,windows,*image,key_symbol);
15802 delay=display_image->delay/MagickMax(
15803 display_image->ticks_per_second,1L);
15804 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15810 Respond to a user key release.
15812 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15813 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15814 if (IfMagickTrue(display_image->debug) )
15815 (void) LogMagickEvent(X11Event,GetMagickModule(),
15816 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15822 Selectively uninstall colormap.
15824 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15825 if (event.xcrossing.mode != NotifyUngrab)
15826 XUninstallColormap(display,map_info->colormap);
15831 if (IfMagickTrue(display_image->debug) )
15832 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15833 event.xmap.window);
15834 if (event.xmap.window == windows->backdrop.id)
15836 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15838 windows->backdrop.mapped=MagickTrue;
15841 if (event.xmap.window == windows->image.id)
15843 if (windows->backdrop.id != (Window) NULL)
15844 (void) XInstallColormap(display,map_info->colormap);
15845 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15847 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15848 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15850 if (((int) windows->image.width < windows->image.ximage->width) ||
15851 ((int) windows->image.height < windows->image.ximage->height))
15852 (void) XMapRaised(display,windows->pan.id);
15853 windows->image.mapped=MagickTrue;
15856 if (event.xmap.window == windows->magnify.id)
15858 XMakeMagnifyImage(display,windows,exception);
15859 windows->magnify.mapped=MagickTrue;
15860 (void) XWithdrawWindow(display,windows->info.id,
15861 windows->info.screen);
15864 if (event.xmap.window == windows->pan.id)
15866 XMakePanImage(display,resource_info,windows,display_image,
15868 windows->pan.mapped=MagickTrue;
15871 if (event.xmap.window == windows->info.id)
15873 windows->info.mapped=MagickTrue;
15876 if (event.xmap.window == windows->icon.id)
15882 Create an icon image.
15884 taint=display_image->taint;
15885 XMakeStandardColormap(display,icon_visual,icon_resources,
15886 display_image,icon_map,icon_pixel,exception);
15887 (void) XMakeImage(display,icon_resources,&windows->icon,
15888 display_image,windows->icon.width,windows->icon.height,
15890 display_image->taint=taint;
15891 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15892 windows->icon.pixmap);
15893 (void) XClearWindow(display,windows->icon.id);
15894 (void) XWithdrawWindow(display,windows->info.id,
15895 windows->info.screen);
15896 windows->icon.mapped=MagickTrue;
15899 if (event.xmap.window == windows->command.id)
15901 windows->command.mapped=MagickTrue;
15904 if (event.xmap.window == windows->popup.id)
15906 windows->popup.mapped=MagickTrue;
15909 if (event.xmap.window == windows->widget.id)
15911 windows->widget.mapped=MagickTrue;
15916 case MappingNotify:
15918 (void) XRefreshKeyboardMapping(&event.xmapping);
15923 case PropertyNotify:
15939 if (IfMagickTrue(display_image->debug) )
15940 (void) LogMagickEvent(X11Event,GetMagickModule(),
15941 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15942 event.xproperty.atom,event.xproperty.state);
15943 if (event.xproperty.atom != windows->im_remote_command)
15946 Display image named by the remote command protocol.
15948 status=XGetWindowProperty(display,event.xproperty.window,
15949 event.xproperty.atom,0L,(long) MagickPathExtent,MagickFalse,(Atom)
15950 AnyPropertyType,&type,&format,&length,&after,&data);
15951 if ((status != Success) || (length == 0))
15953 if (LocaleCompare((char *) data,"-quit") == 0)
15955 XClientMessage(display,windows->image.id,windows->im_protocols,
15956 windows->im_exit,CurrentTime);
15957 (void) XFree((void *) data);
15960 (void) CopyMagickString(resource_info->image_info->filename,
15961 (char *) data,MagickPathExtent);
15962 (void) XFree((void *) data);
15963 nexus=ReadImage(resource_info->image_info,exception);
15964 CatchException(exception);
15965 if (nexus != (Image *) NULL)
15966 *state|=NextImageState | ExitState;
15969 case ReparentNotify:
15971 if (IfMagickTrue(display_image->debug) )
15972 (void) LogMagickEvent(X11Event,GetMagickModule(),
15973 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15974 event.xreparent.window);
15979 if (IfMagickTrue(display_image->debug) )
15980 (void) LogMagickEvent(X11Event,GetMagickModule(),
15981 "Unmap Notify: 0x%lx",event.xunmap.window);
15982 if (event.xunmap.window == windows->backdrop.id)
15984 windows->backdrop.mapped=MagickFalse;
15987 if (event.xunmap.window == windows->image.id)
15989 windows->image.mapped=MagickFalse;
15992 if (event.xunmap.window == windows->magnify.id)
15994 windows->magnify.mapped=MagickFalse;
15997 if (event.xunmap.window == windows->pan.id)
15999 windows->pan.mapped=MagickFalse;
16002 if (event.xunmap.window == windows->info.id)
16004 windows->info.mapped=MagickFalse;
16007 if (event.xunmap.window == windows->icon.id)
16009 if (map_info->colormap == icon_map->colormap)
16010 XConfigureImageColormap(display,resource_info,windows,
16011 display_image,exception);
16012 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16014 windows->icon.mapped=MagickFalse;
16017 if (event.xunmap.window == windows->command.id)
16019 windows->command.mapped=MagickFalse;
16022 if (event.xunmap.window == windows->popup.id)
16024 if (windows->backdrop.id != (Window) NULL)
16025 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16027 windows->popup.mapped=MagickFalse;
16030 if (event.xunmap.window == windows->widget.id)
16032 if (windows->backdrop.id != (Window) NULL)
16033 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16035 windows->widget.mapped=MagickFalse;
16042 if (IfMagickTrue(display_image->debug) )
16043 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16048 } while (!(*state & ExitState));
16049 if ((*state & ExitState) == 0)
16050 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16051 &display_image,exception);
16053 if (IfMagickTrue(resource_info->confirm_edit) )
16056 Query user if image has changed.
16058 if (IfMagickFalse(resource_info->immutable) &&
16059 IfMagickTrue(display_image->taint))
16064 status=XConfirmWidget(display,windows,"Your image changed.",
16065 "Do you want to save it");
16067 *state&=(~ExitState);
16070 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16071 &display_image,exception);
16074 if ((windows->visual_info->klass == GrayScale) ||
16075 (windows->visual_info->klass == PseudoColor) ||
16076 (windows->visual_info->klass == DirectColor))
16079 Withdraw pan and Magnify window.
16081 if (IfMagickTrue(windows->info.mapped) )
16082 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16083 if (IfMagickTrue(windows->magnify.mapped) )
16084 (void) XWithdrawWindow(display,windows->magnify.id,
16085 windows->magnify.screen);
16086 if (IfMagickTrue(windows->command.mapped) )
16087 (void) XWithdrawWindow(display,windows->command.id,
16088 windows->command.screen);
16090 if (IfMagickTrue(windows->pan.mapped) )
16091 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16092 if (IfMagickFalse(resource_info->backdrop) )
16093 if (windows->backdrop.mapped)
16095 (void) XWithdrawWindow(display,windows->backdrop.id,
16096 windows->backdrop.screen);
16097 (void) XDestroyWindow(display,windows->backdrop.id);
16098 windows->backdrop.id=(Window) NULL;
16099 (void) XWithdrawWindow(display,windows->image.id,
16100 windows->image.screen);
16101 (void) XDestroyWindow(display,windows->image.id);
16102 windows->image.id=(Window) NULL;
16104 XSetCursorState(display,windows,MagickTrue);
16105 XCheckRefreshWindows(display,windows);
16106 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16107 *state&=(~ExitState);
16108 if (*state & ExitState)
16111 Free Standard Colormap.
16113 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16114 if (resource_info->map_type == (char *) NULL)
16115 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16119 if (resource_info->copy_image != (Image *) NULL)
16121 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16122 resource_info->copy_image=NewImageList();
16124 DestroyXResources();
16126 (void) XSync(display,MagickFalse);
16128 Restore our progress monitor and warning handlers.
16130 (void) SetErrorHandler(warning_handler);
16131 (void) SetWarningHandler(warning_handler);
16133 Change to home directory.
16135 directory=getcwd(working_directory,MagickPathExtent);
16141 if (*resource_info->home_directory == '\0')
16142 (void) CopyMagickString(resource_info->home_directory,".",MagickPathExtent);
16143 status=chdir(resource_info->home_directory);
16145 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16146 "UnableToOpenFile","%s",resource_info->home_directory);
16148 *image=display_image;
16154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16158 + D i s p l a y I m a g e s %
16162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16164 % DisplayImages() displays an image sequence to any X window screen. It
16165 % returns a value other than 0 if successful. Check the exception member
16166 % of image to determine the reason for any failure.
16168 % The format of the DisplayImages method is:
16170 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16171 % Image *images,ExceptionInfo *exception)
16173 % A description of each parameter follows:
16175 % o image_info: the image info.
16177 % o image: the image.
16179 % o exception: return any errors or warnings in this structure.
16182 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16183 Image *image,ExceptionInfo *exception)
16185 assert(image_info != (const ImageInfo *) NULL);
16186 assert(image_info->signature == MagickSignature);
16187 assert(image != (Image *) NULL);
16188 assert(image->signature == MagickSignature);
16190 if (IfMagickTrue(image->debug) )
16191 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16192 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16193 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
16194 return(MagickFalse);
16198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16202 + R e m o t e D i s p l a y C o m m a n d %
16206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16208 % RemoteDisplayCommand() encourages a remote display program to display the
16209 % specified image filename.
16211 % The format of the RemoteDisplayCommand method is:
16213 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16214 % const char *window,const char *filename,ExceptionInfo *exception)
16216 % A description of each parameter follows:
16218 % o image_info: the image info.
16220 % o window: Specifies the name or id of an X window.
16222 % o filename: the name of the image filename to display.
16224 % o exception: return any errors or warnings in this structure.
16227 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16228 const char *window,const char *filename,ExceptionInfo *exception)
16230 assert(image_info != (const ImageInfo *) NULL);
16231 assert(image_info->signature == MagickSignature);
16232 assert(filename != (char *) NULL);
16234 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16235 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16236 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
16237 return(MagickFalse);