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-2018 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 % https://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/property.h"
81 #include "MagickCore/quantum.h"
82 #include "MagickCore/quantum-private.h"
83 #include "MagickCore/resize.h"
84 #include "MagickCore/resource_.h"
85 #include "MagickCore/shear.h"
86 #include "MagickCore/segment.h"
87 #include "MagickCore/statistic.h"
88 #include "MagickCore/string_.h"
89 #include "MagickCore/string-private.h"
90 #include "MagickCore/transform.h"
91 #include "MagickCore/transform-private.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 == MagickCoreSignature);
1678 assert(images != (Image *) NULL);
1679 assert(images->signature == MagickCoreSignature);
1680 if (images->debug != MagickFalse )
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) memset(&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 == MagickCoreSignature);
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(status != 0 ? MagickTrue : MagickFalse);
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 (windows->info.mapped != MagickFalse )
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 (transparent_pen != MagickFalse )
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 (transparent_box != MagickFalse )
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 (windows->info.mapped != MagickFalse )
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 ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
2263 annotate_info->stencil=OpaqueStencil;
2265 if (transparent_box == MagickFalse)
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=status != 0 ? MagickTrue : MagickFalse;
2815 status=XDisplayBackgroundImage(display,&background_resources,*image,
2817 if (status != MagickFalse)
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);
2934 (void) memset(&segment_info,0,sizeof(segment_info));
2937 if (windows->info.mapped != MagickFalse )
2940 Display pointer position.
2942 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
2943 x+windows->image.x,y+windows->image.y);
2944 XInfoWidget(display,windows,text);
2947 Wait for next event.
2949 XScreenEvent(display,windows,&event,exception);
2950 if (event.xany.window == windows->command.id)
2953 Select a command from the Command widget.
2955 id=XCommandWidget(display,windows,ChopMenu,&event);
2958 switch (ChopCommands[id])
2960 case ChopDirectionCommand:
2963 command[MagickPathExtent];
2974 Select a command from the pop-up menu.
2976 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2978 direction=DirectionCommands[id];
2981 case ChopHelpCommand:
2983 XTextViewWidget(display,resource_info,windows,MagickFalse,
2984 "Help Viewer - Image Chop",ImageChopHelp);
2987 case ChopDismissCommand:
3005 if (event.xbutton.button != Button1)
3007 if (event.xbutton.window != windows->image.id)
3010 User has committed to start point of chopping line.
3012 segment_info.x1=(short int) event.xbutton.x;
3013 segment_info.x2=(short int) event.xbutton.x;
3014 segment_info.y1=(short int) event.xbutton.y;
3015 segment_info.y2=(short int) event.xbutton.y;
3026 command[MagickPathExtent];
3031 if (event.xkey.window != windows->image.id)
3034 Respond to a user key press.
3036 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3037 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3038 switch ((int) key_symbol)
3053 (void) XSetFunction(display,windows->image.highlight_context,
3055 XTextViewWidget(display,resource_info,windows,MagickFalse,
3056 "Help Viewer - Image Chop",ImageChopHelp);
3057 (void) XSetFunction(display,windows->image.highlight_context,
3063 (void) XBell(display,0);
3072 Map and unmap Info widget as text cursor crosses its boundaries.
3076 if (windows->info.mapped != MagickFalse )
3078 if ((x < (int) (windows->info.x+windows->info.width)) &&
3079 (y < (int) (windows->info.y+windows->info.height)))
3080 (void) XWithdrawWindow(display,windows->info.id,
3081 windows->info.screen);
3084 if ((x > (int) (windows->info.x+windows->info.width)) ||
3085 (y > (int) (windows->info.y+windows->info.height)))
3086 (void) XMapWindow(display,windows->info.id);
3089 } while ((state & ExitState) == 0);
3090 (void) XSelectInput(display,windows->image.id,
3091 windows->image.attributes.event_mask);
3092 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3093 if ((state & EscapeState) != 0)
3096 Draw line as pointer moves until the mouse button is released.
3103 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3110 Display info and draw chopping line.
3112 if (windows->info.mapped == MagickFalse)
3113 (void) XMapWindow(display,windows->info.id);
3114 (void) FormatLocaleString(text,MagickPathExtent,
3115 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3116 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3117 XInfoWidget(display,windows,text);
3118 XHighlightLine(display,windows->image.id,
3119 windows->image.highlight_context,&segment_info);
3122 if (windows->info.mapped != MagickFalse )
3123 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3125 Wait for next event.
3127 XScreenEvent(display,windows,&event,exception);
3129 XHighlightLine(display,windows->image.id,
3130 windows->image.highlight_context,&segment_info);
3135 segment_info.x2=(short int) event.xmotion.x;
3136 segment_info.y2=(short int) event.xmotion.y;
3142 User has committed to chopping line.
3144 segment_info.x2=(short int) event.xbutton.x;
3145 segment_info.y2=(short int) event.xbutton.y;
3153 segment_info.x2=(short int) event.xmotion.x;
3154 segment_info.y2=(short int) event.xmotion.y;
3160 Check boundary conditions.
3162 if (segment_info.x2 < 0)
3165 if (segment_info.x2 > windows->image.ximage->width)
3166 segment_info.x2=windows->image.ximage->width;
3167 if (segment_info.y2 < 0)
3170 if (segment_info.y2 > windows->image.ximage->height)
3171 segment_info.y2=windows->image.ximage->height;
3172 distance=(unsigned int)
3173 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3174 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3176 Compute chopping geometry.
3178 if (direction == HorizontalChopCommand)
3180 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3181 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3184 if (segment_info.x1 > (int) segment_info.x2)
3186 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3187 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3193 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3195 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3196 if (segment_info.y1 > segment_info.y2)
3198 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3199 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3202 } while ((state & ExitState) == 0);
3203 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3204 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3208 Image chopping is relative to image configuration.
3210 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3212 XSetCursorState(display,windows,MagickTrue);
3213 XCheckRefreshWindows(display,windows);
3214 windows->image.window_changes.width=windows->image.ximage->width-
3215 (unsigned int) chop_info.width;
3216 windows->image.window_changes.height=windows->image.ximage->height-
3217 (unsigned int) chop_info.height;
3218 width=(unsigned int) (*image)->columns;
3219 height=(unsigned int) (*image)->rows;
3222 if (windows->image.crop_geometry != (char *) NULL)
3223 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3224 scale_factor=(double) width/windows->image.ximage->width;
3226 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3227 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3228 scale_factor=(double) height/windows->image.ximage->height;
3230 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3231 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3235 chop_image=ChopImage(*image,&chop_info,exception);
3236 XSetCursorState(display,windows,MagickFalse);
3237 if (chop_image == (Image *) NULL)
3238 return(MagickFalse);
3239 *image=DestroyImage(*image);
3242 Update image configuration.
3244 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3245 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3254 + X C o l o r E d i t I m a g e %
3258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3260 % XColorEditImage() allows the user to interactively change the color of one
3261 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3263 % The format of the XColorEditImage method is:
3265 % MagickBooleanType XColorEditImage(Display *display,
3266 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3267 % ExceptionInfo *exception)
3269 % A description of each parameter follows:
3271 % o display: Specifies a connection to an X server; returned from
3274 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3276 % o windows: Specifies a pointer to a XWindows structure.
3278 % o image: the image; returned from ReadImage.
3280 % o exception: return any errors or warnings in this structure.
3283 static MagickBooleanType XColorEditImage(Display *display,
3284 XResourceInfo *resource_info,XWindows *windows,Image **image,
3285 ExceptionInfo *exception)
3300 static const ModeType
3301 ColorEditCommands[] =
3303 ColorEditMethodCommand,
3304 ColorEditColorCommand,
3305 ColorEditBorderCommand,
3306 ColorEditFuzzCommand,
3307 ColorEditUndoCommand,
3308 ColorEditHelpCommand,
3309 ColorEditDismissCommand
3313 method = PointMethod;
3319 border_color = { 0, 0, 0, 0, 0, 0 };
3322 command[MagickPathExtent],
3323 text[MagickPathExtent];
3358 (void) CloneString(&windows->command.name,"Color Edit");
3359 windows->command.data=4;
3360 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3361 (void) XMapRaised(display,windows->command.id);
3362 XClientMessage(display,windows->image.id,windows->im_protocols,
3363 windows->im_update_widget,CurrentTime);
3367 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3368 resource_info->background_color,resource_info->foreground_color);
3369 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3371 Track pointer until button 1 is pressed.
3373 XQueryPosition(display,windows->image.id,&x,&y);
3374 (void) XSelectInput(display,windows->image.id,
3375 windows->image.attributes.event_mask | PointerMotionMask);
3379 if (windows->info.mapped != MagickFalse )
3382 Display pointer position.
3384 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
3385 x+windows->image.x,y+windows->image.y);
3386 XInfoWidget(display,windows,text);
3389 Wait for next event.
3391 XScreenEvent(display,windows,&event,exception);
3392 if (event.xany.window == windows->command.id)
3395 Select a command from the Command widget.
3397 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3400 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3403 switch (ColorEditCommands[id])
3405 case ColorEditMethodCommand:
3411 Select a method from the pop-up menu.
3413 methods=(char **) GetCommandOptions(MagickMethodOptions);
3414 if (methods == (char **) NULL)
3416 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3417 (const char **) methods,command);
3419 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3420 MagickFalse,methods[entry]);
3421 methods=DestroyStringList(methods);
3424 case ColorEditColorCommand:
3427 *ColorMenu[MaxNumberPens];
3433 Initialize menu selections.
3435 for (i=0; i < (int) (MaxNumberPens-2); i++)
3436 ColorMenu[i]=resource_info->pen_colors[i];
3437 ColorMenu[MaxNumberPens-2]="Browser...";
3438 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3440 Select a pen color from the pop-up menu.
3442 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3443 (const char **) ColorMenu,command);
3446 if (pen_number == (MaxNumberPens-2))
3449 color_name[MagickPathExtent] = "gray";
3452 Select a pen color from a dialog.
3454 resource_info->pen_colors[pen_number]=color_name;
3455 XColorBrowserWidget(display,windows,"Select",color_name);
3456 if (*color_name == '\0')
3462 (void) XParseColor(display,windows->map_info->colormap,
3463 resource_info->pen_colors[pen_number],&color);
3464 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3465 (unsigned int) MaxColors,&color);
3466 windows->pixel_info->pen_colors[pen_number]=color;
3467 pen_id=(unsigned int) pen_number;
3470 case ColorEditBorderCommand:
3473 *ColorMenu[MaxNumberPens];
3479 Initialize menu selections.
3481 for (i=0; i < (int) (MaxNumberPens-2); i++)
3482 ColorMenu[i]=resource_info->pen_colors[i];
3483 ColorMenu[MaxNumberPens-2]="Browser...";
3484 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3486 Select a pen color from the pop-up menu.
3488 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3489 (const char **) ColorMenu,command);
3492 if (pen_number == (MaxNumberPens-2))
3495 color_name[MagickPathExtent] = "gray";
3498 Select a pen color from a dialog.
3500 resource_info->pen_colors[pen_number]=color_name;
3501 XColorBrowserWidget(display,windows,"Select",color_name);
3502 if (*color_name == '\0')
3508 (void) XParseColor(display,windows->map_info->colormap,
3509 resource_info->pen_colors[pen_number],&border_color);
3512 case ColorEditFuzzCommand:
3515 fuzz[MagickPathExtent];
3530 Select a command from the pop-up menu.
3532 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3538 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
3542 (void) (void) CopyMagickString(fuzz,"20%",MagickPathExtent);
3543 (void) XDialogWidget(display,windows,"Ok",
3544 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3547 (void) ConcatenateMagickString(fuzz,"%",MagickPathExtent);
3548 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
3552 case ColorEditUndoCommand:
3554 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3558 case ColorEditHelpCommand:
3561 XTextViewWidget(display,resource_info,windows,MagickFalse,
3562 "Help Viewer - Image Annotation",ImageColorEditHelp);
3565 case ColorEditDismissCommand:
3575 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3582 if (event.xbutton.button != Button1)
3584 if ((event.xbutton.window != windows->image.id) &&
3585 (event.xbutton.window != windows->magnify.id))
3592 (void) XMagickCommand(display,resource_info,windows,
3593 SaveToUndoBufferCommand,image,exception);
3594 state|=UpdateConfigurationState;
3599 if (event.xbutton.button != Button1)
3601 if ((event.xbutton.window != windows->image.id) &&
3602 (event.xbutton.window != windows->magnify.id))
3605 Update colormap information.
3609 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3610 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3611 XInfoWidget(display,windows,text);
3612 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3613 state&=(~UpdateConfigurationState);
3623 if (event.xkey.window == windows->magnify.id)
3628 window=windows->magnify.id;
3629 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3631 if (event.xkey.window != windows->image.id)
3634 Respond to a user key press.
3636 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3637 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3638 switch ((int) key_symbol)
3652 XTextViewWidget(display,resource_info,windows,MagickFalse,
3653 "Help Viewer - Image Annotation",ImageColorEditHelp);
3658 (void) XBell(display,0);
3667 Map and unmap Info widget as cursor crosses its boundaries.
3671 if (windows->info.mapped != MagickFalse )
3673 if ((x < (int) (windows->info.x+windows->info.width)) &&
3674 (y < (int) (windows->info.y+windows->info.height)))
3675 (void) XWithdrawWindow(display,windows->info.id,
3676 windows->info.screen);
3679 if ((x > (int) (windows->info.x+windows->info.width)) ||
3680 (y > (int) (windows->info.y+windows->info.height)))
3681 (void) XMapWindow(display,windows->info.id);
3687 if (event.xany.window == windows->magnify.id)
3689 x=windows->magnify.x-windows->image.x;
3690 y=windows->magnify.y-windows->image.y;
3694 if ((state & UpdateConfigurationState) != 0)
3704 Pixel edit is relative to image configuration.
3706 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3708 color=windows->pixel_info->pen_colors[pen_id];
3709 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3710 width=(unsigned int) (*image)->columns;
3711 height=(unsigned int) (*image)->rows;
3714 if (windows->image.crop_geometry != (char *) NULL)
3715 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3718 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3720 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3721 if ((x_offset < 0) || (y_offset < 0))
3723 if ((x_offset >= (int) (*image)->columns) ||
3724 (y_offset >= (int) (*image)->rows))
3726 image_view=AcquireAuthenticCacheView(*image,exception);
3733 Update color information using point algorithm.
3735 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3736 return(MagickFalse);
3737 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3738 (ssize_t) y_offset,1,1,exception);
3739 if (q == (Quantum *) NULL)
3741 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3742 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3743 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3744 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3754 Update color information using replace algorithm.
3756 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
3757 x_offset,(ssize_t) y_offset,&target,exception);
3758 if ((*image)->storage_class == DirectClass)
3760 for (y=0; y < (int) (*image)->rows; y++)
3762 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3763 (*image)->columns,1,exception);
3764 if (q == (Quantum *) NULL)
3766 for (x=0; x < (int) (*image)->columns; x++)
3768 GetPixelInfoPixel(*image,q,&pixel);
3769 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3771 SetPixelRed(*image,ScaleShortToQuantum(
3773 SetPixelGreen(*image,ScaleShortToQuantum(
3775 SetPixelBlue(*image,ScaleShortToQuantum(
3778 q+=GetPixelChannels(*image);
3780 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3786 for (i=0; i < (ssize_t) (*image)->colors; i++)
3787 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3789 (*image)->colormap[i].red=(double) ScaleShortToQuantum(
3791 (*image)->colormap[i].green=(double) ScaleShortToQuantum(
3793 (*image)->colormap[i].blue=(double) ScaleShortToQuantum(
3796 (void) SyncImage(*image,exception);
3800 case FloodfillMethod:
3801 case FillToBorderMethod:
3810 Update color information using floodfill algorithm.
3812 (void) GetOneVirtualPixelInfo(*image,
3813 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3814 y_offset,&target,exception);
3815 if (method == FillToBorderMethod)
3818 ScaleShortToQuantum(border_color.red);
3819 target.green=(double)
3820 ScaleShortToQuantum(border_color.green);
3821 target.blue=(double)
3822 ScaleShortToQuantum(border_color.blue);
3824 draw_info=CloneDrawInfo(resource_info->image_info,
3826 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3827 AllCompliance,&draw_info->fill,exception);
3828 (void) FloodfillPaintImage(*image,draw_info,&target,
3829 (ssize_t)x_offset,(ssize_t)y_offset,
3830 method != FloodfillMethod ? MagickTrue : MagickFalse,exception);
3831 draw_info=DestroyDrawInfo(draw_info);
3837 Update color information using reset algorithm.
3839 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3840 return(MagickFalse);
3841 for (y=0; y < (int) (*image)->rows; y++)
3843 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3844 (*image)->columns,1,exception);
3845 if (q == (Quantum *) NULL)
3847 for (x=0; x < (int) (*image)->columns; x++)
3849 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3850 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3851 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3852 q+=GetPixelChannels(*image);
3854 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3860 image_view=DestroyCacheView(image_view);
3861 state&=(~UpdateConfigurationState);
3863 } while ((state & ExitState) == 0);
3864 (void) XSelectInput(display,windows->image.id,
3865 windows->image.attributes.event_mask);
3866 XSetCursorState(display,windows,MagickFalse);
3867 (void) XFreeCursor(display,cursor);
3872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3876 + X C o m p o s i t e I m a g e %
3880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3882 % XCompositeImage() requests an image name from the user, reads the image and
3883 % composites it with the X window image at a location the user chooses with
3886 % The format of the XCompositeImage method is:
3888 % MagickBooleanType XCompositeImage(Display *display,
3889 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3890 % ExceptionInfo *exception)
3892 % A description of each parameter follows:
3894 % o display: Specifies a connection to an X server; returned from
3897 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3899 % o windows: Specifies a pointer to a XWindows structure.
3901 % o image: the image; returned from ReadImage.
3903 % o exception: return any errors or warnings in this structure.
3906 static MagickBooleanType XCompositeImage(Display *display,
3907 XResourceInfo *resource_info,XWindows *windows,Image *image,
3908 ExceptionInfo *exception)
3911 displacement_geometry[MagickPathExtent] = "30x30",
3912 filename[MagickPathExtent] = "\0";
3925 static CompositeOperator
3926 compose = CopyCompositeOp;
3928 static const ModeType
3929 CompositeCommands[] =
3931 CompositeOperatorsCommand,
3932 CompositeDissolveCommand,
3933 CompositeDisplaceCommand,
3934 CompositeHelpCommand,
3935 CompositeDismissCommand
3939 text[MagickPathExtent];
3972 Request image file name from user.
3974 XFileBrowserWidget(display,windows,"Composite",filename);
3975 if (*filename == '\0')
3980 XSetCursorState(display,windows,MagickTrue);
3981 XCheckRefreshWindows(display,windows);
3982 (void) CopyMagickString(resource_info->image_info->filename,filename,
3984 composite_image=ReadImage(resource_info->image_info,exception);
3985 CatchException(exception);
3986 XSetCursorState(display,windows,MagickFalse);
3987 if (composite_image == (Image *) NULL)
3988 return(MagickFalse);
3992 (void) CloneString(&windows->command.name,"Composite");
3993 windows->command.data=1;
3994 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
3995 (void) XMapRaised(display,windows->command.id);
3996 XClientMessage(display,windows->image.id,windows->im_protocols,
3997 windows->im_update_widget,CurrentTime);
3999 Track pointer until button 1 is pressed.
4001 XQueryPosition(display,windows->image.id,&x,&y);
4002 (void) XSelectInput(display,windows->image.id,
4003 windows->image.attributes.event_mask | PointerMotionMask);
4004 composite_info.x=(ssize_t) windows->image.x+x;
4005 composite_info.y=(ssize_t) windows->image.y+y;
4006 composite_info.width=0;
4007 composite_info.height=0;
4008 cursor=XCreateFontCursor(display,XC_ul_angle);
4009 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4014 if (windows->info.mapped != MagickFalse )
4017 Display pointer position.
4019 (void) FormatLocaleString(text,MagickPathExtent," %+ld%+ld ",
4020 (long) composite_info.x,(long) composite_info.y);
4021 XInfoWidget(display,windows,text);
4023 highlight_info=composite_info;
4024 highlight_info.x=composite_info.x-windows->image.x;
4025 highlight_info.y=composite_info.y-windows->image.y;
4026 XHighlightRectangle(display,windows->image.id,
4027 windows->image.highlight_context,&highlight_info);
4029 Wait for next event.
4031 XScreenEvent(display,windows,&event,exception);
4032 XHighlightRectangle(display,windows->image.id,
4033 windows->image.highlight_context,&highlight_info);
4034 if (event.xany.window == windows->command.id)
4037 Select a command from the Command widget.
4039 id=XCommandWidget(display,windows,CompositeMenu,&event);
4042 switch (CompositeCommands[id])
4044 case CompositeOperatorsCommand:
4047 command[MagickPathExtent],
4051 Select a command from the pop-up menu.
4053 operators=GetCommandOptions(MagickComposeOptions);
4054 if (operators == (char **) NULL)
4056 entry=XMenuWidget(display,windows,CompositeMenu[id],
4057 (const char **) operators,command);
4059 compose=(CompositeOperator) ParseCommandOption(
4060 MagickComposeOptions,MagickFalse,operators[entry]);
4061 operators=DestroyStringList(operators);
4064 case CompositeDissolveCommand:
4067 factor[MagickPathExtent] = "20.0";
4070 Dissolve the two images a given percent.
4072 (void) XSetFunction(display,windows->image.highlight_context,
4074 (void) XDialogWidget(display,windows,"Dissolve",
4075 "Enter the blend factor (0.0 - 99.9%):",factor);
4076 (void) XSetFunction(display,windows->image.highlight_context,
4078 if (*factor == '\0')
4080 blend=StringToDouble(factor,(char **) NULL);
4081 compose=DissolveCompositeOp;
4084 case CompositeDisplaceCommand:
4087 Get horizontal and vertical scale displacement geometry.
4089 (void) XSetFunction(display,windows->image.highlight_context,
4091 (void) XDialogWidget(display,windows,"Displace",
4092 "Enter the horizontal and vertical scale:",displacement_geometry);
4093 (void) XSetFunction(display,windows->image.highlight_context,
4095 if (*displacement_geometry == '\0')
4097 compose=DisplaceCompositeOp;
4100 case CompositeHelpCommand:
4102 (void) XSetFunction(display,windows->image.highlight_context,
4104 XTextViewWidget(display,resource_info,windows,MagickFalse,
4105 "Help Viewer - Image Composite",ImageCompositeHelp);
4106 (void) XSetFunction(display,windows->image.highlight_context,
4110 case CompositeDismissCommand:
4128 if (image->debug != MagickFalse )
4129 (void) LogMagickEvent(X11Event,GetMagickModule(),
4130 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4131 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4132 if (event.xbutton.button != Button1)
4134 if (event.xbutton.window != windows->image.id)
4139 composite_info.width=composite_image->columns;
4140 composite_info.height=composite_image->rows;
4141 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4142 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4143 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4148 if (image->debug != MagickFalse )
4149 (void) LogMagickEvent(X11Event,GetMagickModule(),
4150 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4151 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4152 if (event.xbutton.button != Button1)
4154 if (event.xbutton.window != windows->image.id)
4156 if ((composite_info.width != 0) && (composite_info.height != 0))
4159 User has selected the location of the composite image.
4161 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4162 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4172 command[MagickPathExtent];
4180 if (event.xkey.window != windows->image.id)
4183 Respond to a user key press.
4185 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4186 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4187 *(command+length)='\0';
4188 if (image->debug != MagickFalse )
4189 (void) LogMagickEvent(X11Event,GetMagickModule(),
4190 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4191 switch ((int) key_symbol)
4199 composite_image=DestroyImage(composite_image);
4207 (void) XSetFunction(display,windows->image.highlight_context,
4209 XTextViewWidget(display,resource_info,windows,MagickFalse,
4210 "Help Viewer - Image Composite",ImageCompositeHelp);
4211 (void) XSetFunction(display,windows->image.highlight_context,
4217 (void) XBell(display,0);
4226 Map and unmap Info widget as text cursor crosses its boundaries.
4230 if (windows->info.mapped != MagickFalse )
4232 if ((x < (int) (windows->info.x+windows->info.width)) &&
4233 (y < (int) (windows->info.y+windows->info.height)))
4234 (void) XWithdrawWindow(display,windows->info.id,
4235 windows->info.screen);
4238 if ((x > (int) (windows->info.x+windows->info.width)) ||
4239 (y > (int) (windows->info.y+windows->info.height)))
4240 (void) XMapWindow(display,windows->info.id);
4241 composite_info.x=(ssize_t) windows->image.x+x;
4242 composite_info.y=(ssize_t) windows->image.y+y;
4247 if (image->debug != MagickFalse )
4248 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4253 } while ((state & ExitState) == 0);
4254 (void) XSelectInput(display,windows->image.id,
4255 windows->image.attributes.event_mask);
4256 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4257 XSetCursorState(display,windows,MagickFalse);
4258 (void) XFreeCursor(display,cursor);
4259 if ((state & EscapeState) != 0)
4262 Image compositing is relative to image configuration.
4264 XSetCursorState(display,windows,MagickTrue);
4265 XCheckRefreshWindows(display,windows);
4266 width=(unsigned int) image->columns;
4267 height=(unsigned int) image->rows;
4270 if (windows->image.crop_geometry != (char *) NULL)
4271 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4272 scale_factor=(double) width/windows->image.ximage->width;
4273 composite_info.x+=x;
4274 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4275 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4276 scale_factor=(double) height/windows->image.ximage->height;
4277 composite_info.y+=y;
4278 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4279 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4280 if ((composite_info.width != composite_image->columns) ||
4281 (composite_info.height != composite_image->rows))
4287 Scale composite image.
4289 resize_image=ResizeImage(composite_image,composite_info.width,
4290 composite_info.height,composite_image->filter,exception);
4291 composite_image=DestroyImage(composite_image);
4292 if (resize_image == (Image *) NULL)
4294 XSetCursorState(display,windows,MagickFalse);
4295 return(MagickFalse);
4297 composite_image=resize_image;
4299 if (compose == DisplaceCompositeOp)
4300 (void) SetImageArtifact(composite_image,"compose:args",
4301 displacement_geometry);
4320 Create mattes for blending.
4322 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4323 opacity=(Quantum) (ScaleQuantumToChar(QuantumRange)-
4324 ((ssize_t) ScaleQuantumToChar(QuantumRange)*blend)/100);
4325 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4326 return(MagickFalse);
4327 image->alpha_trait=BlendPixelTrait;
4328 image_view=AcquireAuthenticCacheView(image,exception);
4329 for (y=0; y < (int) image->rows; y++)
4331 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4333 if (q == (Quantum *) NULL)
4335 for (x=0; x < (int) image->columns; x++)
4337 SetPixelAlpha(image,opacity,q);
4338 q+=GetPixelChannels(image);
4340 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4343 image_view=DestroyCacheView(image_view);
4346 Composite image with X Image window.
4348 (void) CompositeImage(image,composite_image,compose,MagickTrue,
4349 composite_info.x,composite_info.y,exception);
4350 composite_image=DestroyImage(composite_image);
4351 XSetCursorState(display,windows,MagickFalse);
4353 Update image configuration.
4355 XConfigureImageColormap(display,resource_info,windows,image,exception);
4356 (void) XConfigureImage(display,resource_info,windows,image,exception);
4361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4365 + X C o n f i g u r e I m a g e %
4369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4371 % XConfigureImage() creates a new X image. It also notifies the window
4372 % manager of the new image size and configures the transient widows.
4374 % The format of the XConfigureImage method is:
4376 % MagickBooleanType XConfigureImage(Display *display,
4377 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4378 % ExceptionInfo *exception)
4380 % A description of each parameter follows:
4382 % o display: Specifies a connection to an X server; returned from
4385 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4387 % o windows: Specifies a pointer to a XWindows structure.
4389 % o image: the image.
4391 % o exception: return any errors or warnings in this structure.
4393 % o exception: return any errors or warnings in this structure.
4396 static MagickBooleanType XConfigureImage(Display *display,
4397 XResourceInfo *resource_info,XWindows *windows,Image *image,
4398 ExceptionInfo *exception)
4401 geometry[MagickPathExtent];
4422 Dismiss if window dimensions are zero.
4424 width=(unsigned int) windows->image.window_changes.width;
4425 height=(unsigned int) windows->image.window_changes.height;
4426 if (image->debug != MagickFalse )
4427 (void) LogMagickEvent(X11Event,GetMagickModule(),
4428 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4429 windows->image.ximage->height,(double) width,(double) height);
4430 if ((width*height) == 0)
4435 Resize image to fit Image window dimensions.
4437 XSetCursorState(display,windows,MagickTrue);
4438 (void) XFlush(display);
4439 if (((int) width != windows->image.ximage->width) ||
4440 ((int) height != windows->image.ximage->height))
4441 image->taint=MagickTrue;
4442 windows->magnify.x=(int)
4443 width*windows->magnify.x/windows->image.ximage->width;
4444 windows->magnify.y=(int)
4445 height*windows->magnify.y/windows->image.ximage->height;
4446 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4447 windows->image.y=(int)
4448 (height*windows->image.y/windows->image.ximage->height);
4449 status=XMakeImage(display,resource_info,&windows->image,image,
4450 (unsigned int) width,(unsigned int) height,exception);
4451 if (status == MagickFalse)
4452 XNoticeWidget(display,windows,"Unable to configure X image:",
4453 windows->image.name);
4455 Notify window manager of the new configuration.
4457 if (resource_info->image_geometry != (char *) NULL)
4458 (void) FormatLocaleString(geometry,MagickPathExtent,"%s>!",
4459 resource_info->image_geometry);
4461 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
4462 XDisplayWidth(display,windows->image.screen),
4463 XDisplayHeight(display,windows->image.screen));
4464 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4465 window_changes.width=(int) width;
4466 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4467 window_changes.width=XDisplayWidth(display,windows->image.screen);
4468 window_changes.height=(int) height;
4469 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4470 window_changes.height=XDisplayHeight(display,windows->image.screen);
4471 mask=(size_t) (CWWidth | CWHeight);
4472 if (resource_info->backdrop)
4475 window_changes.x=(int)
4476 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4477 window_changes.y=(int)
4478 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4480 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4481 (unsigned int) mask,&window_changes);
4482 (void) XClearWindow(display,windows->image.id);
4483 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4485 Update Magnify window configuration.
4487 if (windows->magnify.mapped != MagickFalse )
4488 XMakeMagnifyImage(display,windows,exception);
4489 windows->pan.crop_geometry=windows->image.crop_geometry;
4490 XBestIconSize(display,&windows->pan,image);
4491 while (((windows->pan.width << 1) < MaxIconSize) &&
4492 ((windows->pan.height << 1) < MaxIconSize))
4494 windows->pan.width<<=1;
4495 windows->pan.height<<=1;
4497 if (windows->pan.geometry != (char *) NULL)
4498 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4499 &windows->pan.width,&windows->pan.height);
4500 window_changes.width=(int) windows->pan.width;
4501 window_changes.height=(int) windows->pan.height;
4502 size_hints=XAllocSizeHints();
4503 if (size_hints != (XSizeHints *) NULL)
4508 size_hints->flags=PSize | PMinSize | PMaxSize;
4509 size_hints->width=window_changes.width;
4510 size_hints->height=window_changes.height;
4511 size_hints->min_width=size_hints->width;
4512 size_hints->min_height=size_hints->height;
4513 size_hints->max_width=size_hints->width;
4514 size_hints->max_height=size_hints->height;
4515 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4516 (void) XFree((void *) size_hints);
4518 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4519 (unsigned int) (CWWidth | CWHeight),&window_changes);
4521 Update icon window configuration.
4523 windows->icon.crop_geometry=windows->image.crop_geometry;
4524 XBestIconSize(display,&windows->icon,image);
4525 window_changes.width=(int) windows->icon.width;
4526 window_changes.height=(int) windows->icon.height;
4527 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4528 (unsigned int) (CWWidth | CWHeight),&window_changes);
4529 XSetCursorState(display,windows,MagickFalse);
4530 return(status != 0 ? MagickTrue : MagickFalse);
4534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4538 + X C r o p I m a g e %
4542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4544 % XCropImage() allows the user to select a region of the image and crop, copy,
4545 % or cut it. For copy or cut, the image can subsequently be composited onto
4546 % the image with XPasteImage.
4548 % The format of the XCropImage method is:
4550 % MagickBooleanType XCropImage(Display *display,
4551 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4552 % const ClipboardMode mode,ExceptionInfo *exception)
4554 % A description of each parameter follows:
4556 % o display: Specifies a connection to an X server; returned from
4559 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4561 % o windows: Specifies a pointer to a XWindows structure.
4563 % o image: the image; returned from ReadImage.
4565 % o mode: This unsigned value specified whether the image should be
4566 % cropped, copied, or cut.
4568 % o exception: return any errors or warnings in this structure.
4571 static MagickBooleanType XCropImage(Display *display,
4572 XResourceInfo *resource_info,XWindows *windows,Image *image,
4573 const ClipboardMode mode,ExceptionInfo *exception)
4582 *RectifyModeMenu[] =
4590 static const ModeType
4600 RectifyDismissCommand
4607 command[MagickPathExtent],
4608 text[MagickPathExtent];
4651 (void) CloneString(&windows->command.name,"Copy");
4656 (void) CloneString(&windows->command.name,"Crop");
4661 (void) CloneString(&windows->command.name,"Cut");
4665 RectifyModeMenu[0]=windows->command.name;
4666 windows->command.data=0;
4667 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4668 (void) XMapRaised(display,windows->command.id);
4669 XClientMessage(display,windows->image.id,windows->im_protocols,
4670 windows->im_update_widget,CurrentTime);
4672 Track pointer until button 1 is pressed.
4674 XQueryPosition(display,windows->image.id,&x,&y);
4675 (void) XSelectInput(display,windows->image.id,
4676 windows->image.attributes.event_mask | PointerMotionMask);
4677 crop_info.x=(ssize_t) windows->image.x+x;
4678 crop_info.y=(ssize_t) windows->image.y+y;
4681 cursor=XCreateFontCursor(display,XC_fleur);
4685 if (windows->info.mapped != MagickFalse )
4688 Display pointer position.
4690 (void) FormatLocaleString(text,MagickPathExtent," %+ld%+ld ",
4691 (long) crop_info.x,(long) crop_info.y);
4692 XInfoWidget(display,windows,text);
4695 Wait for next event.
4697 XScreenEvent(display,windows,&event,exception);
4698 if (event.xany.window == windows->command.id)
4701 Select a command from the Command widget.
4703 id=XCommandWidget(display,windows,CropModeMenu,&event);
4706 switch (CropCommands[id])
4708 case CropHelpCommand:
4714 XTextViewWidget(display,resource_info,windows,MagickFalse,
4715 "Help Viewer - Image Copy",ImageCopyHelp);
4720 XTextViewWidget(display,resource_info,windows,MagickFalse,
4721 "Help Viewer - Image Crop",ImageCropHelp);
4726 XTextViewWidget(display,resource_info,windows,MagickFalse,
4727 "Help Viewer - Image Cut",ImageCutHelp);
4733 case CropDismissCommand:
4751 if (event.xbutton.button != Button1)
4753 if (event.xbutton.window != windows->image.id)
4756 Note first corner of cropping rectangle-- exit loop.
4758 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4759 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4760 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4770 if (event.xkey.window != windows->image.id)
4773 Respond to a user key press.
4775 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4776 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4777 switch ((int) key_symbol)
4796 XTextViewWidget(display,resource_info,windows,MagickFalse,
4797 "Help Viewer - Image Copy",ImageCopyHelp);
4802 XTextViewWidget(display,resource_info,windows,MagickFalse,
4803 "Help Viewer - Image Crop",ImageCropHelp);
4808 XTextViewWidget(display,resource_info,windows,MagickFalse,
4809 "Help Viewer - Image Cut",ImageCutHelp);
4817 (void) XBell(display,0);
4825 if (event.xmotion.window != windows->image.id)
4828 Map and unmap Info widget as text cursor crosses its boundaries.
4832 if (windows->info.mapped != MagickFalse )
4834 if ((x < (int) (windows->info.x+windows->info.width)) &&
4835 (y < (int) (windows->info.y+windows->info.height)))
4836 (void) XWithdrawWindow(display,windows->info.id,
4837 windows->info.screen);
4840 if ((x > (int) (windows->info.x+windows->info.width)) ||
4841 (y > (int) (windows->info.y+windows->info.height)))
4842 (void) XMapWindow(display,windows->info.id);
4843 crop_info.x=(ssize_t) windows->image.x+x;
4844 crop_info.y=(ssize_t) windows->image.y+y;
4850 } while ((state & ExitState) == 0);
4851 (void) XSelectInput(display,windows->image.id,
4852 windows->image.attributes.event_mask);
4853 if ((state & EscapeState) != 0)
4856 User want to exit without cropping.
4858 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4859 (void) XFreeCursor(display,cursor);
4862 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4866 Size rectangle as pointer moves until the mouse button is released.
4868 x=(int) crop_info.x;
4869 y=(int) crop_info.y;
4875 highlight_info=crop_info;
4876 highlight_info.x=crop_info.x-windows->image.x;
4877 highlight_info.y=crop_info.y-windows->image.y;
4878 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4881 Display info and draw cropping rectangle.
4883 if (windows->info.mapped == MagickFalse)
4884 (void) XMapWindow(display,windows->info.id);
4885 (void) FormatLocaleString(text,MagickPathExtent,
4886 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4887 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4888 XInfoWidget(display,windows,text);
4889 XHighlightRectangle(display,windows->image.id,
4890 windows->image.highlight_context,&highlight_info);
4893 if (windows->info.mapped != MagickFalse )
4894 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4896 Wait for next event.
4898 XScreenEvent(display,windows,&event,exception);
4899 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4900 XHighlightRectangle(display,windows->image.id,
4901 windows->image.highlight_context,&highlight_info);
4906 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4907 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4913 User has committed to cropping rectangle.
4915 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4916 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4917 XSetCursorState(display,windows,MagickFalse);
4919 windows->command.data=0;
4920 (void) XCommandWidget(display,windows,RectifyModeMenu,
4928 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4929 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4934 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4935 ((state & ExitState) != 0))
4938 Check boundary conditions.
4940 if (crop_info.x < 0)
4943 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4944 crop_info.x=(ssize_t) windows->image.ximage->width;
4945 if ((int) crop_info.x < x)
4946 crop_info.width=(unsigned int) (x-crop_info.x);
4949 crop_info.width=(unsigned int) (crop_info.x-x);
4950 crop_info.x=(ssize_t) x;
4952 if (crop_info.y < 0)
4955 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4956 crop_info.y=(ssize_t) windows->image.ximage->height;
4957 if ((int) crop_info.y < y)
4958 crop_info.height=(unsigned int) (y-crop_info.y);
4961 crop_info.height=(unsigned int) (crop_info.y-y);
4962 crop_info.y=(ssize_t) y;
4965 } while ((state & ExitState) == 0);
4967 Wait for user to grab a corner of the rectangle or press return.
4970 (void) XMapWindow(display,windows->info.id);
4973 if (windows->info.mapped != MagickFalse )
4976 Display pointer position.
4978 (void) FormatLocaleString(text,MagickPathExtent,
4979 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4980 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4981 XInfoWidget(display,windows,text);
4983 highlight_info=crop_info;
4984 highlight_info.x=crop_info.x-windows->image.x;
4985 highlight_info.y=crop_info.y-windows->image.y;
4986 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
4992 XHighlightRectangle(display,windows->image.id,
4993 windows->image.highlight_context,&highlight_info);
4994 XScreenEvent(display,windows,&event,exception);
4995 if (event.xany.window == windows->command.id)
4998 Select a command from the Command widget.
5000 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5001 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5002 (void) XSetFunction(display,windows->image.highlight_context,
5004 XHighlightRectangle(display,windows->image.id,
5005 windows->image.highlight_context,&highlight_info);
5007 switch (RectifyCommands[id])
5009 case RectifyCopyCommand:
5014 case RectifyHelpCommand:
5016 (void) XSetFunction(display,windows->image.highlight_context,
5022 XTextViewWidget(display,resource_info,windows,MagickFalse,
5023 "Help Viewer - Image Copy",ImageCopyHelp);
5028 XTextViewWidget(display,resource_info,windows,MagickFalse,
5029 "Help Viewer - Image Crop",ImageCropHelp);
5034 XTextViewWidget(display,resource_info,windows,MagickFalse,
5035 "Help Viewer - Image Cut",ImageCutHelp);
5039 (void) XSetFunction(display,windows->image.highlight_context,
5043 case RectifyDismissCommand:
5057 XHighlightRectangle(display,windows->image.id,
5058 windows->image.highlight_context,&highlight_info);
5063 if (event.xbutton.button != Button1)
5065 if (event.xbutton.window != windows->image.id)
5067 x=windows->image.x+event.xbutton.x;
5068 y=windows->image.y+event.xbutton.y;
5069 if ((x < (int) (crop_info.x+RoiDelta)) &&
5070 (x > (int) (crop_info.x-RoiDelta)) &&
5071 (y < (int) (crop_info.y+RoiDelta)) &&
5072 (y > (int) (crop_info.y-RoiDelta)))
5074 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5075 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5076 state|=UpdateConfigurationState;
5079 if ((x < (int) (crop_info.x+RoiDelta)) &&
5080 (x > (int) (crop_info.x-RoiDelta)) &&
5081 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5082 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5084 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5085 state|=UpdateConfigurationState;
5088 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5089 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5090 (y < (int) (crop_info.y+RoiDelta)) &&
5091 (y > (int) (crop_info.y-RoiDelta)))
5093 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5094 state|=UpdateConfigurationState;
5097 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5098 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5099 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5100 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5102 state|=UpdateConfigurationState;
5108 if (event.xbutton.window == windows->pan.id)
5109 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5110 (highlight_info.y != crop_info.y-windows->image.y))
5111 XHighlightRectangle(display,windows->image.id,
5112 windows->image.highlight_context,&highlight_info);
5113 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5114 event.xbutton.time);
5119 if (event.xexpose.window == windows->image.id)
5120 if (event.xexpose.count == 0)
5122 event.xexpose.x=(int) highlight_info.x;
5123 event.xexpose.y=(int) highlight_info.y;
5124 event.xexpose.width=(int) highlight_info.width;
5125 event.xexpose.height=(int) highlight_info.height;
5126 XRefreshWindow(display,&windows->image,&event);
5128 if (event.xexpose.window == windows->info.id)
5129 if (event.xexpose.count == 0)
5130 XInfoWidget(display,windows,text);
5135 if (event.xkey.window != windows->image.id)
5138 Respond to a user key press.
5140 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5141 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5142 switch ((int) key_symbol)
5155 crop_info.x=(ssize_t) (windows->image.width/2L-crop_info.width/
5157 crop_info.y=(ssize_t) (windows->image.height/2L-crop_info.height/
5190 (void) XSetFunction(display,windows->image.highlight_context,
5196 XTextViewWidget(display,resource_info,windows,MagickFalse,
5197 "Help Viewer - Image Copy",ImageCopyHelp);
5202 XTextViewWidget(display,resource_info,windows,MagickFalse,
5203 "Help Viewer - Image Cropg",ImageCropHelp);
5208 XTextViewWidget(display,resource_info,windows,MagickFalse,
5209 "Help Viewer - Image Cutg",ImageCutHelp);
5213 (void) XSetFunction(display,windows->image.highlight_context,
5219 (void) XBell(display,0);
5223 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5231 if (event.xmotion.window != windows->image.id)
5234 Map and unmap Info widget as text cursor crosses its boundaries.
5238 if (windows->info.mapped != MagickFalse )
5240 if ((x < (int) (windows->info.x+windows->info.width)) &&
5241 (y < (int) (windows->info.y+windows->info.height)))
5242 (void) XWithdrawWindow(display,windows->info.id,
5243 windows->info.screen);
5246 if ((x > (int) (windows->info.x+windows->info.width)) ||
5247 (y > (int) (windows->info.y+windows->info.height)))
5248 (void) XMapWindow(display,windows->info.id);
5249 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5250 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5253 case SelectionRequest:
5258 XSelectionRequestEvent
5262 Set primary selection.
5264 (void) FormatLocaleString(text,MagickPathExtent,
5265 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5266 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5267 request=(&(event.xselectionrequest));
5268 (void) XChangeProperty(request->display,request->requestor,
5269 request->property,request->target,8,PropModeReplace,
5270 (unsigned char *) text,(int) strlen(text));
5271 notify.type=SelectionNotify;
5272 notify.display=request->display;
5273 notify.requestor=request->requestor;
5274 notify.selection=request->selection;
5275 notify.target=request->target;
5276 notify.time=request->time;
5277 if (request->property == None)
5278 notify.property=request->target;
5280 notify.property=request->property;
5281 (void) XSendEvent(request->display,request->requestor,False,0,
5282 (XEvent *) ¬ify);
5287 if ((state & UpdateConfigurationState) != 0)
5289 (void) XPutBackEvent(display,&event);
5290 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5293 } while ((state & ExitState) == 0);
5294 } while ((state & ExitState) == 0);
5295 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5296 XSetCursorState(display,windows,MagickFalse);
5297 if ((state & EscapeState) != 0)
5299 if (mode == CropMode)
5300 if (((int) crop_info.width != windows->image.ximage->width) ||
5301 ((int) crop_info.height != windows->image.ximage->height))
5304 Reconfigure Image window as defined by cropping rectangle.
5306 XSetCropGeometry(display,windows,&crop_info,image);
5307 windows->image.window_changes.width=(int) crop_info.width;
5308 windows->image.window_changes.height=(int) crop_info.height;
5309 (void) XConfigureImage(display,resource_info,windows,image,exception);
5313 Copy image before applying image transforms.
5315 XSetCursorState(display,windows,MagickTrue);
5316 XCheckRefreshWindows(display,windows);
5317 width=(unsigned int) image->columns;
5318 height=(unsigned int) image->rows;
5321 if (windows->image.crop_geometry != (char *) NULL)
5322 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5323 scale_factor=(double) width/windows->image.ximage->width;
5325 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5326 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5327 scale_factor=(double) height/windows->image.ximage->height;
5329 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5330 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5331 crop_image=CropImage(image,&crop_info,exception);
5332 XSetCursorState(display,windows,MagickFalse);
5333 if (crop_image == (Image *) NULL)
5334 return(MagickFalse);
5335 if (resource_info->copy_image != (Image *) NULL)
5336 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5337 resource_info->copy_image=crop_image;
5338 if (mode == CopyMode)
5340 (void) XConfigureImage(display,resource_info,windows,image,exception);
5346 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
5347 return(MagickFalse);
5348 image->alpha_trait=BlendPixelTrait;
5349 image_view=AcquireAuthenticCacheView(image,exception);
5350 for (y=0; y < (int) crop_info.height; y++)
5352 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5353 crop_info.width,1,exception);
5354 if (q == (Quantum *) NULL)
5356 for (x=0; x < (int) crop_info.width; x++)
5358 SetPixelAlpha(image,TransparentAlpha,q);
5359 q+=GetPixelChannels(image);
5361 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
5364 image_view=DestroyCacheView(image_view);
5366 Update image configuration.
5368 XConfigureImageColormap(display,resource_info,windows,image,exception);
5369 (void) XConfigureImage(display,resource_info,windows,image,exception);
5374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5378 + X D r a w I m a g e %
5382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5384 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5387 % The format of the XDrawEditImage method is:
5389 % MagickBooleanType XDrawEditImage(Display *display,
5390 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5391 % ExceptionInfo *exception)
5393 % A description of each parameter follows:
5395 % o display: Specifies a connection to an X server; returned from
5398 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5400 % o windows: Specifies a pointer to a XWindows structure.
5402 % o image: the image.
5404 % o exception: return any errors or warnings in this structure.
5407 static MagickBooleanType XDrawEditImage(Display *display,
5408 XResourceInfo *resource_info,XWindows *windows,Image **image,
5409 ExceptionInfo *exception)
5425 element = PointElement;
5427 static const ModeType
5440 stipple = (Pixmap) NULL;
5447 command[MagickPathExtent],
5448 text[MagickPathExtent];
5497 Allocate polygon info.
5499 max_coordinates=2048;
5500 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5501 sizeof(*coordinate_info));
5502 if (coordinate_info == (XPoint *) NULL)
5504 (void) ThrowMagickException(exception,GetMagickModule(),
5505 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5506 return(MagickFalse);
5511 (void) CloneString(&windows->command.name,"Draw");
5512 windows->command.data=4;
5513 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5514 (void) XMapRaised(display,windows->command.id);
5515 XClientMessage(display,windows->image.id,windows->im_protocols,
5516 windows->im_update_widget,CurrentTime);
5518 Wait for first button press.
5520 root_window=XRootWindow(display,XDefaultScreen(display));
5521 draw_info.stencil=OpaqueStencil;
5523 cursor=XCreateFontCursor(display,XC_tcross);
5526 XQueryPosition(display,windows->image.id,&x,&y);
5527 (void) XSelectInput(display,windows->image.id,
5528 windows->image.attributes.event_mask | PointerMotionMask);
5529 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5533 if (windows->info.mapped != MagickFalse )
5536 Display pointer position.
5538 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
5539 x+windows->image.x,y+windows->image.y);
5540 XInfoWidget(display,windows,text);
5543 Wait for next event.
5545 XScreenEvent(display,windows,&event,exception);
5546 if (event.xany.window == windows->command.id)
5549 Select a command from the Command widget.
5551 id=XCommandWidget(display,windows,DrawMenu,&event);
5554 switch (DrawCommands[id])
5556 case DrawElementCommand:
5575 Select a command from the pop-up menu.
5577 element=(ElementType) (XMenuWidget(display,windows,
5578 DrawMenu[id],Elements,command)+1);
5581 case DrawColorCommand:
5584 *ColorMenu[MaxNumberPens+1];
5596 Initialize menu selections.
5598 for (i=0; i < (int) (MaxNumberPens-2); i++)
5599 ColorMenu[i]=resource_info->pen_colors[i];
5600 ColorMenu[MaxNumberPens-2]="transparent";
5601 ColorMenu[MaxNumberPens-1]="Browser...";
5602 ColorMenu[MaxNumberPens]=(char *) NULL;
5604 Select a pen color from the pop-up menu.
5606 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5607 (const char **) ColorMenu,command);
5610 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5612 if (transparent != MagickFalse )
5614 draw_info.stencil=TransparentStencil;
5617 if (pen_number == (MaxNumberPens-1))
5620 color_name[MagickPathExtent] = "gray";
5623 Select a pen color from a dialog.
5625 resource_info->pen_colors[pen_number]=color_name;
5626 XColorBrowserWidget(display,windows,"Select",color_name);
5627 if (*color_name == '\0')
5633 (void) XParseColor(display,windows->map_info->colormap,
5634 resource_info->pen_colors[pen_number],&color);
5635 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5636 (unsigned int) MaxColors,&color);
5637 windows->pixel_info->pen_colors[pen_number]=color;
5638 pen_id=(unsigned int) pen_number;
5639 draw_info.stencil=OpaqueStencil;
5642 case DrawStippleCommand:
5654 filename[MagickPathExtent] = "\0";
5671 Select a command from the pop-up menu.
5673 StipplesMenu[7]="Open...";
5674 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5678 if (stipple != (Pixmap) NULL)
5679 (void) XFreePixmap(display,stipple);
5680 stipple=(Pixmap) NULL;
5687 stipple=XCreateBitmapFromData(display,root_window,
5688 (char *) BricksBitmap,BricksWidth,BricksHeight);
5693 stipple=XCreateBitmapFromData(display,root_window,
5694 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5699 stipple=XCreateBitmapFromData(display,root_window,
5700 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5705 stipple=XCreateBitmapFromData(display,root_window,
5706 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5711 stipple=XCreateBitmapFromData(display,root_window,
5712 (char *) WavyBitmap,WavyWidth,WavyHeight);
5717 stipple=XCreateBitmapFromData(display,root_window,
5718 (char *) HighlightBitmap,HighlightWidth,
5725 stipple=XCreateBitmapFromData(display,root_window,
5726 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5732 XFileBrowserWidget(display,windows,"Stipple",filename);
5733 if (*filename == '\0')
5738 XSetCursorState(display,windows,MagickTrue);
5739 XCheckRefreshWindows(display,windows);
5740 image_info=AcquireImageInfo();
5741 (void) CopyMagickString(image_info->filename,filename,
5743 stipple_image=ReadImage(image_info,exception);
5744 CatchException(exception);
5745 XSetCursorState(display,windows,MagickFalse);
5746 if (stipple_image == (Image *) NULL)
5748 (void) AcquireUniqueFileResource(filename);
5749 (void) FormatLocaleString(stipple_image->filename,
5750 MagickPathExtent,"xbm:%s",filename);
5751 (void) WriteImage(image_info,stipple_image,exception);
5752 stipple_image=DestroyImage(stipple_image);
5753 image_info=DestroyImageInfo(image_info);
5754 status=XReadBitmapFile(display,root_window,filename,&width,
5755 &height,&stipple,&x,&y);
5756 (void) RelinquishUniqueFileResource(filename);
5757 if ((status != BitmapSuccess) != 0)
5758 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5762 case DrawWidthCommand:
5765 width[MagickPathExtent] = "0";
5780 Select a command from the pop-up menu.
5782 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5788 line_width=(unsigned int) StringToUnsignedLong(
5792 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5796 line_width=(unsigned int) StringToUnsignedLong(width);
5799 case DrawUndoCommand:
5801 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5805 case DrawHelpCommand:
5807 XTextViewWidget(display,resource_info,windows,MagickFalse,
5808 "Help Viewer - Image Rotation",ImageDrawHelp);
5809 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5812 case DrawDismissCommand:
5824 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5831 if (event.xbutton.button != Button1)
5833 if (event.xbutton.window != windows->image.id)
5852 if (event.xkey.window != windows->image.id)
5855 Respond to a user key press.
5857 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5858 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5859 switch ((int) key_symbol)
5874 XTextViewWidget(display,resource_info,windows,MagickFalse,
5875 "Help Viewer - Image Rotation",ImageDrawHelp);
5880 (void) XBell(display,0);
5889 Map and unmap Info widget as text cursor crosses its boundaries.
5893 if (windows->info.mapped != MagickFalse )
5895 if ((x < (int) (windows->info.x+windows->info.width)) &&
5896 (y < (int) (windows->info.y+windows->info.height)))
5897 (void) XWithdrawWindow(display,windows->info.id,
5898 windows->info.screen);
5901 if ((x > (int) (windows->info.x+windows->info.width)) ||
5902 (y > (int) (windows->info.y+windows->info.height)))
5903 (void) XMapWindow(display,windows->info.id);
5907 } while ((state & ExitState) == 0);
5908 (void) XSelectInput(display,windows->image.id,
5909 windows->image.attributes.event_mask);
5910 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5911 if ((state & EscapeState) != 0)
5914 Draw element as pointer moves until the button is released.
5922 rectangle_info.x=(ssize_t) x;
5923 rectangle_info.y=(ssize_t) y;
5924 rectangle_info.width=0;
5925 rectangle_info.height=0;
5926 number_coordinates=1;
5927 coordinate_info->x=x;
5928 coordinate_info->y=y;
5929 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5938 if (number_coordinates > 1)
5940 (void) XDrawLines(display,windows->image.id,
5941 windows->image.highlight_context,coordinate_info,
5942 number_coordinates,CoordModeOrigin);
5943 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d",
5944 coordinate_info[number_coordinates-1].x,
5945 coordinate_info[number_coordinates-1].y);
5946 XInfoWidget(display,windows,text);
5955 Display angle of the line.
5957 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5958 line_info.y1),(double) (line_info.x2-line_info.x1)));
5959 (void) FormatLocaleString(text,MagickPathExtent," %g",
5961 XInfoWidget(display,windows,text);
5962 XHighlightLine(display,windows->image.id,
5963 windows->image.highlight_context,&line_info);
5966 if (windows->info.mapped != MagickFalse )
5967 (void) XWithdrawWindow(display,windows->info.id,
5968 windows->info.screen);
5971 case RectangleElement:
5972 case FillRectangleElement:
5974 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5977 Display info and draw drawing rectangle.
5979 (void) FormatLocaleString(text,MagickPathExtent,
5980 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5981 (double) rectangle_info.height,(double) rectangle_info.x,
5982 (double) rectangle_info.y);
5983 XInfoWidget(display,windows,text);
5984 XHighlightRectangle(display,windows->image.id,
5985 windows->image.highlight_context,&rectangle_info);
5988 if (windows->info.mapped != MagickFalse )
5989 (void) XWithdrawWindow(display,windows->info.id,
5990 windows->info.screen);
5994 case FillCircleElement:
5995 case EllipseElement:
5996 case FillEllipseElement:
5998 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6001 Display info and draw drawing rectangle.
6003 (void) FormatLocaleString(text,MagickPathExtent,
6004 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6005 (double) rectangle_info.height,(double) rectangle_info.x,
6006 (double) rectangle_info.y);
6007 XInfoWidget(display,windows,text);
6008 XHighlightEllipse(display,windows->image.id,
6009 windows->image.highlight_context,&rectangle_info);
6012 if (windows->info.mapped != MagickFalse )
6013 (void) XWithdrawWindow(display,windows->info.id,
6014 windows->info.screen);
6017 case PolygonElement:
6018 case FillPolygonElement:
6020 if (number_coordinates > 1)
6021 (void) XDrawLines(display,windows->image.id,
6022 windows->image.highlight_context,coordinate_info,
6023 number_coordinates,CoordModeOrigin);
6027 Display angle of the line.
6029 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6030 line_info.y1),(double) (line_info.x2-line_info.x1)));
6031 (void) FormatLocaleString(text,MagickPathExtent," %g",
6033 XInfoWidget(display,windows,text);
6034 XHighlightLine(display,windows->image.id,
6035 windows->image.highlight_context,&line_info);
6038 if (windows->info.mapped != MagickFalse )
6039 (void) XWithdrawWindow(display,windows->info.id,
6040 windows->info.screen);
6045 Wait for next event.
6047 XScreenEvent(display,windows,&event,exception);
6053 if (number_coordinates > 1)
6054 (void) XDrawLines(display,windows->image.id,
6055 windows->image.highlight_context,coordinate_info,
6056 number_coordinates,CoordModeOrigin);
6062 XHighlightLine(display,windows->image.id,
6063 windows->image.highlight_context,&line_info);
6066 case RectangleElement:
6067 case FillRectangleElement:
6069 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6070 XHighlightRectangle(display,windows->image.id,
6071 windows->image.highlight_context,&rectangle_info);
6075 case FillCircleElement:
6076 case EllipseElement:
6077 case FillEllipseElement:
6079 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6080 XHighlightEllipse(display,windows->image.id,
6081 windows->image.highlight_context,&rectangle_info);
6084 case PolygonElement:
6085 case FillPolygonElement:
6087 if (number_coordinates > 1)
6088 (void) XDrawLines(display,windows->image.id,
6089 windows->image.highlight_context,coordinate_info,
6090 number_coordinates,CoordModeOrigin);
6092 XHighlightLine(display,windows->image.id,
6093 windows->image.highlight_context,&line_info);
6104 User has committed to element.
6106 line_info.x2=event.xbutton.x;
6107 line_info.y2=event.xbutton.y;
6108 rectangle_info.x=(ssize_t) event.xbutton.x;
6109 rectangle_info.y=(ssize_t) event.xbutton.y;
6110 coordinate_info[number_coordinates].x=event.xbutton.x;
6111 coordinate_info[number_coordinates].y=event.xbutton.y;
6112 if (((element != PolygonElement) &&
6113 (element != FillPolygonElement)) || (distance <= 9))
6118 number_coordinates++;
6119 if (number_coordinates < (int) max_coordinates)
6121 line_info.x1=event.xbutton.x;
6122 line_info.y1=event.xbutton.y;
6125 max_coordinates<<=1;
6126 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6127 max_coordinates,sizeof(*coordinate_info));
6128 if (coordinate_info == (XPoint *) NULL)
6129 (void) ThrowMagickException(exception,GetMagickModule(),
6130 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6137 if (event.xmotion.window != windows->image.id)
6139 if (element != PointElement)
6141 line_info.x2=event.xmotion.x;
6142 line_info.y2=event.xmotion.y;
6143 rectangle_info.x=(ssize_t) event.xmotion.x;
6144 rectangle_info.y=(ssize_t) event.xmotion.y;
6147 coordinate_info[number_coordinates].x=event.xbutton.x;
6148 coordinate_info[number_coordinates].y=event.xbutton.y;
6149 number_coordinates++;
6150 if (number_coordinates < (int) max_coordinates)
6152 max_coordinates<<=1;
6153 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6154 max_coordinates,sizeof(*coordinate_info));
6155 if (coordinate_info == (XPoint *) NULL)
6156 (void) ThrowMagickException(exception,GetMagickModule(),
6157 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6164 Check boundary conditions.
6166 if (line_info.x2 < 0)
6169 if (line_info.x2 > (int) windows->image.width)
6170 line_info.x2=(short) windows->image.width;
6171 if (line_info.y2 < 0)
6174 if (line_info.y2 > (int) windows->image.height)
6175 line_info.y2=(short) windows->image.height;
6176 distance=(unsigned int)
6177 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6178 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6179 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6180 ((state & ExitState) != 0))
6182 if (rectangle_info.x < 0)
6185 if (rectangle_info.x > (ssize_t) windows->image.width)
6186 rectangle_info.x=(ssize_t) windows->image.width;
6187 if ((int) rectangle_info.x < x)
6188 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6191 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6192 rectangle_info.x=(ssize_t) x;
6194 if (rectangle_info.y < 0)
6197 if (rectangle_info.y > (ssize_t) windows->image.height)
6198 rectangle_info.y=(ssize_t) windows->image.height;
6199 if ((int) rectangle_info.y < y)
6200 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6203 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6204 rectangle_info.y=(ssize_t) y;
6207 } while ((state & ExitState) == 0);
6208 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6209 if ((element == PointElement) || (element == PolygonElement) ||
6210 (element == FillPolygonElement))
6213 Determine polygon bounding box.
6215 rectangle_info.x=(ssize_t) coordinate_info->x;
6216 rectangle_info.y=(ssize_t) coordinate_info->y;
6217 x=coordinate_info->x;
6218 y=coordinate_info->y;
6219 for (i=1; i < number_coordinates; i++)
6221 if (coordinate_info[i].x > x)
6222 x=coordinate_info[i].x;
6223 if (coordinate_info[i].y > y)
6224 y=coordinate_info[i].y;
6225 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6226 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6227 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6228 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6230 rectangle_info.width=(size_t) (x-rectangle_info.x);
6231 rectangle_info.height=(size_t) (y-rectangle_info.y);
6232 for (i=0; i < number_coordinates; i++)
6234 coordinate_info[i].x-=rectangle_info.x;
6235 coordinate_info[i].y-=rectangle_info.y;
6242 if ((element == RectangleElement) ||
6243 (element == CircleElement) || (element == EllipseElement))
6245 rectangle_info.width--;
6246 rectangle_info.height--;
6249 Drawing is relative to image configuration.
6251 draw_info.x=(int) rectangle_info.x;
6252 draw_info.y=(int) rectangle_info.y;
6253 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6255 width=(unsigned int) (*image)->columns;
6256 height=(unsigned int) (*image)->rows;
6259 if (windows->image.crop_geometry != (char *) NULL)
6260 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6261 draw_info.x+=windows->image.x-(line_width/2);
6262 if (draw_info.x < 0)
6264 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6265 draw_info.y+=windows->image.y-(line_width/2);
6266 if (draw_info.y < 0)
6268 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6269 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6270 if (draw_info.width > (unsigned int) (*image)->columns)
6271 draw_info.width=(unsigned int) (*image)->columns;
6272 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6273 if (draw_info.height > (unsigned int) (*image)->rows)
6274 draw_info.height=(unsigned int) (*image)->rows;
6275 (void) FormatLocaleString(draw_info.geometry,MagickPathExtent,"%ux%u%+d%+d",
6276 width*draw_info.width/windows->image.ximage->width,
6277 height*draw_info.height/windows->image.ximage->height,
6278 draw_info.x+x,draw_info.y+y);
6280 Initialize drawing attributes.
6282 draw_info.degrees=0.0;
6283 draw_info.element=element;
6284 draw_info.stipple=stipple;
6285 draw_info.line_width=line_width;
6286 draw_info.line_info=line_info;
6287 if (line_info.x1 > (int) (line_width/2))
6288 draw_info.line_info.x1=(short) line_width/2;
6289 if (line_info.y1 > (int) (line_width/2))
6290 draw_info.line_info.y1=(short) line_width/2;
6291 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6292 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6293 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6295 draw_info.line_info.x2=(-draw_info.line_info.x2);
6296 draw_info.line_info.y2=(-draw_info.line_info.y2);
6298 if (draw_info.line_info.x2 < 0)
6300 draw_info.line_info.x2=(-draw_info.line_info.x2);
6301 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6303 if (draw_info.line_info.y2 < 0)
6305 draw_info.line_info.y2=(-draw_info.line_info.y2);
6306 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6308 draw_info.rectangle_info=rectangle_info;
6309 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6310 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6311 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6312 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6313 draw_info.number_coordinates=(unsigned int) number_coordinates;
6314 draw_info.coordinate_info=coordinate_info;
6315 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6317 Draw element on image.
6319 XSetCursorState(display,windows,MagickTrue);
6320 XCheckRefreshWindows(display,windows);
6321 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6322 XSetCursorState(display,windows,MagickFalse);
6324 Update image colormap and return to image drawing.
6326 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6327 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6329 XSetCursorState(display,windows,MagickFalse);
6330 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6331 return(status != 0 ? MagickTrue : MagickFalse);
6335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6339 + X D r a w P a n R e c t a n g l e %
6343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6345 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6346 % displays a zoom image and the rectangle shows which portion of the image is
6347 % displayed in the Image window.
6349 % The format of the XDrawPanRectangle method is:
6351 % XDrawPanRectangle(Display *display,XWindows *windows)
6353 % A description of each parameter follows:
6355 % o display: Specifies a connection to an X server; returned from
6358 % o windows: Specifies a pointer to a XWindows structure.
6361 static void XDrawPanRectangle(Display *display,XWindows *windows)
6370 Determine dimensions of the panning rectangle.
6372 scale_factor=(double) windows->pan.width/windows->image.ximage->width;
6373 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6374 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6375 scale_factor=(double)
6376 windows->pan.height/windows->image.ximage->height;
6377 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6378 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6380 Display the panning rectangle.
6382 (void) XClearWindow(display,windows->pan.id);
6383 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6392 + X I m a g e C a c h e %
6396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6398 % XImageCache() handles the creation, manipulation, and destruction of the
6399 % image cache (undo and redo buffers).
6401 % The format of the XImageCache method is:
6403 % void XImageCache(Display *display,XResourceInfo *resource_info,
6404 % XWindows *windows,const CommandType command,Image **image,
6405 % ExceptionInfo *exception)
6407 % A description of each parameter follows:
6409 % o display: Specifies a connection to an X server; returned from
6412 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6414 % o windows: Specifies a pointer to a XWindows structure.
6416 % o command: Specifies a command to perform.
6418 % o image: the image; XImageCache may transform the image and return a new
6421 % o exception: return any errors or warnings in this structure.
6424 static void XImageCache(Display *display,XResourceInfo *resource_info,
6425 XWindows *windows,const CommandType command,Image **image,
6426 ExceptionInfo *exception)
6432 *redo_image = (Image *) NULL,
6433 *undo_image = (Image *) NULL;
6437 case FreeBuffersCommand:
6440 Free memory from the undo and redo cache.
6442 while (undo_image != (Image *) NULL)
6444 cache_image=undo_image;
6445 undo_image=GetPreviousImageInList(undo_image);
6446 cache_image->list=DestroyImage(cache_image->list);
6447 cache_image=DestroyImage(cache_image);
6449 undo_image=NewImageList();
6450 if (redo_image != (Image *) NULL)
6451 redo_image=DestroyImage(redo_image);
6452 redo_image=NewImageList();
6458 image_geometry[MagickPathExtent];
6461 Undo the last image transformation.
6463 if (undo_image == (Image *) NULL)
6465 (void) XBell(display,0);
6468 cache_image=undo_image;
6469 undo_image=GetPreviousImageInList(undo_image);
6470 windows->image.window_changes.width=(int) cache_image->columns;
6471 windows->image.window_changes.height=(int) cache_image->rows;
6472 (void) FormatLocaleString(image_geometry,MagickPathExtent,"%dx%d!",
6473 windows->image.ximage->width,windows->image.ximage->height);
6474 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6476 if (windows->image.crop_geometry != (char *) NULL)
6477 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6478 windows->image.crop_geometry);
6479 windows->image.crop_geometry=cache_image->geometry;
6480 if (redo_image != (Image *) NULL)
6481 redo_image=DestroyImage(redo_image);
6482 redo_image=(*image);
6483 *image=cache_image->list;
6484 cache_image=DestroyImage(cache_image);
6485 if (windows->image.orphan != MagickFalse )
6487 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6488 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6494 case HalfSizeCommand:
6495 case OriginalSizeCommand:
6496 case DoubleSizeCommand:
6503 case RotateRightCommand:
6504 case RotateLeftCommand:
6509 case ContrastStretchCommand:
6510 case SigmoidalContrastCommand:
6511 case NormalizeCommand:
6512 case EqualizeCommand:
6514 case SaturationCommand:
6515 case BrightnessCommand:
6519 case GrayscaleCommand:
6521 case QuantizeCommand:
6522 case DespeckleCommand:
6524 case ReduceNoiseCommand:
6525 case AddNoiseCommand:
6526 case SharpenCommand:
6528 case ThresholdCommand:
6529 case EdgeDetectCommand:
6533 case SegmentCommand:
6534 case SolarizeCommand:
6535 case SepiaToneCommand:
6537 case ImplodeCommand:
6538 case VignetteCommand:
6540 case OilPaintCommand:
6541 case CharcoalDrawCommand:
6542 case AnnotateCommand:
6543 case AddBorderCommand:
6544 case AddFrameCommand:
6545 case CompositeCommand:
6546 case CommentCommand:
6548 case RegionofInterestCommand:
6549 case SaveToUndoBufferCommand:
6558 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6559 if (undo_image != (Image *) NULL)
6562 Ensure the undo cache has enough memory available.
6564 previous_image=undo_image;
6565 while (previous_image != (Image *) NULL)
6567 bytes+=previous_image->list->columns*previous_image->list->rows*
6569 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6571 previous_image=GetPreviousImageInList(previous_image);
6574 bytes-=previous_image->list->columns*previous_image->list->rows*
6576 if (previous_image == undo_image)
6577 undo_image=NewImageList();
6579 previous_image->next->previous=NewImageList();
6582 while (previous_image != (Image *) NULL)
6585 Delete any excess memory from undo cache.
6587 cache_image=previous_image;
6588 previous_image=GetPreviousImageInList(previous_image);
6589 cache_image->list=DestroyImage(cache_image->list);
6590 cache_image=DestroyImage(cache_image);
6593 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6596 Save image before transformations are applied.
6598 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6599 if (cache_image == (Image *) NULL)
6601 XSetCursorState(display,windows,MagickTrue);
6602 XCheckRefreshWindows(display,windows);
6603 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6604 XSetCursorState(display,windows,MagickFalse);
6605 if (cache_image->list == (Image *) NULL)
6607 cache_image=DestroyImage(cache_image);
6610 cache_image->columns=(size_t) windows->image.ximage->width;
6611 cache_image->rows=(size_t) windows->image.ximage->height;
6612 cache_image->geometry=windows->image.crop_geometry;
6613 if (windows->image.crop_geometry != (char *) NULL)
6615 cache_image->geometry=AcquireString((char *) NULL);
6616 (void) CopyMagickString(cache_image->geometry,
6617 windows->image.crop_geometry,MagickPathExtent);
6619 if (undo_image == (Image *) NULL)
6621 undo_image=cache_image;
6624 undo_image->next=cache_image;
6625 undo_image->next->previous=undo_image;
6626 undo_image=undo_image->next;
6632 if (command == RedoCommand)
6635 Redo the last image transformation.
6637 if (redo_image == (Image *) NULL)
6639 (void) XBell(display,0);
6642 windows->image.window_changes.width=(int) redo_image->columns;
6643 windows->image.window_changes.height=(int) redo_image->rows;
6644 if (windows->image.crop_geometry != (char *) NULL)
6645 windows->image.crop_geometry=(char *)
6646 RelinquishMagickMemory(windows->image.crop_geometry);
6647 windows->image.crop_geometry=redo_image->geometry;
6648 *image=DestroyImage(*image);
6650 redo_image=NewImageList();
6651 if (windows->image.orphan != MagickFalse )
6653 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6654 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6657 if (command != InfoCommand)
6662 XSetCursorState(display,windows,MagickTrue);
6663 XCheckRefreshWindows(display,windows);
6664 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6665 XSetCursorState(display,windows,MagickFalse);
6669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6673 + X I m a g e W i n d o w C o m m a n d %
6677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6679 % XImageWindowCommand() makes a transform to the image or Image window as
6680 % specified by a user menu button or keyboard command.
6682 % The format of the XImageWindowCommand method is:
6684 % CommandType XImageWindowCommand(Display *display,
6685 % XResourceInfo *resource_info,XWindows *windows,
6686 % const MagickStatusType state,KeySym key_symbol,Image **image,
6687 % ExceptionInfo *exception)
6689 % A description of each parameter follows:
6691 % o nexus: Method XImageWindowCommand returns an image when the
6692 % user chooses 'Open Image' from the command menu. Otherwise a null
6693 % image is returned.
6695 % o display: Specifies a connection to an X server; returned from
6698 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6700 % o windows: Specifies a pointer to a XWindows structure.
6702 % o state: key mask.
6704 % o key_symbol: Specifies a command to perform.
6706 % o image: the image; XImageWIndowCommand may transform the image and
6707 % return a new image pointer.
6709 % o exception: return any errors or warnings in this structure.
6712 static CommandType XImageWindowCommand(Display *display,
6713 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6714 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6717 delta[MagickPathExtent] = "";
6720 Digits[] = "01234567890";
6725 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6727 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6730 resource_info->quantum=1;
6732 last_symbol=key_symbol;
6733 delta[strlen(delta)+1]='\0';
6734 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6735 resource_info->quantum=StringToLong(delta);
6736 return(NullCommand);
6738 last_symbol=key_symbol;
6739 if (resource_info->immutable)
6742 Virtual image window has a restricted command set.
6747 return(InfoCommand);
6750 return(PrintCommand);
6752 return(NextCommand);
6755 return(QuitCommand);
6759 return(NullCommand);
6761 switch ((int) key_symbol)
6765 if ((state & ControlMask) == 0)
6767 return(OpenCommand);
6770 return(NextCommand);
6772 return(FormerCommand);
6775 if ((state & Mod1Mask) != 0)
6776 return(SwirlCommand);
6777 if ((state & ControlMask) == 0)
6778 return(ShearCommand);
6779 return(SaveCommand);
6784 if ((state & Mod1Mask) != 0)
6785 return(OilPaintCommand);
6786 if ((state & Mod4Mask) != 0)
6787 return(ColorCommand);
6788 if ((state & ControlMask) == 0)
6789 return(NullCommand);
6790 return(PrintCommand);
6794 if ((state & Mod4Mask) != 0)
6795 return(DrawCommand);
6796 if ((state & ControlMask) == 0)
6797 return(NullCommand);
6798 return(DeleteCommand);
6802 if ((state & ControlMask) == 0)
6803 return(NullCommand);
6804 return(SelectCommand);
6808 if ((state & ControlMask) == 0)
6809 return(NullCommand);
6814 return(QuitCommand);
6818 if ((state & ControlMask) == 0)
6819 return(NullCommand);
6820 return(UndoCommand);
6825 if ((state & ControlMask) == 0)
6826 return(RollCommand);
6827 return(RedoCommand);
6831 if ((state & ControlMask) == 0)
6832 return(NullCommand);
6837 if ((state & Mod1Mask) != 0)
6838 return(CharcoalDrawCommand);
6839 if ((state & ControlMask) == 0)
6840 return(CropCommand);
6841 return(CopyCommand);
6846 if ((state & Mod4Mask) != 0)
6847 return(CompositeCommand);
6848 if ((state & ControlMask) == 0)
6849 return(FlipCommand);
6850 return(PasteCommand);
6853 return(HalfSizeCommand);
6855 return(OriginalSizeCommand);
6857 return(DoubleSizeCommand);
6859 return(ResizeCommand);
6861 return(RefreshCommand);
6862 case XK_bracketleft:
6863 return(ChopCommand);
6865 return(FlopCommand);
6867 return(RotateRightCommand);
6869 return(RotateLeftCommand);
6871 return(RotateCommand);
6873 return(TrimCommand);
6877 return(SaturationCommand);
6879 return(BrightnessCommand);
6881 return(GammaCommand);
6883 return(SpiffCommand);
6885 return(DullCommand);
6887 return(NormalizeCommand);
6889 return(EqualizeCommand);
6891 return(NegateCommand);
6893 return(GrayscaleCommand);
6895 return(QuantizeCommand);
6897 return(DespeckleCommand);
6899 return(EmbossCommand);
6901 return(ReduceNoiseCommand);
6903 return(AddNoiseCommand);
6905 return(SharpenCommand);
6907 return(BlurCommand);
6909 return(ThresholdCommand);
6911 return(EdgeDetectCommand);
6913 return(SpreadCommand);
6915 return(ShadeCommand);
6917 return(RaiseCommand);
6919 return(SegmentCommand);
6922 if ((state & Mod1Mask) == 0)
6923 return(NullCommand);
6924 return(ImplodeCommand);
6928 if ((state & Mod1Mask) == 0)
6929 return(NullCommand);
6930 return(WaveCommand);
6934 if ((state & Mod4Mask) == 0)
6935 return(NullCommand);
6936 return(MatteCommand);
6940 if ((state & Mod4Mask) == 0)
6941 return(NullCommand);
6942 return(AddBorderCommand);
6946 if ((state & Mod4Mask) == 0)
6947 return(NullCommand);
6948 return(AddFrameCommand);
6952 if ((state & Mod4Mask) == 0)
6953 return(NullCommand);
6954 return(CommentCommand);
6958 if ((state & Mod1Mask) != 0)
6959 return(ApplyCommand);
6960 if ((state & Mod4Mask) != 0)
6961 return(AnnotateCommand);
6962 if ((state & ControlMask) == 0)
6963 return(NullCommand);
6964 return(RegionofInterestCommand);
6967 return(InfoCommand);
6969 return(ZoomCommand);
6972 if ((state & ShiftMask) == 0)
6973 return(NullCommand);
6974 return(ShowPreviewCommand);
6977 return(LaunchCommand);
6979 return(HelpCommand);
6981 return(BrowseDocumentationCommand);
6984 (void) XMapRaised(display,windows->command.id);
6985 return(NullCommand);
6992 XTranslateImage(display,windows,*image,key_symbol);
6993 return(NullCommand);
7004 if ((state & Mod1Mask) != 0)
7010 Trim one pixel from edge of image.
7014 crop_info.width=(size_t) windows->image.ximage->width;
7015 crop_info.height=(size_t) windows->image.ximage->height;
7016 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7018 if (resource_info->quantum >= (int) crop_info.height)
7019 resource_info->quantum=(int) crop_info.height-1;
7020 crop_info.height-=resource_info->quantum;
7022 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7024 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7025 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7026 crop_info.y+=resource_info->quantum;
7027 crop_info.height-=resource_info->quantum;
7029 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7031 if (resource_info->quantum >= (int) crop_info.width)
7032 resource_info->quantum=(int) crop_info.width-1;
7033 crop_info.width-=resource_info->quantum;
7035 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7037 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7038 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7039 crop_info.x+=resource_info->quantum;
7040 crop_info.width-=resource_info->quantum;
7042 if ((int) (windows->image.x+windows->image.width) >
7043 (int) crop_info.width)
7044 windows->image.x=(int) (crop_info.width-windows->image.width);
7045 if ((int) (windows->image.y+windows->image.height) >
7046 (int) crop_info.height)
7047 windows->image.y=(int) (crop_info.height-windows->image.height);
7048 XSetCropGeometry(display,windows,&crop_info,*image);
7049 windows->image.window_changes.width=(int) crop_info.width;
7050 windows->image.window_changes.height=(int) crop_info.height;
7051 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7052 (void) XConfigureImage(display,resource_info,windows,*image,
7054 return(NullCommand);
7056 XTranslateImage(display,windows,*image,key_symbol);
7057 return(NullCommand);
7060 return(NullCommand);
7062 return(NullCommand);
7066 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7070 + X M a g i c k C o m m a n d %
7074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7076 % XMagickCommand() makes a transform to the image or Image window as
7077 % specified by a user menu button or keyboard command.
7079 % The format of the XMagickCommand method is:
7081 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7082 % XWindows *windows,const CommandType command,Image **image,
7083 % ExceptionInfo *exception)
7085 % A description of each parameter follows:
7087 % o display: Specifies a connection to an X server; returned from
7090 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7092 % o windows: Specifies a pointer to a XWindows structure.
7094 % o command: Specifies a command to perform.
7096 % o image: the image; XMagickCommand may transform the image and return a
7097 % new image pointer.
7099 % o exception: return any errors or warnings in this structure.
7102 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7103 XWindows *windows,const CommandType command,Image **image,
7104 ExceptionInfo *exception)
7107 filename[MagickPathExtent],
7108 geometry[MagickPathExtent],
7109 modulate_factors[MagickPathExtent];
7138 color[MagickPathExtent] = "gray";
7145 Process user command.
7147 XCheckRefreshWindows(display,windows);
7148 XImageCache(display,resource_info,windows,command,image,exception);
7149 nexus=NewImageList();
7150 windows->image.window_changes.width=windows->image.ximage->width;
7151 windows->image.window_changes.height=windows->image.ximage->height;
7152 image_info=CloneImageInfo(resource_info->image_info);
7153 SetGeometryInfo(&geometry_info);
7154 GetQuantizeInfo(&quantize_info);
7162 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7170 for (i=0; i < resource_info->quantum; i++)
7171 XClientMessage(display,windows->image.id,windows->im_protocols,
7172 windows->im_next_image,CurrentTime);
7178 Display former image.
7180 for (i=0; i < resource_info->quantum; i++)
7181 XClientMessage(display,windows->image.id,windows->im_protocols,
7182 windows->im_former_image,CurrentTime);
7193 if (*resource_info->home_directory == '\0')
7194 (void) CopyMagickString(resource_info->home_directory,".",
7196 status=chdir(resource_info->home_directory);
7198 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7199 "UnableToOpenFile","%s",resource_info->home_directory);
7200 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7208 status=XSaveImage(display,resource_info,windows,*image,exception);
7209 if (status == MagickFalse)
7212 message[MagickPathExtent];
7214 (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
7215 exception->reason != (char *) NULL ? exception->reason : "",
7216 exception->description != (char *) NULL ? exception->description :
7218 XNoticeWidget(display,windows,"Unable to save file:",message);
7228 status=XPrintImage(display,resource_info,windows,*image,exception);
7229 if (status == MagickFalse)
7232 message[MagickPathExtent];
7234 (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
7235 exception->reason != (char *) NULL ? exception->reason : "",
7236 exception->description != (char *) NULL ? exception->description :
7238 XNoticeWidget(display,windows,"Unable to print file:",message);
7246 filename[MagickPathExtent] = "\0";
7251 XFileBrowserWidget(display,windows,"Delete",filename);
7252 if (*filename == '\0')
7254 status=ShredFile(filename);
7255 if (status != MagickFalse )
7256 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7265 color[MagickPathExtent] = "gray",
7266 geometry[MagickPathExtent] = "640x480";
7269 *format = "gradient";
7272 Query user for canvas geometry.
7274 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7276 if (*geometry == '\0')
7280 XColorBrowserWidget(display,windows,"Select",color);
7286 (void) FormatLocaleString(image_info->filename,MagickPathExtent,
7287 "%s:%s",format,color);
7288 (void) CloneString(&image_info->size,geometry);
7289 nexus=ReadImage(image_info,exception);
7290 CatchException(exception);
7291 XClientMessage(display,windows->image.id,windows->im_protocols,
7292 windows->im_next_image,CurrentTime);
7295 case VisualDirectoryCommand:
7298 Visual Image directory.
7300 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7308 if (resource_info->confirm_exit == MagickFalse)
7309 XClientMessage(display,windows->image.id,windows->im_protocols,
7310 windows->im_exit,CurrentTime);
7317 Confirm program exit.
7319 status=XConfirmWidget(display,windows,"Do you really want to exit",
7320 resource_info->client_name);
7322 XClientMessage(display,windows->image.id,windows->im_protocols,
7323 windows->im_exit,CurrentTime);
7332 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7340 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7349 status=XPasteImage(display,resource_info,windows,*image,exception);
7350 if (status == MagickFalse)
7352 XNoticeWidget(display,windows,"Unable to paste X image",
7353 (*image)->filename);
7358 case HalfSizeCommand:
7363 windows->image.window_changes.width=windows->image.ximage->width/2;
7364 windows->image.window_changes.height=windows->image.ximage->height/2;
7365 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7368 case OriginalSizeCommand:
7371 Original image size.
7373 windows->image.window_changes.width=(int) (*image)->columns;
7374 windows->image.window_changes.height=(int) (*image)->rows;
7375 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7378 case DoubleSizeCommand:
7381 Double the image size.
7383 windows->image.window_changes.width=windows->image.ximage->width << 1;
7384 windows->image.window_changes.height=windows->image.ximage->height << 1;
7385 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7404 width=(size_t) windows->image.ximage->width;
7405 height=(size_t) windows->image.ximage->height;
7408 (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g+0+0",
7409 (double) width,(double) height);
7410 status=XDialogWidget(display,windows,"Resize",
7411 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7412 if (*geometry == '\0')
7415 (void) ConcatenateMagickString(geometry,"!",MagickPathExtent);
7416 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7417 windows->image.window_changes.width=(int) width;
7418 windows->image.window_changes.height=(int) height;
7419 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7425 image_geometry[MagickPathExtent];
7427 if ((windows->image.crop_geometry == (char *) NULL) &&
7428 ((int) (*image)->columns == windows->image.ximage->width) &&
7429 ((int) (*image)->rows == windows->image.ximage->height))
7432 Apply size transforms to image.
7434 XSetCursorState(display,windows,MagickTrue);
7435 XCheckRefreshWindows(display,windows);
7437 Crop and/or scale displayed image.
7439 (void) FormatLocaleString(image_geometry,MagickPathExtent,"%dx%d!",
7440 windows->image.ximage->width,windows->image.ximage->height);
7441 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7443 if (windows->image.crop_geometry != (char *) NULL)
7444 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7445 windows->image.crop_geometry);
7448 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7449 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7452 case RefreshCommand:
7454 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7457 case RestoreCommand:
7460 Restore Image window to its original size.
7462 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7463 (windows->image.height == (unsigned int) (*image)->rows) &&
7464 (windows->image.crop_geometry == (char *) NULL))
7466 (void) XBell(display,0);
7469 windows->image.window_changes.width=(int) (*image)->columns;
7470 windows->image.window_changes.height=(int) (*image)->rows;
7471 if (windows->image.crop_geometry != (char *) NULL)
7473 windows->image.crop_geometry=(char *)
7474 RelinquishMagickMemory(windows->image.crop_geometry);
7475 windows->image.crop_geometry=(char *) NULL;
7479 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7480 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7488 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7497 status=XChopImage(display,resource_info,windows,image,exception);
7498 if (status == MagickFalse)
7500 XNoticeWidget(display,windows,"Unable to cut X image",
7501 (*image)->filename);
7512 Flop image scanlines.
7514 XSetCursorState(display,windows,MagickTrue);
7515 XCheckRefreshWindows(display,windows);
7516 flop_image=FlopImage(*image,exception);
7517 if (flop_image != (Image *) NULL)
7519 *image=DestroyImage(*image);
7522 CatchException(exception);
7523 XSetCursorState(display,windows,MagickFalse);
7524 if (windows->image.crop_geometry != (char *) NULL)
7529 width=(unsigned int) (*image)->columns;
7530 height=(unsigned int) (*image)->rows;
7531 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7533 (void) FormatLocaleString(windows->image.crop_geometry,
7534 MagickPathExtent,"%ux%u%+d%+d",width,height,(int) (*image)->columns-
7537 if (windows->image.orphan != MagickFalse )
7539 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7548 Flip image scanlines.
7550 XSetCursorState(display,windows,MagickTrue);
7551 XCheckRefreshWindows(display,windows);
7552 flip_image=FlipImage(*image,exception);
7553 if (flip_image != (Image *) NULL)
7555 *image=DestroyImage(*image);
7558 CatchException(exception);
7559 XSetCursorState(display,windows,MagickFalse);
7560 if (windows->image.crop_geometry != (char *) NULL)
7565 width=(unsigned int) (*image)->columns;
7566 height=(unsigned int) (*image)->rows;
7567 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7569 (void) FormatLocaleString(windows->image.crop_geometry,
7570 MagickPathExtent,"%ux%u%+d%+d",width,height,x,(int) (*image)->rows-
7573 if (windows->image.orphan != MagickFalse )
7575 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7578 case RotateRightCommand:
7581 Rotate image 90 degrees clockwise.
7583 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7584 if (status == MagickFalse)
7586 XNoticeWidget(display,windows,"Unable to rotate X image",
7587 (*image)->filename);
7592 case RotateLeftCommand:
7595 Rotate image 90 degrees counter-clockwise.
7597 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7598 if (status == MagickFalse)
7600 XNoticeWidget(display,windows,"Unable to rotate X image",
7601 (*image)->filename);
7611 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7612 if (status == MagickFalse)
7614 XNoticeWidget(display,windows,"Unable to rotate X image",
7615 (*image)->filename);
7626 geometry[MagickPathExtent] = "45.0x45.0";
7629 Query user for shear color and geometry.
7631 XColorBrowserWidget(display,windows,"Select",color);
7634 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7636 if (*geometry == '\0')
7641 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7643 XSetCursorState(display,windows,MagickTrue);
7644 XCheckRefreshWindows(display,windows);
7645 (void) QueryColorCompliance(color,AllCompliance,
7646 &(*image)->background_color,exception);
7647 flags=ParseGeometry(geometry,&geometry_info);
7648 if ((flags & SigmaValue) == 0)
7649 geometry_info.sigma=geometry_info.rho;
7650 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7652 if (shear_image != (Image *) NULL)
7654 *image=DestroyImage(*image);
7657 CatchException(exception);
7658 XSetCursorState(display,windows,MagickFalse);
7659 if (windows->image.orphan != MagickFalse )
7661 windows->image.window_changes.width=(int) (*image)->columns;
7662 windows->image.window_changes.height=(int) (*image)->rows;
7663 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7664 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7673 geometry[MagickPathExtent] = "+2+2";
7676 Query user for the roll geometry.
7678 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7680 if (*geometry == '\0')
7685 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7687 XSetCursorState(display,windows,MagickTrue);
7688 XCheckRefreshWindows(display,windows);
7689 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7691 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7693 if (roll_image != (Image *) NULL)
7695 *image=DestroyImage(*image);
7698 CatchException(exception);
7699 XSetCursorState(display,windows,MagickFalse);
7700 if (windows->image.orphan != MagickFalse )
7702 windows->image.window_changes.width=(int) (*image)->columns;
7703 windows->image.window_changes.height=(int) (*image)->rows;
7704 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7705 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7711 fuzz[MagickPathExtent];
7714 Query user for the fuzz factor.
7716 (void) FormatLocaleString(fuzz,MagickPathExtent,"%g%%",100.0*
7717 (*image)->fuzz/(QuantumRange+1.0));
7718 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7721 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+1.0);
7725 status=XTrimImage(display,resource_info,windows,*image,exception);
7726 if (status == MagickFalse)
7728 XNoticeWidget(display,windows,"Unable to trim X image",
7729 (*image)->filename);
7737 hue_percent[MagickPathExtent] = "110";
7740 Query user for percent hue change.
7742 (void) XDialogWidget(display,windows,"Apply",
7743 "Enter percent change in image hue (0-200):",hue_percent);
7744 if (*hue_percent == '\0')
7749 XSetCursorState(display,windows,MagickTrue);
7750 XCheckRefreshWindows(display,windows);
7751 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MagickPathExtent);
7752 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7754 (void) ModulateImage(*image,modulate_factors,exception);
7755 XSetCursorState(display,windows,MagickFalse);
7756 if (windows->image.orphan != MagickFalse )
7758 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7759 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7762 case SaturationCommand:
7765 saturation_percent[MagickPathExtent] = "110";
7768 Query user for percent saturation change.
7770 (void) XDialogWidget(display,windows,"Apply",
7771 "Enter percent change in color saturation (0-200):",saturation_percent);
7772 if (*saturation_percent == '\0')
7775 Vary color saturation.
7777 XSetCursorState(display,windows,MagickTrue);
7778 XCheckRefreshWindows(display,windows);
7779 (void) CopyMagickString(modulate_factors,"100.0/",MagickPathExtent);
7780 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7782 (void) ModulateImage(*image,modulate_factors,exception);
7783 XSetCursorState(display,windows,MagickFalse);
7784 if (windows->image.orphan != MagickFalse )
7786 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7787 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7790 case BrightnessCommand:
7793 brightness_percent[MagickPathExtent] = "110";
7796 Query user for percent brightness change.
7798 (void) XDialogWidget(display,windows,"Apply",
7799 "Enter percent change in color brightness (0-200):",brightness_percent);
7800 if (*brightness_percent == '\0')
7803 Vary the color brightness.
7805 XSetCursorState(display,windows,MagickTrue);
7806 XCheckRefreshWindows(display,windows);
7807 (void) CopyMagickString(modulate_factors,brightness_percent,
7809 (void) ModulateImage(*image,modulate_factors,exception);
7810 XSetCursorState(display,windows,MagickFalse);
7811 if (windows->image.orphan != MagickFalse )
7813 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7814 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7820 factor[MagickPathExtent] = "1.6";
7823 Query user for gamma value.
7825 (void) XDialogWidget(display,windows,"Gamma",
7826 "Enter gamma value (e.g. 1.2):",factor);
7827 if (*factor == '\0')
7830 Gamma correct image.
7832 XSetCursorState(display,windows,MagickTrue);
7833 XCheckRefreshWindows(display,windows);
7834 (void) GammaImage(*image,strtod(factor,(char **) NULL),exception);
7835 XSetCursorState(display,windows,MagickFalse);
7836 if (windows->image.orphan != MagickFalse )
7838 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7839 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7845 Sharpen the image contrast.
7847 XSetCursorState(display,windows,MagickTrue);
7848 XCheckRefreshWindows(display,windows);
7849 (void) ContrastImage(*image,MagickTrue,exception);
7850 XSetCursorState(display,windows,MagickFalse);
7851 if (windows->image.orphan != MagickFalse )
7853 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7854 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7860 Dull the image contrast.
7862 XSetCursorState(display,windows,MagickTrue);
7863 XCheckRefreshWindows(display,windows);
7864 (void) ContrastImage(*image,MagickFalse,exception);
7865 XSetCursorState(display,windows,MagickFalse);
7866 if (windows->image.orphan != MagickFalse )
7868 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7869 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7872 case ContrastStretchCommand:
7879 levels[MagickPathExtent] = "1%";
7882 Query user for gamma value.
7884 (void) XDialogWidget(display,windows,"Contrast Stretch",
7885 "Enter black and white points:",levels);
7886 if (*levels == '\0')
7889 Contrast stretch image.
7891 XSetCursorState(display,windows,MagickTrue);
7892 XCheckRefreshWindows(display,windows);
7893 flags=ParseGeometry(levels,&geometry_info);
7894 black_point=geometry_info.rho;
7895 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7896 if ((flags & PercentValue) != 0)
7898 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7899 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7901 white_point=(double) (*image)->columns*(*image)->rows-white_point;
7902 (void) ContrastStretchImage(*image,black_point,white_point,
7904 XSetCursorState(display,windows,MagickFalse);
7905 if (windows->image.orphan != MagickFalse )
7907 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7908 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7911 case SigmoidalContrastCommand:
7920 levels[MagickPathExtent] = "3x50%";
7923 Query user for gamma value.
7925 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7926 "Enter contrast and midpoint:",levels);
7927 if (*levels == '\0')
7930 Contrast stretch image.
7932 XSetCursorState(display,windows,MagickTrue);
7933 XCheckRefreshWindows(display,windows);
7934 flags=ParseGeometry(levels,&geometry_info);
7935 if ((flags & SigmaValue) == 0)
7936 geometry_info.sigma=1.0*QuantumRange/2.0;
7937 if ((flags & PercentValue) != 0)
7938 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7939 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7940 geometry_info.sigma,exception);
7941 XSetCursorState(display,windows,MagickFalse);
7942 if (windows->image.orphan != MagickFalse )
7944 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7945 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7948 case NormalizeCommand:
7951 Perform histogram normalization on the image.
7953 XSetCursorState(display,windows,MagickTrue);
7954 XCheckRefreshWindows(display,windows);
7955 (void) NormalizeImage(*image,exception);
7956 XSetCursorState(display,windows,MagickFalse);
7957 if (windows->image.orphan != MagickFalse )
7959 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7960 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7963 case EqualizeCommand:
7966 Perform histogram equalization on the image.
7968 XSetCursorState(display,windows,MagickTrue);
7969 XCheckRefreshWindows(display,windows);
7970 (void) EqualizeImage(*image,exception);
7971 XSetCursorState(display,windows,MagickFalse);
7972 if (windows->image.orphan != MagickFalse )
7974 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7975 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7981 Negate colors in image.
7983 XSetCursorState(display,windows,MagickTrue);
7984 XCheckRefreshWindows(display,windows);
7985 (void) NegateImage(*image,MagickFalse,exception);
7986 XSetCursorState(display,windows,MagickFalse);
7987 if (windows->image.orphan != MagickFalse )
7989 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7990 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7993 case GrayscaleCommand:
7996 Convert image to grayscale.
7998 XSetCursorState(display,windows,MagickTrue);
7999 XCheckRefreshWindows(display,windows);
8000 (void) SetImageType(*image,(*image)->alpha_trait == UndefinedPixelTrait ?
8001 GrayscaleType : GrayscaleAlphaType,exception);
8002 XSetCursorState(display,windows,MagickFalse);
8003 if (windows->image.orphan != MagickFalse )
8005 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8006 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8015 filename[MagickPathExtent] = "\0";
8018 Request image file name from user.
8020 XFileBrowserWidget(display,windows,"Map",filename);
8021 if (*filename == '\0')
8026 XSetCursorState(display,windows,MagickTrue);
8027 XCheckRefreshWindows(display,windows);
8028 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
8029 affinity_image=ReadImage(image_info,exception);
8030 if (affinity_image != (Image *) NULL)
8032 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8033 affinity_image=DestroyImage(affinity_image);
8035 CatchException(exception);
8036 XSetCursorState(display,windows,MagickFalse);
8037 if (windows->image.orphan != MagickFalse )
8039 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8040 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8043 case QuantizeCommand:
8049 colors[MagickPathExtent] = "256";
8052 Query user for maximum number of colors.
8054 status=XDialogWidget(display,windows,"Quantize",
8055 "Maximum number of colors:",colors);
8056 if (*colors == '\0')
8059 Color reduce the image.
8061 XSetCursorState(display,windows,MagickTrue);
8062 XCheckRefreshWindows(display,windows);
8063 quantize_info.number_colors=StringToUnsignedLong(colors);
8064 quantize_info.dither_method=status != 0 ? RiemersmaDitherMethod :
8066 (void) QuantizeImage(&quantize_info,*image,exception);
8067 XSetCursorState(display,windows,MagickFalse);
8068 if (windows->image.orphan != MagickFalse )
8070 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8071 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8074 case DespeckleCommand:
8082 XSetCursorState(display,windows,MagickTrue);
8083 XCheckRefreshWindows(display,windows);
8084 despeckle_image=DespeckleImage(*image,exception);
8085 if (despeckle_image != (Image *) NULL)
8087 *image=DestroyImage(*image);
8088 *image=despeckle_image;
8090 CatchException(exception);
8091 XSetCursorState(display,windows,MagickFalse);
8092 if (windows->image.orphan != MagickFalse )
8094 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8095 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8104 radius[MagickPathExtent] = "0.0x1.0";
8107 Query user for emboss radius.
8109 (void) XDialogWidget(display,windows,"Emboss",
8110 "Enter the emboss radius and standard deviation:",radius);
8111 if (*radius == '\0')
8114 Reduce noise in the image.
8116 XSetCursorState(display,windows,MagickTrue);
8117 XCheckRefreshWindows(display,windows);
8118 flags=ParseGeometry(radius,&geometry_info);
8119 if ((flags & SigmaValue) == 0)
8120 geometry_info.sigma=1.0;
8121 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8123 if (emboss_image != (Image *) NULL)
8125 *image=DestroyImage(*image);
8126 *image=emboss_image;
8128 CatchException(exception);
8129 XSetCursorState(display,windows,MagickFalse);
8130 if (windows->image.orphan != MagickFalse )
8132 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8133 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8136 case ReduceNoiseCommand:
8142 radius[MagickPathExtent] = "0";
8145 Query user for noise radius.
8147 (void) XDialogWidget(display,windows,"Reduce Noise",
8148 "Enter the noise radius:",radius);
8149 if (*radius == '\0')
8152 Reduce noise in the image.
8154 XSetCursorState(display,windows,MagickTrue);
8155 XCheckRefreshWindows(display,windows);
8156 flags=ParseGeometry(radius,&geometry_info);
8157 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8158 geometry_info.rho,(size_t) geometry_info.rho,exception);
8159 if (noise_image != (Image *) NULL)
8161 *image=DestroyImage(*image);
8164 CatchException(exception);
8165 XSetCursorState(display,windows,MagickFalse);
8166 if (windows->image.orphan != MagickFalse )
8168 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8169 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8172 case AddNoiseCommand:
8181 noise_type[MagickPathExtent] = "Gaussian";
8184 Add noise to the image.
8186 noises=GetCommandOptions(MagickNoiseOptions);
8187 if (noises == (char **) NULL)
8189 XListBrowserWidget(display,windows,&windows->widget,
8190 (const char **) noises,"Add Noise",
8191 "Select a type of noise to add to your image:",noise_type);
8192 noises=DestroyStringList(noises);
8193 if (*noise_type == '\0')
8195 XSetCursorState(display,windows,MagickTrue);
8196 XCheckRefreshWindows(display,windows);
8197 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8198 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8199 if (noise_image != (Image *) NULL)
8201 *image=DestroyImage(*image);
8204 CatchException(exception);
8205 XSetCursorState(display,windows,MagickFalse);
8206 if (windows->image.orphan != MagickFalse )
8208 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8209 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8212 case SharpenCommand:
8218 radius[MagickPathExtent] = "0.0x1.0";
8221 Query user for sharpen radius.
8223 (void) XDialogWidget(display,windows,"Sharpen",
8224 "Enter the sharpen radius and standard deviation:",radius);
8225 if (*radius == '\0')
8228 Sharpen image scanlines.
8230 XSetCursorState(display,windows,MagickTrue);
8231 XCheckRefreshWindows(display,windows);
8232 flags=ParseGeometry(radius,&geometry_info);
8233 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8235 if (sharp_image != (Image *) NULL)
8237 *image=DestroyImage(*image);
8240 CatchException(exception);
8241 XSetCursorState(display,windows,MagickFalse);
8242 if (windows->image.orphan != MagickFalse )
8244 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8245 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8254 radius[MagickPathExtent] = "0.0x1.0";
8257 Query user for blur radius.
8259 (void) XDialogWidget(display,windows,"Blur",
8260 "Enter the blur radius and standard deviation:",radius);
8261 if (*radius == '\0')
8266 XSetCursorState(display,windows,MagickTrue);
8267 XCheckRefreshWindows(display,windows);
8268 flags=ParseGeometry(radius,&geometry_info);
8269 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8271 if (blur_image != (Image *) NULL)
8273 *image=DestroyImage(*image);
8276 CatchException(exception);
8277 XSetCursorState(display,windows,MagickFalse);
8278 if (windows->image.orphan != MagickFalse )
8280 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8281 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8284 case ThresholdCommand:
8290 factor[MagickPathExtent] = "128";
8293 Query user for threshold value.
8295 (void) XDialogWidget(display,windows,"Threshold",
8296 "Enter threshold value:",factor);
8297 if (*factor == '\0')
8300 Gamma correct image.
8302 XSetCursorState(display,windows,MagickTrue);
8303 XCheckRefreshWindows(display,windows);
8304 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8305 (void) BilevelImage(*image,threshold,exception);
8306 XSetCursorState(display,windows,MagickFalse);
8307 if (windows->image.orphan != MagickFalse )
8309 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8310 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8313 case EdgeDetectCommand:
8319 radius[MagickPathExtent] = "0";
8322 Query user for edge factor.
8324 (void) XDialogWidget(display,windows,"Detect Edges",
8325 "Enter the edge detect radius:",radius);
8326 if (*radius == '\0')
8329 Detect edge in image.
8331 XSetCursorState(display,windows,MagickTrue);
8332 XCheckRefreshWindows(display,windows);
8333 flags=ParseGeometry(radius,&geometry_info);
8334 edge_image=EdgeImage(*image,geometry_info.rho,exception);
8335 if (edge_image != (Image *) NULL)
8337 *image=DestroyImage(*image);
8340 CatchException(exception);
8341 XSetCursorState(display,windows,MagickFalse);
8342 if (windows->image.orphan != MagickFalse )
8344 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8345 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8354 amount[MagickPathExtent] = "2";
8357 Query user for spread amount.
8359 (void) XDialogWidget(display,windows,"Spread",
8360 "Enter the displacement amount:",amount);
8361 if (*amount == '\0')
8364 Displace image pixels by a random amount.
8366 XSetCursorState(display,windows,MagickTrue);
8367 XCheckRefreshWindows(display,windows);
8368 flags=ParseGeometry(amount,&geometry_info);
8369 spread_image=EdgeImage(*image,geometry_info.rho,exception);
8370 if (spread_image != (Image *) NULL)
8372 *image=DestroyImage(*image);
8373 *image=spread_image;
8375 CatchException(exception);
8376 XSetCursorState(display,windows,MagickFalse);
8377 if (windows->image.orphan != MagickFalse )
8379 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8380 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8392 geometry[MagickPathExtent] = "30x30";
8395 Query user for the shade geometry.
8397 status=XDialogWidget(display,windows,"Shade",
8398 "Enter the azimuth and elevation of the light source:",geometry);
8399 if (*geometry == '\0')
8404 XSetCursorState(display,windows,MagickTrue);
8405 XCheckRefreshWindows(display,windows);
8406 flags=ParseGeometry(geometry,&geometry_info);
8407 if ((flags & SigmaValue) == 0)
8408 geometry_info.sigma=1.0;
8409 shade_image=ShadeImage(*image,status != 0 ? MagickTrue : MagickFalse,
8410 geometry_info.rho,geometry_info.sigma,exception);
8411 if (shade_image != (Image *) NULL)
8413 *image=DestroyImage(*image);
8416 CatchException(exception);
8417 XSetCursorState(display,windows,MagickFalse);
8418 if (windows->image.orphan != MagickFalse )
8420 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8421 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8427 bevel_width[MagickPathExtent] = "10";
8430 Query user for bevel width.
8432 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8433 if (*bevel_width == '\0')
8438 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8440 XSetCursorState(display,windows,MagickTrue);
8441 XCheckRefreshWindows(display,windows);
8442 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8444 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8445 XSetCursorState(display,windows,MagickFalse);
8446 if (windows->image.orphan != MagickFalse )
8448 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8449 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8452 case SegmentCommand:
8455 threshold[MagickPathExtent] = "1.0x1.5";
8458 Query user for smoothing threshold.
8460 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8462 if (*threshold == '\0')
8467 XSetCursorState(display,windows,MagickTrue);
8468 XCheckRefreshWindows(display,windows);
8469 flags=ParseGeometry(threshold,&geometry_info);
8470 if ((flags & SigmaValue) == 0)
8471 geometry_info.sigma=1.0;
8472 (void) SegmentImage(*image,sRGBColorspace,MagickFalse,geometry_info.rho,
8473 geometry_info.sigma,exception);
8474 XSetCursorState(display,windows,MagickFalse);
8475 if (windows->image.orphan != MagickFalse )
8477 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8478 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8481 case SepiaToneCommand:
8490 factor[MagickPathExtent] = "80%";
8493 Query user for sepia-tone factor.
8495 (void) XDialogWidget(display,windows,"Sepia Tone",
8496 "Enter the sepia tone factor (0 - 99.9%):",factor);
8497 if (*factor == '\0')
8500 Sepia tone image pixels.
8502 XSetCursorState(display,windows,MagickTrue);
8503 XCheckRefreshWindows(display,windows);
8504 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8505 sepia_image=SepiaToneImage(*image,threshold,exception);
8506 if (sepia_image != (Image *) NULL)
8508 *image=DestroyImage(*image);
8511 CatchException(exception);
8512 XSetCursorState(display,windows,MagickFalse);
8513 if (windows->image.orphan != MagickFalse )
8515 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8516 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8519 case SolarizeCommand:
8525 factor[MagickPathExtent] = "60%";
8528 Query user for solarize factor.
8530 (void) XDialogWidget(display,windows,"Solarize",
8531 "Enter the solarize factor (0 - 99.9%):",factor);
8532 if (*factor == '\0')
8535 Solarize image pixels.
8537 XSetCursorState(display,windows,MagickTrue);
8538 XCheckRefreshWindows(display,windows);
8539 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8540 (void) SolarizeImage(*image,threshold,exception);
8541 XSetCursorState(display,windows,MagickFalse);
8542 if (windows->image.orphan != MagickFalse )
8544 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8545 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8554 degrees[MagickPathExtent] = "60";
8557 Query user for swirl angle.
8559 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8561 if (*degrees == '\0')
8564 Swirl image pixels about the center.
8566 XSetCursorState(display,windows,MagickTrue);
8567 XCheckRefreshWindows(display,windows);
8568 flags=ParseGeometry(degrees,&geometry_info);
8569 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8571 if (swirl_image != (Image *) NULL)
8573 *image=DestroyImage(*image);
8576 CatchException(exception);
8577 XSetCursorState(display,windows,MagickFalse);
8578 if (windows->image.orphan != MagickFalse )
8580 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8581 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8584 case ImplodeCommand:
8590 factor[MagickPathExtent] = "0.3";
8593 Query user for implode factor.
8595 (void) XDialogWidget(display,windows,"Implode",
8596 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8597 if (*factor == '\0')
8600 Implode image pixels about the center.
8602 XSetCursorState(display,windows,MagickTrue);
8603 XCheckRefreshWindows(display,windows);
8604 flags=ParseGeometry(factor,&geometry_info);
8605 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8607 if (implode_image != (Image *) NULL)
8609 *image=DestroyImage(*image);
8610 *image=implode_image;
8612 CatchException(exception);
8613 XSetCursorState(display,windows,MagickFalse);
8614 if (windows->image.orphan != MagickFalse )
8616 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8617 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8620 case VignetteCommand:
8626 geometry[MagickPathExtent] = "0x20";
8629 Query user for the vignette geometry.
8631 (void) XDialogWidget(display,windows,"Vignette",
8632 "Enter the radius, sigma, and x and y offsets:",geometry);
8633 if (*geometry == '\0')
8636 Soften the edges of the image in vignette style
8638 XSetCursorState(display,windows,MagickTrue);
8639 XCheckRefreshWindows(display,windows);
8640 flags=ParseGeometry(geometry,&geometry_info);
8641 if ((flags & SigmaValue) == 0)
8642 geometry_info.sigma=1.0;
8643 if ((flags & XiValue) == 0)
8644 geometry_info.xi=0.1*(*image)->columns;
8645 if ((flags & PsiValue) == 0)
8646 geometry_info.psi=0.1*(*image)->rows;
8647 vignette_image=VignetteImage(*image,geometry_info.rho,0.0,(ssize_t)
8648 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
8650 if (vignette_image != (Image *) NULL)
8652 *image=DestroyImage(*image);
8653 *image=vignette_image;
8655 CatchException(exception);
8656 XSetCursorState(display,windows,MagickFalse);
8657 if (windows->image.orphan != MagickFalse )
8659 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8660 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8669 geometry[MagickPathExtent] = "25x150";
8672 Query user for the wave geometry.
8674 (void) XDialogWidget(display,windows,"Wave",
8675 "Enter the amplitude and length of the wave:",geometry);
8676 if (*geometry == '\0')
8679 Alter an image along a sine wave.
8681 XSetCursorState(display,windows,MagickTrue);
8682 XCheckRefreshWindows(display,windows);
8683 flags=ParseGeometry(geometry,&geometry_info);
8684 if ((flags & SigmaValue) == 0)
8685 geometry_info.sigma=1.0;
8686 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8687 (*image)->interpolate,exception);
8688 if (wave_image != (Image *) NULL)
8690 *image=DestroyImage(*image);
8693 CatchException(exception);
8694 XSetCursorState(display,windows,MagickFalse);
8695 if (windows->image.orphan != MagickFalse )
8697 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8698 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8701 case OilPaintCommand:
8707 radius[MagickPathExtent] = "0";
8710 Query user for circular neighborhood radius.
8712 (void) XDialogWidget(display,windows,"Oil Paint",
8713 "Enter the mask radius:",radius);
8714 if (*radius == '\0')
8717 OilPaint image scanlines.
8719 XSetCursorState(display,windows,MagickTrue);
8720 XCheckRefreshWindows(display,windows);
8721 flags=ParseGeometry(radius,&geometry_info);
8722 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8724 if (paint_image != (Image *) NULL)
8726 *image=DestroyImage(*image);
8729 CatchException(exception);
8730 XSetCursorState(display,windows,MagickFalse);
8731 if (windows->image.orphan != MagickFalse )
8733 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8734 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8737 case CharcoalDrawCommand:
8743 radius[MagickPathExtent] = "0x1";
8746 Query user for charcoal radius.
8748 (void) XDialogWidget(display,windows,"Charcoal Draw",
8749 "Enter the charcoal radius and sigma:",radius);
8750 if (*radius == '\0')
8755 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8757 XSetCursorState(display,windows,MagickTrue);
8758 XCheckRefreshWindows(display,windows);
8759 flags=ParseGeometry(radius,&geometry_info);
8760 if ((flags & SigmaValue) == 0)
8761 geometry_info.sigma=geometry_info.rho;
8762 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8764 if (charcoal_image != (Image *) NULL)
8766 *image=DestroyImage(*image);
8767 *image=charcoal_image;
8769 CatchException(exception);
8770 XSetCursorState(display,windows,MagickFalse);
8771 if (windows->image.orphan != MagickFalse )
8773 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8774 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8777 case AnnotateCommand:
8780 Annotate the image with text.
8782 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8783 if (status == MagickFalse)
8785 XNoticeWidget(display,windows,"Unable to annotate X image",
8786 (*image)->filename);
8796 status=XDrawEditImage(display,resource_info,windows,image,exception);
8797 if (status == MagickFalse)
8799 XNoticeWidget(display,windows,"Unable to draw on the X image",
8800 (*image)->filename);
8810 status=XColorEditImage(display,resource_info,windows,image,exception);
8811 if (status == MagickFalse)
8813 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8814 (*image)->filename);
8824 status=XMatteEditImage(display,resource_info,windows,image,exception);
8825 if (status == MagickFalse)
8827 XNoticeWidget(display,windows,"Unable to matte edit X image",
8828 (*image)->filename);
8833 case CompositeCommand:
8838 status=XCompositeImage(display,resource_info,windows,*image,
8840 if (status == MagickFalse)
8842 XNoticeWidget(display,windows,"Unable to composite X image",
8843 (*image)->filename);
8848 case AddBorderCommand:
8854 geometry[MagickPathExtent] = "6x6";
8857 Query user for border color and geometry.
8859 XColorBrowserWidget(display,windows,"Select",color);
8862 (void) XDialogWidget(display,windows,"Add Border",
8863 "Enter border geometry:",geometry);
8864 if (*geometry == '\0')
8867 Add a border to the image.
8869 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8871 XSetCursorState(display,windows,MagickTrue);
8872 XCheckRefreshWindows(display,windows);
8873 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8875 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8877 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8879 if (border_image != (Image *) NULL)
8881 *image=DestroyImage(*image);
8882 *image=border_image;
8884 CatchException(exception);
8885 XSetCursorState(display,windows,MagickFalse);
8886 if (windows->image.orphan != MagickFalse )
8888 windows->image.window_changes.width=(int) (*image)->columns;
8889 windows->image.window_changes.height=(int) (*image)->rows;
8890 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8891 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8894 case AddFrameCommand:
8903 geometry[MagickPathExtent] = "6x6";
8906 Query user for frame color and geometry.
8908 XColorBrowserWidget(display,windows,"Select",color);
8911 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8913 if (*geometry == '\0')
8916 Surround image with an ornamental border.
8918 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8920 XSetCursorState(display,windows,MagickTrue);
8921 XCheckRefreshWindows(display,windows);
8922 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8924 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8926 frame_info.width=page_geometry.width;
8927 frame_info.height=page_geometry.height;
8928 frame_info.outer_bevel=page_geometry.x;
8929 frame_info.inner_bevel=page_geometry.y;
8930 frame_info.x=(ssize_t) frame_info.width;
8931 frame_info.y=(ssize_t) frame_info.height;
8932 frame_info.width=(*image)->columns+2*frame_info.width;
8933 frame_info.height=(*image)->rows+2*frame_info.height;
8934 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8935 if (frame_image != (Image *) NULL)
8937 *image=DestroyImage(*image);
8940 CatchException(exception);
8941 XSetCursorState(display,windows,MagickFalse);
8942 if (windows->image.orphan != MagickFalse )
8944 windows->image.window_changes.width=(int) (*image)->columns;
8945 windows->image.window_changes.height=(int) (*image)->rows;
8946 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8947 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8950 case CommentCommand:
8964 unique_file=AcquireUniqueFileResource(image_info->filename);
8965 if (unique_file == -1)
8966 XNoticeWidget(display,windows,"Unable to edit image comment",
8967 image_info->filename);
8968 value=GetImageProperty(*image,"comment",exception);
8969 if (value == (char *) NULL)
8970 unique_file=close(unique_file)-1;
8976 file=fdopen(unique_file,"w");
8977 if (file == (FILE *) NULL)
8979 XNoticeWidget(display,windows,"Unable to edit image comment",
8980 image_info->filename);
8983 for (p=value; *p != '\0'; p++)
8984 (void) fputc((int) *p,file);
8985 (void) fputc('\n',file);
8986 (void) fclose(file);
8988 XSetCursorState(display,windows,MagickTrue);
8989 XCheckRefreshWindows(display,windows);
8990 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
8992 if (status == MagickFalse)
8993 XNoticeWidget(display,windows,"Unable to edit image comment",
9000 comment=FileToString(image_info->filename,~0UL,exception);
9001 if (comment != (char *) NULL)
9003 (void) SetImageProperty(*image,"comment",comment,exception);
9004 (*image)->taint=MagickTrue;
9007 (void) RelinquishUniqueFileResource(image_info->filename);
9008 XSetCursorState(display,windows,MagickFalse);
9016 XSetCursorState(display,windows,MagickTrue);
9017 XCheckRefreshWindows(display,windows);
9018 (void) AcquireUniqueFilename(filename);
9019 (void) FormatLocaleString((*image)->filename,MagickPathExtent,"launch:%s",
9021 status=WriteImage(image_info,*image,exception);
9022 if (status == MagickFalse)
9023 XNoticeWidget(display,windows,"Unable to launch image editor",
9027 nexus=ReadImage(resource_info->image_info,exception);
9028 CatchException(exception);
9029 XClientMessage(display,windows->image.id,windows->im_protocols,
9030 windows->im_next_image,CurrentTime);
9032 (void) RelinquishUniqueFileResource(filename);
9033 XSetCursorState(display,windows,MagickFalse);
9036 case RegionofInterestCommand:
9039 Apply an image processing technique to a region of interest.
9041 (void) XROIImage(display,resource_info,windows,image,exception);
9051 if (windows->magnify.mapped != MagickFalse )
9052 (void) XRaiseWindow(display,windows->magnify.id);
9058 XSetCursorState(display,windows,MagickTrue);
9059 (void) XMapRaised(display,windows->magnify.id);
9060 XSetCursorState(display,windows,MagickFalse);
9064 case ShowPreviewCommand:
9068 value[MagickPathExtent];
9077 preview_type[MagickPathExtent] = "Gamma";
9080 Select preview type from menu.
9082 previews=GetCommandOptions(MagickPreviewOptions);
9083 if (previews == (char **) NULL)
9085 XListBrowserWidget(display,windows,&windows->widget,
9086 (const char **) previews,"Preview",
9087 "Select an enhancement, effect, or F/X:",preview_type);
9088 previews=DestroyStringList(previews);
9089 if (*preview_type == '\0')
9094 XSetCursorState(display,windows,MagickTrue);
9095 XCheckRefreshWindows(display,windows);
9096 preview=(PreviewType) ParseCommandOption(MagickPreviewOptions,
9097 MagickFalse,preview_type);
9098 (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
9100 (void) SetImageProperty(*image,"group",value,exception);
9101 (void) DeleteImageProperty(*image,"label");
9102 (void) SetImageProperty(*image,"label","Preview",exception);
9103 preview_image=PreviewImage(*image,preview,exception);
9104 if (preview_image == (Image *) NULL)
9106 (void) AcquireUniqueFilename(filename);
9107 (void) FormatLocaleString(preview_image->filename,MagickPathExtent,
9108 "show:%s",filename);
9109 status=WriteImage(image_info,preview_image,exception);
9110 (void) RelinquishUniqueFileResource(filename);
9111 preview_image=DestroyImage(preview_image);
9112 if (status == MagickFalse)
9113 XNoticeWidget(display,windows,"Unable to show image preview",
9114 (*image)->filename);
9115 XDelay(display,1500);
9116 XSetCursorState(display,windows,MagickFalse);
9119 case ShowHistogramCommand:
9122 value[MagickPathExtent];
9128 Show image histogram.
9130 XSetCursorState(display,windows,MagickTrue);
9131 XCheckRefreshWindows(display,windows);
9132 (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
9134 (void) SetImageProperty(*image,"group",value,exception);
9135 (void) DeleteImageProperty(*image,"label");
9136 (void) SetImageProperty(*image,"label","Histogram",exception);
9137 (void) AcquireUniqueFilename(filename);
9138 (void) FormatLocaleString((*image)->filename,MagickPathExtent,
9139 "histogram:%s",filename);
9140 status=WriteImage(image_info,*image,exception);
9141 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
9142 histogram_image=ReadImage(image_info,exception);
9143 (void) RelinquishUniqueFileResource(filename);
9144 if (histogram_image == (Image *) NULL)
9146 (void) FormatLocaleString(histogram_image->filename,MagickPathExtent,
9147 "show:%s",filename);
9148 status=WriteImage(image_info,histogram_image,exception);
9149 histogram_image=DestroyImage(histogram_image);
9150 if (status == MagickFalse)
9151 XNoticeWidget(display,windows,"Unable to show histogram",
9152 (*image)->filename);
9153 XDelay(display,1500);
9154 XSetCursorState(display,windows,MagickFalse);
9157 case ShowMatteCommand:
9160 value[MagickPathExtent];
9165 if ((*image)->alpha_trait == UndefinedPixelTrait)
9167 XNoticeWidget(display,windows,
9168 "Image does not have any matte information",(*image)->filename);
9174 XSetCursorState(display,windows,MagickTrue);
9175 XCheckRefreshWindows(display,windows);
9176 (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
9178 (void) SetImageProperty(*image,"group",value,exception);
9179 (void) DeleteImageProperty(*image,"label");
9180 (void) SetImageProperty(*image,"label","Matte",exception);
9181 (void) AcquireUniqueFilename(filename);
9182 (void) FormatLocaleString((*image)->filename,MagickPathExtent,"matte:%s",
9184 status=WriteImage(image_info,*image,exception);
9185 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
9186 matte_image=ReadImage(image_info,exception);
9187 (void) RelinquishUniqueFileResource(filename);
9188 if (matte_image == (Image *) NULL)
9190 (void) FormatLocaleString(matte_image->filename,MagickPathExtent,"show:%s",
9192 status=WriteImage(image_info,matte_image,exception);
9193 matte_image=DestroyImage(matte_image);
9194 if (status == MagickFalse)
9195 XNoticeWidget(display,windows,"Unable to show matte",
9196 (*image)->filename);
9197 XDelay(display,1500);
9198 XSetCursorState(display,windows,MagickFalse);
9201 case BackgroundCommand:
9206 status=XBackgroundImage(display,resource_info,windows,image,exception);
9207 if (status == MagickFalse)
9209 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9210 if (nexus != (Image *) NULL)
9211 XClientMessage(display,windows->image.id,windows->im_protocols,
9212 windows->im_next_image,CurrentTime);
9215 case SlideShowCommand:
9218 delay[MagickPathExtent] = "5";
9221 Display next image after pausing.
9223 (void) XDialogWidget(display,windows,"Slide Show",
9224 "Pause how many 1/100ths of a second between images:",delay);
9227 resource_info->delay=StringToUnsignedLong(delay);
9228 XClientMessage(display,windows->image.id,windows->im_protocols,
9229 windows->im_next_image,CurrentTime);
9232 case PreferencesCommand:
9235 Set user preferences.
9237 status=XPreferencesWidget(display,resource_info,windows);
9238 if (status == MagickFalse)
9240 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9241 if (nexus != (Image *) NULL)
9242 XClientMessage(display,windows->image.id,windows->im_protocols,
9243 windows->im_next_image,CurrentTime);
9249 User requested help.
9251 XTextViewWidget(display,resource_info,windows,MagickFalse,
9252 "Help Viewer - Display",DisplayHelp);
9255 case BrowseDocumentationCommand:
9265 Browse the ImageMagick documentation.
9267 root_window=XRootWindow(display,XDefaultScreen(display));
9268 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9269 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9270 if (mozilla_window != (Window) NULL)
9273 command[MagickPathExtent],
9277 Display documentation using Netscape remote control.
9279 url=GetMagickHomeURL();
9280 (void) FormatLocaleString(command,MagickPathExtent,
9281 "openurl(%s,new-tab)",url);
9282 url=DestroyString(url);
9283 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9284 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9285 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9286 XSetCursorState(display,windows,MagickFalse);
9289 XSetCursorState(display,windows,MagickTrue);
9290 XCheckRefreshWindows(display,windows);
9291 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9293 if (status == MagickFalse)
9294 XNoticeWidget(display,windows,"Unable to browse documentation",
9296 XDelay(display,1500);
9297 XSetCursorState(display,windows,MagickFalse);
9300 case VersionCommand:
9302 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9303 GetMagickCopyright());
9306 case SaveToUndoBufferCommand:
9310 (void) XBell(display,0);
9314 image_info=DestroyImageInfo(image_info);
9319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9323 + X M a g n i f y I m a g e %
9327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9329 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9330 % The magnified portion is displayed in a separate window.
9332 % The format of the XMagnifyImage method is:
9334 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9335 % ExceptionInfo *exception)
9337 % A description of each parameter follows:
9339 % o display: Specifies a connection to an X server; returned from
9342 % o windows: Specifies a pointer to a XWindows structure.
9344 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9345 % the entire image is refreshed.
9347 % o exception: return any errors or warnings in this structure.
9350 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9351 ExceptionInfo *exception)
9354 text[MagickPathExtent];
9364 Update magnified image until the mouse button is released.
9366 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9370 windows->magnify.x=(int) windows->image.x+x;
9371 windows->magnify.y=(int) windows->image.y+y;
9375 Map and unmap Info widget as text cursor crosses its boundaries.
9377 if (windows->info.mapped != MagickFalse )
9379 if ((x < (int) (windows->info.x+windows->info.width)) &&
9380 (y < (int) (windows->info.y+windows->info.height)))
9381 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9384 if ((x > (int) (windows->info.x+windows->info.width)) ||
9385 (y > (int) (windows->info.y+windows->info.height)))
9386 (void) XMapWindow(display,windows->info.id);
9387 if (windows->info.mapped != MagickFalse )
9390 Display pointer position.
9392 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
9393 windows->magnify.x,windows->magnify.y);
9394 XInfoWidget(display,windows,text);
9397 Wait for next event.
9399 XScreenEvent(display,windows,event,exception);
9400 switch (event->type)
9407 User has finished magnifying image.
9426 Check boundary conditions.
9431 if (x >= (int) windows->image.width)
9432 x=(int) windows->image.width-1;
9436 if (y >= (int) windows->image.height)
9437 y=(int) windows->image.height-1;
9438 } while ((state & ExitState) == 0);
9440 Display magnified image.
9442 XSetCursorState(display,windows,MagickFalse);
9446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9450 + X M a g n i f y W i n d o w C o m m a n d %
9454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9456 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9457 % pixel as specified by the key symbol.
9459 % The format of the XMagnifyWindowCommand method is:
9461 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9462 % const MagickStatusType state,const KeySym key_symbol,
9463 % ExceptionInfo *exception)
9465 % A description of each parameter follows:
9467 % o display: Specifies a connection to an X server; returned from
9470 % o windows: Specifies a pointer to a XWindows structure.
9472 % o state: key mask.
9474 % o key_symbol: Specifies a KeySym which indicates which side of the image
9477 % o exception: return any errors or warnings in this structure.
9480 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9481 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9487 User specified a magnify factor or position.
9490 if ((state & Mod1Mask) != 0)
9492 switch ((int) key_symbol)
9496 (void) XWithdrawWindow(display,windows->magnify.id,
9497 windows->magnify.screen);
9503 windows->magnify.x=(int) windows->image.width/2;
9504 windows->magnify.y=(int) windows->image.height/2;
9510 if (windows->magnify.x > 0)
9511 windows->magnify.x-=quantum;
9517 if (windows->magnify.y > 0)
9518 windows->magnify.y-=quantum;
9524 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9525 windows->magnify.x+=quantum;
9531 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9532 windows->magnify.y+=quantum;
9546 windows->magnify.data=(key_symbol-XK_0);
9560 windows->magnify.data=(key_symbol-XK_KP_0);
9566 XMakeMagnifyImage(display,windows,exception);
9570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9574 + X M a k e P a n I m a g e %
9578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9580 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9583 % The format of the XMakePanImage method is:
9585 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9586 % XWindows *windows,Image *image,ExceptionInfo *exception)
9588 % A description of each parameter follows:
9590 % o display: Specifies a connection to an X server; returned from
9593 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9595 % o windows: Specifies a pointer to a XWindows structure.
9597 % o image: the image.
9599 % o exception: return any errors or warnings in this structure.
9602 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9603 XWindows *windows,Image *image,ExceptionInfo *exception)
9609 Create and display image for panning icon.
9611 XSetCursorState(display,windows,MagickTrue);
9612 XCheckRefreshWindows(display,windows);
9613 windows->pan.x=(int) windows->image.x;
9614 windows->pan.y=(int) windows->image.y;
9615 status=XMakeImage(display,resource_info,&windows->pan,image,
9616 windows->pan.width,windows->pan.height,exception);
9617 if (status == MagickFalse)
9618 ThrowXWindowException(ResourceLimitError,
9619 "MemoryAllocationFailed",image->filename);
9620 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9621 windows->pan.pixmap);
9622 (void) XClearWindow(display,windows->pan.id);
9623 XDrawPanRectangle(display,windows);
9624 XSetCursorState(display,windows,MagickFalse);
9628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9632 + X M a t t a E d i t I m a g e %
9636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9638 % XMatteEditImage() allows the user to interactively change the Matte channel
9639 % of an image. If the image is PseudoClass it is promoted to DirectClass
9640 % before the matte information is stored.
9642 % The format of the XMatteEditImage method is:
9644 % MagickBooleanType XMatteEditImage(Display *display,
9645 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9646 % ExceptionInfo *exception)
9648 % A description of each parameter follows:
9650 % o display: Specifies a connection to an X server; returned from
9653 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9655 % o windows: Specifies a pointer to a XWindows structure.
9657 % o image: the image; returned from ReadImage.
9659 % o exception: return any errors or warnings in this structure.
9662 static MagickBooleanType XMatteEditImage(Display *display,
9663 XResourceInfo *resource_info,XWindows *windows,Image **image,
9664 ExceptionInfo *exception)
9667 matte[MagickPathExtent] = "0";
9682 static const ModeType
9683 MatteEditCommands[] =
9686 MatteEditBorderCommand,
9687 MatteEditFuzzCommand,
9688 MatteEditValueCommand,
9689 MatteEditUndoCommand,
9690 MatteEditHelpCommand,
9691 MatteEditDismissCommand
9695 method = PointMethod;
9698 border_color = { 0, 0, 0, 0, 0, 0 };
9701 command[MagickPathExtent],
9702 text[MagickPathExtent];
9734 (void) CloneString(&windows->command.name,"Matte Edit");
9735 windows->command.data=4;
9736 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9737 (void) XMapRaised(display,windows->command.id);
9738 XClientMessage(display,windows->image.id,windows->im_protocols,
9739 windows->im_update_widget,CurrentTime);
9743 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9744 resource_info->background_color,resource_info->foreground_color);
9745 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9747 Track pointer until button 1 is pressed.
9749 XQueryPosition(display,windows->image.id,&x,&y);
9750 (void) XSelectInput(display,windows->image.id,
9751 windows->image.attributes.event_mask | PointerMotionMask);
9755 if (windows->info.mapped != MagickFalse )
9758 Display pointer position.
9760 (void) FormatLocaleString(text,MagickPathExtent," %+d%+d ",
9761 x+windows->image.x,y+windows->image.y);
9762 XInfoWidget(display,windows,text);
9765 Wait for next event.
9767 XScreenEvent(display,windows,&event,exception);
9768 if (event.xany.window == windows->command.id)
9771 Select a command from the Command widget.
9773 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9776 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9779 switch (MatteEditCommands[id])
9781 case MatteEditMethod:
9787 Select a method from the pop-up menu.
9789 methods=GetCommandOptions(MagickMethodOptions);
9790 if (methods == (char **) NULL)
9792 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9793 (const char **) methods,command);
9795 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9796 MagickFalse,methods[entry]);
9797 methods=DestroyStringList(methods);
9800 case MatteEditBorderCommand:
9803 *ColorMenu[MaxNumberPens];
9809 Initialize menu selections.
9811 for (i=0; i < (int) (MaxNumberPens-2); i++)
9812 ColorMenu[i]=resource_info->pen_colors[i];
9813 ColorMenu[MaxNumberPens-2]="Browser...";
9814 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9816 Select a pen color from the pop-up menu.
9818 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9819 (const char **) ColorMenu,command);
9822 if (pen_number == (MaxNumberPens-2))
9825 color_name[MagickPathExtent] = "gray";
9828 Select a pen color from a dialog.
9830 resource_info->pen_colors[pen_number]=color_name;
9831 XColorBrowserWidget(display,windows,"Select",color_name);
9832 if (*color_name == '\0')
9838 (void) XParseColor(display,windows->map_info->colormap,
9839 resource_info->pen_colors[pen_number],&border_color);
9842 case MatteEditFuzzCommand:
9845 fuzz[MagickPathExtent];
9860 Select a command from the pop-up menu.
9862 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9868 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9872 (void) CopyMagickString(fuzz,"20%",MagickPathExtent);
9873 (void) XDialogWidget(display,windows,"Ok",
9874 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9877 (void) ConcatenateMagickString(fuzz,"%",MagickPathExtent);
9878 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9882 case MatteEditValueCommand:
9885 message[MagickPathExtent];
9897 Select a command from the pop-up menu.
9899 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9905 (void) FormatLocaleString(matte,MagickPathExtent,QuantumFormat,
9907 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9908 (void) FormatLocaleString(matte,MagickPathExtent,
9909 QuantumFormat,(Quantum) TransparentAlpha);
9912 (void) FormatLocaleString(message,MagickPathExtent,
9913 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9915 (void) XDialogWidget(display,windows,"Matte",message,matte);
9920 case MatteEditUndoCommand:
9922 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9926 case MatteEditHelpCommand:
9928 XTextViewWidget(display,resource_info,windows,MagickFalse,
9929 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9932 case MatteEditDismissCommand:
9944 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9951 if (event.xbutton.button != Button1)
9953 if ((event.xbutton.window != windows->image.id) &&
9954 (event.xbutton.window != windows->magnify.id))
9961 (void) XMagickCommand(display,resource_info,windows,
9962 SaveToUndoBufferCommand,image,exception);
9963 state|=UpdateConfigurationState;
9968 if (event.xbutton.button != Button1)
9970 if ((event.xbutton.window != windows->image.id) &&
9971 (event.xbutton.window != windows->magnify.id))
9974 Update colormap information.
9978 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9979 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9980 XInfoWidget(display,windows,text);
9981 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9982 state&=(~UpdateConfigurationState);
9990 command[MagickPathExtent];
9995 if (event.xkey.window == windows->magnify.id)
10000 window=windows->magnify.id;
10001 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
10003 if (event.xkey.window != windows->image.id)
10006 Respond to a user key press.
10008 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10009 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10010 switch ((int) key_symbol)
10024 XTextViewWidget(display,resource_info,windows,MagickFalse,
10025 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10030 (void) XBell(display,0);
10039 Map and unmap Info widget as cursor crosses its boundaries.
10043 if (windows->info.mapped != MagickFalse )
10045 if ((x < (int) (windows->info.x+windows->info.width)) &&
10046 (y < (int) (windows->info.y+windows->info.height)))
10047 (void) XWithdrawWindow(display,windows->info.id,
10048 windows->info.screen);
10051 if ((x > (int) (windows->info.x+windows->info.width)) ||
10052 (y > (int) (windows->info.y+windows->info.height)))
10053 (void) XMapWindow(display,windows->info.id);
10059 if (event.xany.window == windows->magnify.id)
10061 x=windows->magnify.x-windows->image.x;
10062 y=windows->magnify.y-windows->image.y;
10066 if ((state & UpdateConfigurationState) != 0)
10076 Matte edit is relative to image configuration.
10078 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10080 XPutPixel(windows->image.ximage,x_offset,y_offset,
10081 windows->pixel_info->background_color.pixel);
10082 width=(unsigned int) (*image)->columns;
10083 height=(unsigned int) (*image)->rows;
10086 if (windows->image.crop_geometry != (char *) NULL)
10087 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10089 x_offset=(int) (width*(windows->image.x+x_offset)/
10090 windows->image.ximage->width+x);
10091 y_offset=(int) (height*(windows->image.y+y_offset)/
10092 windows->image.ximage->height+y);
10093 if ((x_offset < 0) || (y_offset < 0))
10095 if ((x_offset >= (int) (*image)->columns) ||
10096 (y_offset >= (int) (*image)->rows))
10098 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10099 return(MagickFalse);
10100 if ((*image)->alpha_trait == UndefinedPixelTrait)
10101 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10102 image_view=AcquireAuthenticCacheView(*image,exception);
10109 Update matte information using point algorithm.
10111 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10112 (ssize_t) y_offset,1,1,exception);
10113 if (q == (Quantum *) NULL)
10115 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10116 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10119 case ReplaceMethod:
10126 Update matte information using replace algorithm.
10128 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
10129 x_offset,(ssize_t) y_offset,&target,exception);
10130 for (y=0; y < (int) (*image)->rows; y++)
10132 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10133 (*image)->columns,1,exception);
10134 if (q == (Quantum *) NULL)
10136 for (x=0; x < (int) (*image)->columns; x++)
10138 GetPixelInfoPixel(*image,q,&pixel);
10139 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10140 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10141 q+=GetPixelChannels(*image);
10143 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10148 case FloodfillMethod:
10149 case FillToBorderMethod:
10161 Update matte information using floodfill algorithm.
10163 (void) GetOneVirtualPixelInfo(*image,
10164 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10165 y_offset,&target,exception);
10166 if (method == FillToBorderMethod)
10168 target.red=(double) ScaleShortToQuantum(
10170 target.green=(double) ScaleShortToQuantum(
10171 border_color.green);
10172 target.blue=(double) ScaleShortToQuantum(
10173 border_color.blue);
10175 draw_info=CloneDrawInfo(resource_info->image_info,
10176 (DrawInfo *) NULL);
10177 draw_info->fill.alpha=(double) ClampToQuantum(
10178 StringToDouble(matte,(char **) NULL));
10179 channel_mask=SetImageChannelMask(*image,AlphaChannel);
10180 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10181 x_offset,(ssize_t) y_offset,
10182 method != FloodfillMethod ? MagickTrue : MagickFalse,exception);
10183 (void) SetPixelChannelMask(*image,channel_mask);
10184 draw_info=DestroyDrawInfo(draw_info);
10190 Update matte information using reset algorithm.
10192 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10193 return(MagickFalse);
10194 for (y=0; y < (int) (*image)->rows; y++)
10196 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10197 (*image)->columns,1,exception);
10198 if (q == (Quantum *) NULL)
10200 for (x=0; x < (int) (*image)->columns; x++)
10202 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10203 q+=GetPixelChannels(*image);
10205 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10208 if (StringToLong(matte) == (long) OpaqueAlpha)
10209 (*image)->alpha_trait=UndefinedPixelTrait;
10213 image_view=DestroyCacheView(image_view);
10214 state&=(~UpdateConfigurationState);
10216 } while ((state & ExitState) == 0);
10217 (void) XSelectInput(display,windows->image.id,
10218 windows->image.attributes.event_mask);
10219 XSetCursorState(display,windows,MagickFalse);
10220 (void) XFreeCursor(display,cursor);
10221 return(MagickTrue);
10225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10229 + X O p e n I m a g e %
10233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10235 % XOpenImage() loads an image from a file.
10237 % The format of the XOpenImage method is:
10239 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10240 % XWindows *windows,const unsigned int command)
10242 % A description of each parameter follows:
10244 % o display: Specifies a connection to an X server; returned from
10247 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10249 % o windows: Specifies a pointer to a XWindows structure.
10251 % o command: A value other than zero indicates that the file is selected
10252 % from the command line argument list.
10255 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10256 XWindows *windows,const MagickBooleanType command)
10271 filename[MagickPathExtent] = "\0";
10274 Request file name from user.
10276 if (command == MagickFalse)
10277 XFileBrowserWidget(display,windows,"Open",filename);
10293 Select next image from the command line.
10295 status=XGetCommand(display,windows->image.id,&files,&count);
10298 ThrowXWindowException(XServerError,"UnableToGetProperty","...");
10299 return((Image *) NULL);
10301 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10302 if (filelist == (char **) NULL)
10304 ThrowXWindowException(ResourceLimitError,
10305 "MemoryAllocationFailed","...");
10306 (void) XFreeStringList(files);
10307 return((Image *) NULL);
10310 for (i=1; i < count; i++)
10311 if (*files[i] != '-')
10312 filelist[j++]=files[i];
10313 filelist[j]=(char *) NULL;
10314 XListBrowserWidget(display,windows,&windows->widget,
10315 (const char **) filelist,"Load","Select Image to Load:",filename);
10316 filelist=(char **) RelinquishMagickMemory(filelist);
10317 (void) XFreeStringList(files);
10319 if (*filename == '\0')
10320 return((Image *) NULL);
10321 image_info=CloneImageInfo(resource_info->image_info);
10322 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10324 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
10325 exception=AcquireExceptionInfo();
10326 (void) SetImageInfo(image_info,0,exception);
10327 if (LocaleCompare(image_info->magick,"X") == 0)
10330 seconds[MagickPathExtent];
10333 User may want to delay the X server screen grab.
10335 (void) CopyMagickString(seconds,"0",MagickPathExtent);
10336 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10338 if (*seconds == '\0')
10339 return((Image *) NULL);
10340 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10342 magick_info=GetMagickInfo(image_info->magick,exception);
10343 if ((magick_info != (const MagickInfo *) NULL) &&
10344 GetMagickRawSupport(magick_info) == MagickTrue)
10347 geometry[MagickPathExtent];
10350 Request image size from the user.
10352 (void) CopyMagickString(geometry,"512x512",MagickPathExtent);
10353 if (image_info->size != (char *) NULL)
10354 (void) CopyMagickString(geometry,image_info->size,MagickPathExtent);
10355 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10357 (void) CloneString(&image_info->size,geometry);
10362 XSetCursorState(display,windows,MagickTrue);
10363 XCheckRefreshWindows(display,windows);
10364 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
10365 nexus=ReadImage(image_info,exception);
10366 CatchException(exception);
10367 XSetCursorState(display,windows,MagickFalse);
10368 if (nexus != (Image *) NULL)
10369 XClientMessage(display,windows->image.id,windows->im_protocols,
10370 windows->im_next_image,CurrentTime);
10378 Unknown image format.
10380 text=FileToString(filename,~0UL,exception);
10381 if (text == (char *) NULL)
10382 return((Image *) NULL);
10383 textlist=StringToList(text);
10384 if (textlist != (char **) NULL)
10387 title[MagickPathExtent];
10392 (void) FormatLocaleString(title,MagickPathExtent,
10393 "Unknown format: %s",filename);
10394 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10395 (const char **) textlist);
10396 for (i=0; textlist[i] != (char *) NULL; i++)
10397 textlist[i]=DestroyString(textlist[i]);
10398 textlist=(char **) RelinquishMagickMemory(textlist);
10400 text=DestroyString(text);
10402 exception=DestroyExceptionInfo(exception);
10403 image_info=DestroyImageInfo(image_info);
10408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10412 + X P a n I m a g e %
10416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10418 % XPanImage() pans the image until the mouse button is released.
10420 % The format of the XPanImage method is:
10422 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10423 % ExceptionInfo *exception)
10425 % A description of each parameter follows:
10427 % o display: Specifies a connection to an X server; returned from
10430 % o windows: Specifies a pointer to a XWindows structure.
10432 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10433 % the entire image is refreshed.
10435 % o exception: return any errors or warnings in this structure.
10438 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10439 ExceptionInfo *exception)
10442 text[MagickPathExtent];
10460 if ((windows->image.ximage->width > (int) windows->image.width) &&
10461 (windows->image.ximage->height > (int) windows->image.height))
10462 cursor=XCreateFontCursor(display,XC_fleur);
10464 if (windows->image.ximage->width > (int) windows->image.width)
10465 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10467 if (windows->image.ximage->height > (int) windows->image.height)
10468 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10470 cursor=XCreateFontCursor(display,XC_arrow);
10471 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10473 Pan image as pointer moves until the mouse button is released.
10475 x_factor=(double) windows->image.ximage->width/windows->pan.width;
10476 y_factor=(double) windows->image.ximage->height/windows->pan.height;
10477 pan_info.width=windows->pan.width*windows->image.width/
10478 windows->image.ximage->width;
10479 pan_info.height=windows->pan.height*windows->image.height/
10480 windows->image.ximage->height;
10483 state=UpdateConfigurationState;
10486 switch (event->type)
10491 User choose an initial pan location.
10493 pan_info.x=(ssize_t) event->xbutton.x;
10494 pan_info.y=(ssize_t) event->xbutton.y;
10495 state|=UpdateConfigurationState;
10498 case ButtonRelease:
10501 User has finished panning the image.
10503 pan_info.x=(ssize_t) event->xbutton.x;
10504 pan_info.y=(ssize_t) event->xbutton.y;
10505 state|=UpdateConfigurationState | ExitState;
10510 pan_info.x=(ssize_t) event->xmotion.x;
10511 pan_info.y=(ssize_t) event->xmotion.y;
10512 state|=UpdateConfigurationState;
10517 if ((state & UpdateConfigurationState) != 0)
10520 Check boundary conditions.
10522 if (pan_info.x < (ssize_t) (pan_info.width/2))
10525 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10526 if (pan_info.x < 0)
10529 if ((int) (pan_info.x+windows->image.width) >
10530 windows->image.ximage->width)
10531 pan_info.x=(ssize_t)
10532 (windows->image.ximage->width-windows->image.width);
10533 if (pan_info.y < (ssize_t) (pan_info.height/2))
10536 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10537 if (pan_info.y < 0)
10540 if ((int) (pan_info.y+windows->image.height) >
10541 windows->image.ximage->height)
10542 pan_info.y=(ssize_t)
10543 (windows->image.ximage->height-windows->image.height);
10544 if ((windows->image.x != (int) pan_info.x) ||
10545 (windows->image.y != (int) pan_info.y))
10548 Display image pan offset.
10550 windows->image.x=(int) pan_info.x;
10551 windows->image.y=(int) pan_info.y;
10552 (void) FormatLocaleString(text,MagickPathExtent," %ux%u%+d%+d ",
10553 windows->image.width,windows->image.height,windows->image.x,
10555 XInfoWidget(display,windows,text);
10557 Refresh Image window.
10559 XDrawPanRectangle(display,windows);
10560 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10562 state&=(~UpdateConfigurationState);
10565 Wait for next event.
10567 if ((state & ExitState) == 0)
10568 XScreenEvent(display,windows,event,exception);
10569 } while ((state & ExitState) == 0);
10573 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10574 (void) XFreeCursor(display,cursor);
10575 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10583 + X P a s t e I m a g e %
10587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10589 % XPasteImage() pastes an image previously saved with XCropImage in the X
10590 % window image at a location the user chooses with the pointer.
10592 % The format of the XPasteImage method is:
10594 % MagickBooleanType XPasteImage(Display *display,
10595 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10596 % ExceptionInfo *exception)
10598 % A description of each parameter follows:
10600 % o display: Specifies a connection to an X server; returned from
10603 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10605 % o windows: Specifies a pointer to a XWindows structure.
10607 % o image: the image; returned from ReadImage.
10609 % o exception: return any errors or warnings in this structure.
10612 static MagickBooleanType XPasteImage(Display *display,
10613 XResourceInfo *resource_info,XWindows *windows,Image *image,
10614 ExceptionInfo *exception)
10625 static const ModeType
10628 PasteOperatorsCommand,
10630 PasteDismissCommand
10633 static CompositeOperator
10634 compose = CopyCompositeOp;
10637 text[MagickPathExtent];
10671 if (resource_info->copy_image == (Image *) NULL)
10672 return(MagickFalse);
10673 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10674 if (paste_image == (Image *) NULL)
10675 return(MagickFalse);
10677 Map Command widget.
10679 (void) CloneString(&windows->command.name,"Paste");
10680 windows->command.data=1;
10681 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10682 (void) XMapRaised(display,windows->command.id);
10683 XClientMessage(display,windows->image.id,windows->im_protocols,
10684 windows->im_update_widget,CurrentTime);
10686 Track pointer until button 1 is pressed.
10688 XSetCursorState(display,windows,MagickFalse);
10689 XQueryPosition(display,windows->image.id,&x,&y);
10690 (void) XSelectInput(display,windows->image.id,
10691 windows->image.attributes.event_mask | PointerMotionMask);
10692 paste_info.x=(ssize_t) windows->image.x+x;
10693 paste_info.y=(ssize_t) windows->image.y+y;
10694 paste_info.width=0;
10695 paste_info.height=0;
10696 cursor=XCreateFontCursor(display,XC_ul_angle);
10697 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10698 state=DefaultState;
10701 if (windows->info.mapped != MagickFalse )
10704 Display pointer position.
10706 (void) FormatLocaleString(text,MagickPathExtent," %+ld%+ld ",
10707 (long) paste_info.x,(long) paste_info.y);
10708 XInfoWidget(display,windows,text);
10710 highlight_info=paste_info;
10711 highlight_info.x=paste_info.x-windows->image.x;
10712 highlight_info.y=paste_info.y-windows->image.y;
10713 XHighlightRectangle(display,windows->image.id,
10714 windows->image.highlight_context,&highlight_info);
10716 Wait for next event.
10718 XScreenEvent(display,windows,&event,exception);
10719 XHighlightRectangle(display,windows->image.id,
10720 windows->image.highlight_context,&highlight_info);
10721 if (event.xany.window == windows->command.id)
10724 Select a command from the Command widget.
10726 id=XCommandWidget(display,windows,PasteMenu,&event);
10729 switch (PasteCommands[id])
10731 case PasteOperatorsCommand:
10734 command[MagickPathExtent],
10738 Select a command from the pop-up menu.
10740 operators=GetCommandOptions(MagickComposeOptions);
10741 if (operators == (char **) NULL)
10743 entry=XMenuWidget(display,windows,PasteMenu[id],
10744 (const char **) operators,command);
10746 compose=(CompositeOperator) ParseCommandOption(
10747 MagickComposeOptions,MagickFalse,operators[entry]);
10748 operators=DestroyStringList(operators);
10751 case PasteHelpCommand:
10753 XTextViewWidget(display,resource_info,windows,MagickFalse,
10754 "Help Viewer - Image Composite",ImagePasteHelp);
10757 case PasteDismissCommand:
10762 state|=EscapeState;
10771 switch (event.type)
10775 if (image->debug != MagickFalse )
10776 (void) LogMagickEvent(X11Event,GetMagickModule(),
10777 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10778 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10779 if (event.xbutton.button != Button1)
10781 if (event.xbutton.window != windows->image.id)
10784 Paste rectangle is relative to image configuration.
10786 width=(unsigned int) image->columns;
10787 height=(unsigned int) image->rows;
10790 if (windows->image.crop_geometry != (char *) NULL)
10791 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10793 scale_factor=(double) windows->image.ximage->width/width;
10794 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10795 scale_factor=(double) windows->image.ximage->height/height;
10796 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10797 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10798 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10799 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10802 case ButtonRelease:
10804 if (image->debug != MagickFalse )
10805 (void) LogMagickEvent(X11Event,GetMagickModule(),
10806 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10807 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10808 if (event.xbutton.button != Button1)
10810 if (event.xbutton.window != windows->image.id)
10812 if ((paste_info.width != 0) && (paste_info.height != 0))
10815 User has selected the location of the paste image.
10817 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10818 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10828 command[MagickPathExtent];
10836 if (event.xkey.window != windows->image.id)
10839 Respond to a user key press.
10841 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10842 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10843 *(command+length)='\0';
10844 if (image->debug != MagickFalse )
10845 (void) LogMagickEvent(X11Event,GetMagickModule(),
10846 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10847 switch ((int) key_symbol)
10855 paste_image=DestroyImage(paste_image);
10856 state|=EscapeState;
10863 (void) XSetFunction(display,windows->image.highlight_context,
10865 XTextViewWidget(display,resource_info,windows,MagickFalse,
10866 "Help Viewer - Image Composite",ImagePasteHelp);
10867 (void) XSetFunction(display,windows->image.highlight_context,
10873 (void) XBell(display,0);
10882 Map and unmap Info widget as text cursor crosses its boundaries.
10886 if (windows->info.mapped != MagickFalse )
10888 if ((x < (int) (windows->info.x+windows->info.width)) &&
10889 (y < (int) (windows->info.y+windows->info.height)))
10890 (void) XWithdrawWindow(display,windows->info.id,
10891 windows->info.screen);
10894 if ((x > (int) (windows->info.x+windows->info.width)) ||
10895 (y > (int) (windows->info.y+windows->info.height)))
10896 (void) XMapWindow(display,windows->info.id);
10897 paste_info.x=(ssize_t) windows->image.x+x;
10898 paste_info.y=(ssize_t) windows->image.y+y;
10903 if (image->debug != MagickFalse )
10904 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10909 } while ((state & ExitState) == 0);
10910 (void) XSelectInput(display,windows->image.id,
10911 windows->image.attributes.event_mask);
10912 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10913 XSetCursorState(display,windows,MagickFalse);
10914 (void) XFreeCursor(display,cursor);
10915 if ((state & EscapeState) != 0)
10916 return(MagickTrue);
10918 Image pasting is relative to image configuration.
10920 XSetCursorState(display,windows,MagickTrue);
10921 XCheckRefreshWindows(display,windows);
10922 width=(unsigned int) image->columns;
10923 height=(unsigned int) image->rows;
10926 if (windows->image.crop_geometry != (char *) NULL)
10927 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10928 scale_factor=(double) width/windows->image.ximage->width;
10930 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10931 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10932 scale_factor=(double) height/windows->image.ximage->height;
10934 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10935 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10937 Paste image with X Image window.
10939 (void) CompositeImage(image,paste_image,compose,MagickTrue,paste_info.x,
10940 paste_info.y,exception);
10941 paste_image=DestroyImage(paste_image);
10942 XSetCursorState(display,windows,MagickFalse);
10944 Update image colormap.
10946 XConfigureImageColormap(display,resource_info,windows,image,exception);
10947 (void) XConfigureImage(display,resource_info,windows,image,exception);
10948 return(MagickTrue);
10952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10956 + X P r i n t I m a g e %
10960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10962 % XPrintImage() prints an image to a Postscript printer.
10964 % The format of the XPrintImage method is:
10966 % MagickBooleanType XPrintImage(Display *display,
10967 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10968 % ExceptionInfo *exception)
10970 % A description of each parameter follows:
10972 % o display: Specifies a connection to an X server; returned from
10975 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10977 % o windows: Specifies a pointer to a XWindows structure.
10979 % o image: the image.
10981 % o exception: return any errors or warnings in this structure.
10984 static MagickBooleanType XPrintImage(Display *display,
10985 XResourceInfo *resource_info,XWindows *windows,Image *image,
10986 ExceptionInfo *exception)
10989 filename[MagickPathExtent],
10990 geometry[MagickPathExtent];
11002 Request Postscript page geometry from user.
11004 image_info=CloneImageInfo(resource_info->image_info);
11005 (void) FormatLocaleString(geometry,MagickPathExtent,"Letter");
11006 if (image_info->page != (char *) NULL)
11007 (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
11008 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11009 "Select Postscript Page Geometry:",geometry);
11010 if (*geometry == '\0')
11011 return(MagickTrue);
11012 image_info->page=GetPageGeometry(geometry);
11014 Apply image transforms.
11016 XSetCursorState(display,windows,MagickTrue);
11017 XCheckRefreshWindows(display,windows);
11018 print_image=CloneImage(image,0,0,MagickTrue,exception);
11019 if (print_image == (Image *) NULL)
11020 return(MagickFalse);
11021 (void) FormatLocaleString(geometry,MagickPathExtent,"%dx%d!",
11022 windows->image.ximage->width,windows->image.ximage->height);
11023 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11028 (void) AcquireUniqueFilename(filename);
11029 (void) FormatLocaleString(print_image->filename,MagickPathExtent,"print:%s",
11031 status=WriteImage(image_info,print_image,exception);
11032 (void) RelinquishUniqueFileResource(filename);
11033 print_image=DestroyImage(print_image);
11034 image_info=DestroyImageInfo(image_info);
11035 XSetCursorState(display,windows,MagickFalse);
11036 return(status != 0 ? MagickTrue : MagickFalse);
11040 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11044 + X R O I I m a g e %
11048 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11050 % XROIImage() applies an image processing technique to a region of interest.
11052 % The format of the XROIImage method is:
11054 % MagickBooleanType XROIImage(Display *display,
11055 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11056 % ExceptionInfo *exception)
11058 % A description of each parameter follows:
11060 % o display: Specifies a connection to an X server; returned from
11063 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11065 % o windows: Specifies a pointer to a XWindows structure.
11067 % o image: the image; returned from ReadImage.
11069 % o exception: return any errors or warnings in this structure.
11072 static MagickBooleanType XROIImage(Display *display,
11073 XResourceInfo *resource_info,XWindows *windows,Image **image,
11074 ExceptionInfo *exception)
11076 #define ApplyMenus 7
11126 "Contrast Stretch...",
11127 "Sigmoidal Contrast...",
11161 "Charcoal Draw...",
11164 *MiscellanyMenu[] =
11175 **Menus[ApplyMenus] =
11186 static const CommandType
11209 TransformCommands[] =
11213 RotateRightCommand,
11216 EnhanceCommands[] =
11224 ContrastStretchCommand,
11225 SigmoidalContrastCommand,
11233 EffectsCommands[] =
11237 ReduceNoiseCommand,
11256 CharcoalDrawCommand
11258 MiscellanyCommands[] =
11262 ShowPreviewCommand,
11263 ShowHistogramCommand,
11272 static const CommandType
11273 *Commands[ApplyMenus] =
11285 command[MagickPathExtent],
11286 text[MagickPathExtent];
11306 MagickProgressMonitor
11325 Map Command widget.
11327 (void) CloneString(&windows->command.name,"ROI");
11328 windows->command.data=0;
11329 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11330 (void) XMapRaised(display,windows->command.id);
11331 XClientMessage(display,windows->image.id,windows->im_protocols,
11332 windows->im_update_widget,CurrentTime);
11334 Track pointer until button 1 is pressed.
11336 XQueryPosition(display,windows->image.id,&x,&y);
11337 (void) XSelectInput(display,windows->image.id,
11338 windows->image.attributes.event_mask | PointerMotionMask);
11339 roi_info.x=(ssize_t) windows->image.x+x;
11340 roi_info.y=(ssize_t) windows->image.y+y;
11343 cursor=XCreateFontCursor(display,XC_fleur);
11344 state=DefaultState;
11347 if (windows->info.mapped != MagickFalse )
11350 Display pointer position.
11352 (void) FormatLocaleString(text,MagickPathExtent," %+ld%+ld ",
11353 (long) roi_info.x,(long) roi_info.y);
11354 XInfoWidget(display,windows,text);
11357 Wait for next event.
11359 XScreenEvent(display,windows,&event,exception);
11360 if (event.xany.window == windows->command.id)
11363 Select a command from the Command widget.
11365 id=XCommandWidget(display,windows,ROIMenu,&event);
11368 switch (ROICommands[id])
11370 case ROIHelpCommand:
11372 XTextViewWidget(display,resource_info,windows,MagickFalse,
11373 "Help Viewer - Region of Interest",ImageROIHelp);
11376 case ROIDismissCommand:
11381 state|=EscapeState;
11390 switch (event.type)
11394 if (event.xbutton.button != Button1)
11396 if (event.xbutton.window != windows->image.id)
11399 Note first corner of region of interest rectangle-- exit loop.
11401 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11402 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11403 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11407 case ButtonRelease:
11416 if (event.xkey.window != windows->image.id)
11419 Respond to a user key press.
11421 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11422 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11423 switch ((int) key_symbol)
11431 state|=EscapeState;
11438 XTextViewWidget(display,resource_info,windows,MagickFalse,
11439 "Help Viewer - Region of Interest",ImageROIHelp);
11444 (void) XBell(display,0);
11453 Map and unmap Info widget as text cursor crosses its boundaries.
11457 if (windows->info.mapped != MagickFalse )
11459 if ((x < (int) (windows->info.x+windows->info.width)) &&
11460 (y < (int) (windows->info.y+windows->info.height)))
11461 (void) XWithdrawWindow(display,windows->info.id,
11462 windows->info.screen);
11465 if ((x > (int) (windows->info.x+windows->info.width)) ||
11466 (y > (int) (windows->info.y+windows->info.height)))
11467 (void) XMapWindow(display,windows->info.id);
11468 roi_info.x=(ssize_t) windows->image.x+x;
11469 roi_info.y=(ssize_t) windows->image.y+y;
11475 } while ((state & ExitState) == 0);
11476 (void) XSelectInput(display,windows->image.id,
11477 windows->image.attributes.event_mask);
11478 if ((state & EscapeState) != 0)
11481 User want to exit without region of interest.
11483 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11484 (void) XFreeCursor(display,cursor);
11485 return(MagickTrue);
11487 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11491 Size rectangle as pointer moves until the mouse button is released.
11493 x=(int) roi_info.x;
11494 y=(int) roi_info.y;
11497 state=DefaultState;
11500 highlight_info=roi_info;
11501 highlight_info.x=roi_info.x-windows->image.x;
11502 highlight_info.y=roi_info.y-windows->image.y;
11503 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11506 Display info and draw region of interest rectangle.
11508 if (windows->info.mapped == MagickFalse)
11509 (void) XMapWindow(display,windows->info.id);
11510 (void) FormatLocaleString(text,MagickPathExtent,
11511 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11512 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11513 XInfoWidget(display,windows,text);
11514 XHighlightRectangle(display,windows->image.id,
11515 windows->image.highlight_context,&highlight_info);
11518 if (windows->info.mapped != MagickFalse )
11519 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11521 Wait for next event.
11523 XScreenEvent(display,windows,&event,exception);
11524 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11525 XHighlightRectangle(display,windows->image.id,
11526 windows->image.highlight_context,&highlight_info);
11527 switch (event.type)
11531 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11532 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11535 case ButtonRelease:
11538 User has committed to region of interest rectangle.
11540 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11541 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11542 XSetCursorState(display,windows,MagickFalse);
11544 if (LocaleCompare(windows->command.name,"Apply") == 0)
11546 (void) CloneString(&windows->command.name,"Apply");
11547 windows->command.data=ApplyMenus;
11548 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11555 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11556 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11561 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11562 ((state & ExitState) != 0))
11565 Check boundary conditions.
11567 if (roi_info.x < 0)
11570 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11571 roi_info.x=(ssize_t) windows->image.ximage->width;
11572 if ((int) roi_info.x < x)
11573 roi_info.width=(unsigned int) (x-roi_info.x);
11576 roi_info.width=(unsigned int) (roi_info.x-x);
11577 roi_info.x=(ssize_t) x;
11579 if (roi_info.y < 0)
11582 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11583 roi_info.y=(ssize_t) windows->image.ximage->height;
11584 if ((int) roi_info.y < y)
11585 roi_info.height=(unsigned int) (y-roi_info.y);
11588 roi_info.height=(unsigned int) (roi_info.y-y);
11589 roi_info.y=(ssize_t) y;
11592 } while ((state & ExitState) == 0);
11594 Wait for user to grab a corner of the rectangle or press return.
11596 state=DefaultState;
11597 command_type=NullCommand;
11600 (void) XMapWindow(display,windows->info.id);
11603 if (windows->info.mapped != MagickFalse )
11606 Display pointer position.
11608 (void) FormatLocaleString(text,MagickPathExtent,
11609 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11610 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11611 XInfoWidget(display,windows,text);
11613 highlight_info=roi_info;
11614 highlight_info.x=roi_info.x-windows->image.x;
11615 highlight_info.y=roi_info.y-windows->image.y;
11616 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11618 state|=EscapeState;
11622 if ((state & UpdateRegionState) != 0)
11624 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11625 switch (command_type)
11630 (void) XMagickCommand(display,resource_info,windows,command_type,
11637 Region of interest is relative to image configuration.
11639 progress_monitor=SetImageProgressMonitor(*image,
11640 (MagickProgressMonitor) NULL,(*image)->client_data);
11641 crop_info=roi_info;
11642 width=(unsigned int) (*image)->columns;
11643 height=(unsigned int) (*image)->rows;
11646 if (windows->image.crop_geometry != (char *) NULL)
11647 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11649 scale_factor=(double) width/windows->image.ximage->width;
11651 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11652 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11653 scale_factor=(double)
11654 height/windows->image.ximage->height;
11656 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11657 crop_info.height=(unsigned int)
11658 (scale_factor*crop_info.height+0.5);
11659 roi_image=CropImage(*image,&crop_info,exception);
11660 (void) SetImageProgressMonitor(*image,progress_monitor,
11661 (*image)->client_data);
11662 if (roi_image == (Image *) NULL)
11665 Apply image processing technique to the region of interest.
11667 windows->image.orphan=MagickTrue;
11668 (void) XMagickCommand(display,resource_info,windows,command_type,
11669 &roi_image,exception);
11670 progress_monitor=SetImageProgressMonitor(*image,
11671 (MagickProgressMonitor) NULL,(*image)->client_data);
11672 (void) XMagickCommand(display,resource_info,windows,
11673 SaveToUndoBufferCommand,image,exception);
11674 windows->image.orphan=MagickFalse;
11675 (void) CompositeImage(*image,roi_image,CopyCompositeOp,
11676 MagickTrue,crop_info.x,crop_info.y,exception);
11677 roi_image=DestroyImage(roi_image);
11678 (void) SetImageProgressMonitor(*image,progress_monitor,
11679 (*image)->client_data);
11683 if (command_type != InfoCommand)
11685 XConfigureImageColormap(display,resource_info,windows,*image,
11687 (void) XConfigureImage(display,resource_info,windows,*image,
11690 XCheckRefreshWindows(display,windows);
11691 XInfoWidget(display,windows,text);
11692 (void) XSetFunction(display,windows->image.highlight_context,
11694 state&=(~UpdateRegionState);
11696 XHighlightRectangle(display,windows->image.id,
11697 windows->image.highlight_context,&highlight_info);
11698 XScreenEvent(display,windows,&event,exception);
11699 if (event.xany.window == windows->command.id)
11702 Select a command from the Command widget.
11704 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11705 command_type=NullCommand;
11706 id=XCommandWidget(display,windows,ApplyMenu,&event);
11709 (void) CopyMagickString(command,ApplyMenu[id],MagickPathExtent);
11710 command_type=ApplyCommands[id];
11711 if (id < ApplyMenus)
11714 Select a command from a pop-up menu.
11716 entry=XMenuWidget(display,windows,ApplyMenu[id],
11717 (const char **) Menus[id],command);
11720 (void) CopyMagickString(command,Menus[id][entry],
11722 command_type=Commands[id][entry];
11726 (void) XSetFunction(display,windows->image.highlight_context,
11728 XHighlightRectangle(display,windows->image.id,
11729 windows->image.highlight_context,&highlight_info);
11730 if (command_type == HelpCommand)
11732 (void) XSetFunction(display,windows->image.highlight_context,
11734 XTextViewWidget(display,resource_info,windows,MagickFalse,
11735 "Help Viewer - Region of Interest",ImageROIHelp);
11736 (void) XSetFunction(display,windows->image.highlight_context,
11740 if (command_type == QuitCommand)
11745 state|=EscapeState;
11749 if (command_type != NullCommand)
11750 state|=UpdateRegionState;
11753 XHighlightRectangle(display,windows->image.id,
11754 windows->image.highlight_context,&highlight_info);
11755 switch (event.type)
11759 x=windows->image.x;
11760 y=windows->image.y;
11761 if (event.xbutton.button != Button1)
11763 if (event.xbutton.window != windows->image.id)
11765 x=windows->image.x+event.xbutton.x;
11766 y=windows->image.y+event.xbutton.y;
11767 if ((x < (int) (roi_info.x+RoiDelta)) &&
11768 (x > (int) (roi_info.x-RoiDelta)) &&
11769 (y < (int) (roi_info.y+RoiDelta)) &&
11770 (y > (int) (roi_info.y-RoiDelta)))
11772 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11773 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11774 state|=UpdateConfigurationState;
11777 if ((x < (int) (roi_info.x+RoiDelta)) &&
11778 (x > (int) (roi_info.x-RoiDelta)) &&
11779 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11780 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11782 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11783 state|=UpdateConfigurationState;
11786 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11787 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11788 (y < (int) (roi_info.y+RoiDelta)) &&
11789 (y > (int) (roi_info.y-RoiDelta)))
11791 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11792 state|=UpdateConfigurationState;
11795 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11796 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11797 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11798 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11800 state|=UpdateConfigurationState;
11804 case ButtonRelease:
11806 if (event.xbutton.window == windows->pan.id)
11807 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11808 (highlight_info.y != crop_info.y-windows->image.y))
11809 XHighlightRectangle(display,windows->image.id,
11810 windows->image.highlight_context,&highlight_info);
11811 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11812 event.xbutton.time);
11817 if (event.xexpose.window == windows->image.id)
11818 if (event.xexpose.count == 0)
11820 event.xexpose.x=(int) highlight_info.x;
11821 event.xexpose.y=(int) highlight_info.y;
11822 event.xexpose.width=(int) highlight_info.width;
11823 event.xexpose.height=(int) highlight_info.height;
11824 XRefreshWindow(display,&windows->image,&event);
11826 if (event.xexpose.window == windows->info.id)
11827 if (event.xexpose.count == 0)
11828 XInfoWidget(display,windows,text);
11836 if (event.xkey.window != windows->image.id)
11839 Respond to a user key press.
11841 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11842 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11843 switch ((int) key_symbol)
11850 state|=EscapeState;
11859 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11860 roi_info.y=(ssize_t) (windows->image.height/2L-
11861 roi_info.height/2L);
11893 (void) XSetFunction(display,windows->image.highlight_context,
11895 XTextViewWidget(display,resource_info,windows,MagickFalse,
11896 "Help Viewer - Region of Interest",ImageROIHelp);
11897 (void) XSetFunction(display,windows->image.highlight_context,
11903 command_type=XImageWindowCommand(display,resource_info,windows,
11904 event.xkey.state,key_symbol,image,exception);
11905 if (command_type != NullCommand)
11906 state|=UpdateRegionState;
11910 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11918 if (event.xbutton.window != windows->image.id)
11921 Map and unmap Info widget as text cursor crosses its boundaries.
11925 if (windows->info.mapped != MagickFalse )
11927 if ((x < (int) (windows->info.x+windows->info.width)) &&
11928 (y < (int) (windows->info.y+windows->info.height)))
11929 (void) XWithdrawWindow(display,windows->info.id,
11930 windows->info.screen);
11933 if ((x > (int) (windows->info.x+windows->info.width)) ||
11934 (y > (int) (windows->info.y+windows->info.height)))
11935 (void) XMapWindow(display,windows->info.id);
11936 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11937 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11940 case SelectionRequest:
11945 XSelectionRequestEvent
11949 Set primary selection.
11951 (void) FormatLocaleString(text,MagickPathExtent,
11952 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11953 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11954 request=(&(event.xselectionrequest));
11955 (void) XChangeProperty(request->display,request->requestor,
11956 request->property,request->target,8,PropModeReplace,
11957 (unsigned char *) text,(int) strlen(text));
11958 notify.type=SelectionNotify;
11959 notify.display=request->display;
11960 notify.requestor=request->requestor;
11961 notify.selection=request->selection;
11962 notify.target=request->target;
11963 notify.time=request->time;
11964 if (request->property == None)
11965 notify.property=request->target;
11967 notify.property=request->property;
11968 (void) XSendEvent(request->display,request->requestor,False,0,
11969 (XEvent *) ¬ify);
11974 if ((state & UpdateConfigurationState) != 0)
11976 (void) XPutBackEvent(display,&event);
11977 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11980 } while ((state & ExitState) == 0);
11981 } while ((state & ExitState) == 0);
11982 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11983 XSetCursorState(display,windows,MagickFalse);
11984 if ((state & EscapeState) != 0)
11985 return(MagickTrue);
11986 return(MagickTrue);
11990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11994 + X R o t a t e I m a g e %
11998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12000 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
12001 % rotation angle is computed from the slope of a line drawn by the user.
12003 % The format of the XRotateImage method is:
12005 % MagickBooleanType XRotateImage(Display *display,
12006 % XResourceInfo *resource_info,XWindows *windows,double degrees,
12007 % Image **image,ExceptionInfo *exception)
12009 % A description of each parameter follows:
12011 % o display: Specifies a connection to an X server; returned from
12014 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12016 % o windows: Specifies a pointer to a XWindows structure.
12018 % o degrees: Specifies the number of degrees to rotate the image.
12020 % o image: the image.
12022 % o exception: return any errors or warnings in this structure.
12025 static MagickBooleanType XRotateImage(Display *display,
12026 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12027 ExceptionInfo *exception)
12040 direction = HorizontalRotateCommand;
12042 static const ModeType
12043 DirectionCommands[] =
12045 HorizontalRotateCommand,
12046 VerticalRotateCommand
12050 RotateColorCommand,
12051 RotateDirectionCommand,
12053 RotateDismissCommand
12056 static unsigned int
12060 command[MagickPathExtent],
12061 text[MagickPathExtent];
12072 normalized_degrees;
12082 if (degrees == 0.0)
12097 Map Command widget.
12099 (void) CloneString(&windows->command.name,"Rotate");
12100 windows->command.data=2;
12101 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12102 (void) XMapRaised(display,windows->command.id);
12103 XClientMessage(display,windows->image.id,windows->im_protocols,
12104 windows->im_update_widget,CurrentTime);
12106 Wait for first button press.
12108 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12109 XQueryPosition(display,windows->image.id,&x,&y);
12114 state=DefaultState;
12117 XHighlightLine(display,windows->image.id,
12118 windows->image.highlight_context,&rotate_info);
12120 Wait for next event.
12122 XScreenEvent(display,windows,&event,exception);
12123 XHighlightLine(display,windows->image.id,
12124 windows->image.highlight_context,&rotate_info);
12125 if (event.xany.window == windows->command.id)
12128 Select a command from the Command widget.
12130 id=XCommandWidget(display,windows,RotateMenu,&event);
12133 (void) XSetFunction(display,windows->image.highlight_context,
12135 switch (RotateCommands[id])
12137 case RotateColorCommand:
12140 *ColorMenu[MaxNumberPens];
12149 Initialize menu selections.
12151 for (i=0; i < (int) (MaxNumberPens-2); i++)
12152 ColorMenu[i]=resource_info->pen_colors[i];
12153 ColorMenu[MaxNumberPens-2]="Browser...";
12154 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12156 Select a pen color from the pop-up menu.
12158 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12159 (const char **) ColorMenu,command);
12160 if (pen_number < 0)
12162 if (pen_number == (MaxNumberPens-2))
12165 color_name[MagickPathExtent] = "gray";
12168 Select a pen color from a dialog.
12170 resource_info->pen_colors[pen_number]=color_name;
12171 XColorBrowserWidget(display,windows,"Select",color_name);
12172 if (*color_name == '\0')
12178 (void) XParseColor(display,windows->map_info->colormap,
12179 resource_info->pen_colors[pen_number],&color);
12180 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12181 (unsigned int) MaxColors,&color);
12182 windows->pixel_info->pen_colors[pen_number]=color;
12183 pen_id=(unsigned int) pen_number;
12186 case RotateDirectionCommand:
12197 Select a command from the pop-up menu.
12199 id=XMenuWidget(display,windows,RotateMenu[id],
12200 Directions,command);
12202 direction=DirectionCommands[id];
12205 case RotateHelpCommand:
12207 XTextViewWidget(display,resource_info,windows,MagickFalse,
12208 "Help Viewer - Image Rotation",ImageRotateHelp);
12211 case RotateDismissCommand:
12216 state|=EscapeState;
12223 (void) XSetFunction(display,windows->image.highlight_context,
12227 switch (event.type)
12231 if (event.xbutton.button != Button1)
12233 if (event.xbutton.window != windows->image.id)
12238 (void) XSetFunction(display,windows->image.highlight_context,
12240 rotate_info.x1=event.xbutton.x;
12241 rotate_info.y1=event.xbutton.y;
12245 case ButtonRelease:
12252 command[MagickPathExtent];
12257 if (event.xkey.window != windows->image.id)
12260 Respond to a user key press.
12262 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12263 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12264 switch ((int) key_symbol)
12272 state|=EscapeState;
12279 (void) XSetFunction(display,windows->image.highlight_context,
12281 XTextViewWidget(display,resource_info,windows,MagickFalse,
12282 "Help Viewer - Image Rotation",ImageRotateHelp);
12283 (void) XSetFunction(display,windows->image.highlight_context,
12289 (void) XBell(display,0);
12297 rotate_info.x1=event.xmotion.x;
12298 rotate_info.y1=event.xmotion.y;
12301 rotate_info.x2=rotate_info.x1;
12302 rotate_info.y2=rotate_info.y1;
12303 if (direction == HorizontalRotateCommand)
12304 rotate_info.x2+=32;
12306 rotate_info.y2-=32;
12307 } while ((state & ExitState) == 0);
12308 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12309 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12310 if ((state & EscapeState) != 0)
12311 return(MagickTrue);
12313 Draw line as pointer moves until the mouse button is released.
12316 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12317 state=DefaultState;
12323 Display info and draw rotation line.
12325 if (windows->info.mapped == MagickFalse)
12326 (void) XMapWindow(display,windows->info.id);
12327 (void) FormatLocaleString(text,MagickPathExtent," %g",
12328 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12329 XInfoWidget(display,windows,text);
12330 XHighlightLine(display,windows->image.id,
12331 windows->image.highlight_context,&rotate_info);
12334 if (windows->info.mapped != MagickFalse )
12335 (void) XWithdrawWindow(display,windows->info.id,
12336 windows->info.screen);
12338 Wait for next event.
12340 XScreenEvent(display,windows,&event,exception);
12342 XHighlightLine(display,windows->image.id,
12343 windows->image.highlight_context,&rotate_info);
12344 switch (event.type)
12348 case ButtonRelease:
12351 User has committed to rotation line.
12353 rotate_info.x2=event.xbutton.x;
12354 rotate_info.y2=event.xbutton.y;
12362 rotate_info.x2=event.xmotion.x;
12363 rotate_info.y2=event.xmotion.y;
12369 Check boundary conditions.
12371 if (rotate_info.x2 < 0)
12374 if (rotate_info.x2 > (int) windows->image.width)
12375 rotate_info.x2=(short) windows->image.width;
12376 if (rotate_info.y2 < 0)
12379 if (rotate_info.y2 > (int) windows->image.height)
12380 rotate_info.y2=(short) windows->image.height;
12382 Compute rotation angle from the slope of the line.
12385 distance=(unsigned int)
12386 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12387 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12389 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12390 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12391 } while ((state & ExitState) == 0);
12392 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12393 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12395 return(MagickTrue);
12397 if (direction == VerticalRotateCommand)
12399 if (degrees == 0.0)
12400 return(MagickTrue);
12404 normalized_degrees=degrees;
12405 while (normalized_degrees < -45.0)
12406 normalized_degrees+=360.0;
12407 for (rotations=0; normalized_degrees > 45.0; rotations++)
12408 normalized_degrees-=90.0;
12409 if (normalized_degrees != 0.0)
12410 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12412 XSetCursorState(display,windows,MagickTrue);
12413 XCheckRefreshWindows(display,windows);
12414 (*image)->background_color.red=(double) ScaleShortToQuantum(
12415 windows->pixel_info->pen_colors[pen_id].red);
12416 (*image)->background_color.green=(double) ScaleShortToQuantum(
12417 windows->pixel_info->pen_colors[pen_id].green);
12418 (*image)->background_color.blue=(double) ScaleShortToQuantum(
12419 windows->pixel_info->pen_colors[pen_id].blue);
12420 rotate_image=RotateImage(*image,degrees,exception);
12421 XSetCursorState(display,windows,MagickFalse);
12422 if (rotate_image == (Image *) NULL)
12423 return(MagickFalse);
12424 *image=DestroyImage(*image);
12425 *image=rotate_image;
12426 if (windows->image.crop_geometry != (char *) NULL)
12429 Rotate crop geometry.
12431 width=(unsigned int) (*image)->columns;
12432 height=(unsigned int) (*image)->rows;
12433 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12434 switch (rotations % 4)
12444 (void) FormatLocaleString(windows->image.crop_geometry,
12445 MagickPathExtent,"%ux%u%+d%+d",height,width,(int) (*image)->columns-
12452 Rotate 180 degrees.
12454 (void) FormatLocaleString(windows->image.crop_geometry,
12455 MagickPathExtent,"%ux%u%+d%+d",width,height,(int) width-x,(int)
12462 Rotate 270 degrees.
12464 (void) FormatLocaleString(windows->image.crop_geometry,
12465 MagickPathExtent,"%ux%u%+d%+d",height,width,y,(int) (*image)->rows-
12471 if (windows->image.orphan != MagickFalse )
12472 return(MagickTrue);
12473 if (normalized_degrees != 0.0)
12476 Update image colormap.
12478 windows->image.window_changes.width=(int) (*image)->columns;
12479 windows->image.window_changes.height=(int) (*image)->rows;
12480 if (windows->image.crop_geometry != (char *) NULL)
12483 Obtain dimensions of image from crop geometry.
12485 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12487 windows->image.window_changes.width=(int) width;
12488 windows->image.window_changes.height=(int) height;
12490 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12493 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12495 windows->image.window_changes.width=windows->image.ximage->height;
12496 windows->image.window_changes.height=windows->image.ximage->width;
12499 Update image configuration.
12501 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12502 return(MagickTrue);
12506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12510 + X S a v e I m a g e %
12514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12516 % XSaveImage() saves an image to a file.
12518 % The format of the XSaveImage method is:
12520 % MagickBooleanType XSaveImage(Display *display,
12521 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12522 % ExceptionInfo *exception)
12524 % A description of each parameter follows:
12526 % o display: Specifies a connection to an X server; returned from
12529 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12531 % o windows: Specifies a pointer to a XWindows structure.
12533 % o image: the image.
12535 % o exception: return any errors or warnings in this structure.
12538 static MagickBooleanType XSaveImage(Display *display,
12539 XResourceInfo *resource_info,XWindows *windows,Image *image,
12540 ExceptionInfo *exception)
12543 filename[MagickPathExtent],
12544 geometry[MagickPathExtent];
12556 Request file name from user.
12558 if (resource_info->write_filename != (char *) NULL)
12559 (void) CopyMagickString(filename,resource_info->write_filename,
12564 path[MagickPathExtent];
12569 GetPathComponent(image->filename,HeadPath,path);
12570 GetPathComponent(image->filename,TailPath,filename);
12573 status=chdir(path);
12575 (void) ThrowMagickException(exception,GetMagickModule(),
12576 FileOpenError,"UnableToOpenFile","%s",path);
12579 XFileBrowserWidget(display,windows,"Save",filename);
12580 if (*filename == '\0')
12581 return(MagickTrue);
12582 if (IsPathAccessible(filename) != MagickFalse )
12588 File exists-- seek user's permission before overwriting.
12590 status=XConfirmWidget(display,windows,"Overwrite",filename);
12592 return(MagickTrue);
12594 image_info=CloneImageInfo(resource_info->image_info);
12595 (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
12596 (void) SetImageInfo(image_info,1,exception);
12597 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12598 (LocaleCompare(image_info->magick,"JPG") == 0))
12601 quality[MagickPathExtent];
12607 Request JPEG quality from user.
12609 (void) FormatLocaleString(quality,MagickPathExtent,"%.20g",(double)
12611 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12613 if (*quality == '\0')
12614 return(MagickTrue);
12615 image->quality=StringToUnsignedLong(quality);
12616 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12618 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12619 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12620 (LocaleCompare(image_info->magick,"PS") == 0) ||
12621 (LocaleCompare(image_info->magick,"PS2") == 0))
12624 geometry[MagickPathExtent];
12627 Request page geometry from user.
12629 (void) CopyMagickString(geometry,PSPageGeometry,MagickPathExtent);
12630 if (LocaleCompare(image_info->magick,"PDF") == 0)
12631 (void) CopyMagickString(geometry,PSPageGeometry,MagickPathExtent);
12632 if (image_info->page != (char *) NULL)
12633 (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
12634 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12635 "Select page geometry:",geometry);
12636 if (*geometry != '\0')
12637 image_info->page=GetPageGeometry(geometry);
12640 Apply image transforms.
12642 XSetCursorState(display,windows,MagickTrue);
12643 XCheckRefreshWindows(display,windows);
12644 save_image=CloneImage(image,0,0,MagickTrue,exception);
12645 if (save_image == (Image *) NULL)
12646 return(MagickFalse);
12647 (void) FormatLocaleString(geometry,MagickPathExtent,"%dx%d!",
12648 windows->image.ximage->width,windows->image.ximage->height);
12649 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12654 (void) CopyMagickString(save_image->filename,filename,MagickPathExtent);
12655 status=WriteImage(image_info,save_image,exception);
12656 if (status != MagickFalse )
12657 image->taint=MagickFalse;
12658 save_image=DestroyImage(save_image);
12659 image_info=DestroyImageInfo(image_info);
12660 XSetCursorState(display,windows,MagickFalse);
12661 return(status != 0 ? MagickTrue : MagickFalse);
12665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12669 + X S c r e e n E v e n t %
12673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12675 % XScreenEvent() handles global events associated with the Pan and Magnify
12678 % The format of the XScreenEvent function is:
12680 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12681 % ExceptionInfo *exception)
12683 % A description of each parameter follows:
12685 % o display: Specifies a pointer to the Display structure; returned from
12688 % o windows: Specifies a pointer to a XWindows structure.
12690 % o event: Specifies a pointer to a X11 XEvent structure.
12692 % o exception: return any errors or warnings in this structure.
12696 #if defined(__cplusplus) || defined(c_plusplus)
12700 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12705 windows=(XWindows *) data;
12706 if ((event->type == ClientMessage) &&
12707 (event->xclient.window == windows->image.id))
12708 return(MagickFalse);
12709 return(MagickTrue);
12712 #if defined(__cplusplus) || defined(c_plusplus)
12716 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12717 ExceptionInfo *exception)
12723 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12724 if (event->xany.window == windows->command.id)
12726 switch (event->type)
12729 case ButtonRelease:
12731 if ((event->xbutton.button == Button3) &&
12732 (event->xbutton.state & Mod1Mask))
12735 Convert Alt-Button3 to Button2.
12737 event->xbutton.button=Button2;
12738 event->xbutton.state&=(~Mod1Mask);
12740 if (event->xbutton.window == windows->backdrop.id)
12742 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12743 event->xbutton.time);
12746 if (event->xbutton.window == windows->pan.id)
12748 XPanImage(display,windows,event,exception);
12751 if (event->xbutton.window == windows->image.id)
12752 if (event->xbutton.button == Button2)
12755 Update magnified image.
12757 x=event->xbutton.x;
12758 y=event->xbutton.y;
12762 if (x >= (int) windows->image.width)
12763 x=(int) (windows->image.width-1);
12764 windows->magnify.x=(int) windows->image.x+x;
12768 if (y >= (int) windows->image.height)
12769 y=(int) (windows->image.height-1);
12770 windows->magnify.y=windows->image.y+y;
12771 if (windows->magnify.mapped == MagickFalse)
12772 (void) XMapRaised(display,windows->magnify.id);
12773 XMakeMagnifyImage(display,windows,exception);
12774 if (event->type == ButtonRelease)
12775 (void) XWithdrawWindow(display,windows->info.id,
12776 windows->info.screen);
12781 case ClientMessage:
12784 If client window delete message, exit.
12786 if (event->xclient.message_type != windows->wm_protocols)
12788 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12790 if (event->xclient.window == windows->magnify.id)
12792 (void) XWithdrawWindow(display,windows->magnify.id,
12793 windows->magnify.screen);
12798 case ConfigureNotify:
12800 if (event->xconfigure.window == windows->magnify.id)
12806 Magnify window has a new configuration.
12808 windows->magnify.width=(unsigned int) event->xconfigure.width;
12809 windows->magnify.height=(unsigned int) event->xconfigure.height;
12810 if (windows->magnify.mapped == MagickFalse)
12813 while ((int) magnify <= event->xconfigure.width)
12815 while ((int) magnify <= event->xconfigure.height)
12818 if (((int) magnify != event->xconfigure.width) ||
12819 ((int) magnify != event->xconfigure.height))
12824 window_changes.width=(int) magnify;
12825 window_changes.height=(int) magnify;
12826 (void) XReconfigureWMWindow(display,windows->magnify.id,
12827 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12831 XMakeMagnifyImage(display,windows,exception);
12838 if (event->xexpose.window == windows->image.id)
12840 XRefreshWindow(display,&windows->image,event);
12843 if (event->xexpose.window == windows->pan.id)
12844 if (event->xexpose.count == 0)
12846 XDrawPanRectangle(display,windows);
12849 if (event->xexpose.window == windows->magnify.id)
12850 if (event->xexpose.count == 0)
12852 XMakeMagnifyImage(display,windows,exception);
12860 command[MagickPathExtent];
12865 if (event->xkey.window != windows->magnify.id)
12868 Respond to a user key press.
12870 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12871 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12872 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12878 if (event->xmap.window == windows->magnify.id)
12880 windows->magnify.mapped=MagickTrue;
12881 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12884 if (event->xmap.window == windows->info.id)
12886 windows->info.mapped=MagickTrue;
12893 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12894 if (event->xmotion.window == windows->image.id)
12895 if (windows->magnify.mapped != MagickFalse )
12898 Update magnified image.
12900 x=event->xmotion.x;
12901 y=event->xmotion.y;
12905 if (x >= (int) windows->image.width)
12906 x=(int) (windows->image.width-1);
12907 windows->magnify.x=(int) windows->image.x+x;
12911 if (y >= (int) windows->image.height)
12912 y=(int) (windows->image.height-1);
12913 windows->magnify.y=windows->image.y+y;
12914 XMakeMagnifyImage(display,windows,exception);
12920 if (event->xunmap.window == windows->magnify.id)
12922 windows->magnify.mapped=MagickFalse;
12925 if (event->xunmap.window == windows->info.id)
12927 windows->info.mapped=MagickFalse;
12938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12942 + X S e t C r o p G e o m e t r y %
12946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12948 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12949 % and translates it to a cropping geometry relative to the image.
12951 % The format of the XSetCropGeometry method is:
12953 % void XSetCropGeometry(Display *display,XWindows *windows,
12954 % RectangleInfo *crop_info,Image *image)
12956 % A description of each parameter follows:
12958 % o display: Specifies a connection to an X server; returned from
12961 % o windows: Specifies a pointer to a XWindows structure.
12963 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12964 % Image window to crop.
12966 % o image: the image.
12969 static void XSetCropGeometry(Display *display,XWindows *windows,
12970 RectangleInfo *crop_info,Image *image)
12973 text[MagickPathExtent];
12986 if (windows->info.mapped != MagickFalse )
12989 Display info on cropping rectangle.
12991 (void) FormatLocaleString(text,MagickPathExtent," %.20gx%.20g%+.20g%+.20g",
12992 (double) crop_info->width,(double) crop_info->height,(double)
12993 crop_info->x,(double) crop_info->y);
12994 XInfoWidget(display,windows,text);
12997 Cropping geometry is relative to any previous crop geometry.
13001 width=(unsigned int) image->columns;
13002 height=(unsigned int) image->rows;
13003 if (windows->image.crop_geometry != (char *) NULL)
13004 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13006 windows->image.crop_geometry=AcquireString((char *) NULL);
13008 Define the crop geometry string from the cropping rectangle.
13010 scale_factor=(double) width/windows->image.ximage->width;
13011 if (crop_info->x > 0)
13012 x+=(int) (scale_factor*crop_info->x+0.5);
13013 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13016 scale_factor=(double) height/windows->image.ximage->height;
13017 if (crop_info->y > 0)
13018 y+=(int) (scale_factor*crop_info->y+0.5);
13019 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13022 (void) FormatLocaleString(windows->image.crop_geometry,MagickPathExtent,
13023 "%ux%u%+d%+d",width,height,x,y);
13027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13031 + X T i l e I m a g e %
13035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13037 % XTileImage() loads or deletes a selected tile from a visual image directory.
13038 % The load or delete command is chosen from a menu.
13040 % The format of the XTileImage method is:
13042 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13043 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13045 % A description of each parameter follows:
13047 % o tile_image: XTileImage reads or deletes the tile image
13048 % and returns it. A null image is returned if an error occurs.
13050 % o display: Specifies a connection to an X server; returned from
13053 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13055 % o windows: Specifies a pointer to a XWindows structure.
13057 % o image: the image; returned from ReadImage.
13059 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13060 % the entire image is refreshed.
13062 % o exception: return any errors or warnings in this structure.
13065 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13066 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13079 static const ModeType
13090 command[MagickPathExtent],
13091 filename[MagickPathExtent];
13118 Tile image is relative to montage image configuration.
13122 width=(unsigned int) image->columns;
13123 height=(unsigned int) image->rows;
13124 if (windows->image.crop_geometry != (char *) NULL)
13125 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13126 scale_factor=(double) width/windows->image.ximage->width;
13127 event->xbutton.x+=windows->image.x;
13128 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13129 scale_factor=(double) height/windows->image.ximage->height;
13130 event->xbutton.y+=windows->image.y;
13131 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13133 Determine size and location of each tile in the visual image directory.
13135 width=(unsigned int) image->columns;
13136 height=(unsigned int) image->rows;
13139 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13140 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13141 (event->xbutton.x-x)/width;
13145 Button press is outside any tile.
13147 (void) XBell(display,0);
13148 return((Image *) NULL);
13151 Determine file name from the tile directory.
13153 p=image->directory;
13154 for (i=tile; (i != 0) && (*p != '\0'); )
13163 Button press is outside any tile.
13165 (void) XBell(display,0);
13166 return((Image *) NULL);
13169 Select a command from the pop-up menu.
13171 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13173 return((Image *) NULL);
13175 while ((*q != '\n') && (*q != '\0'))
13177 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13179 Perform command for the selected tile.
13181 XSetCursorState(display,windows,MagickTrue);
13182 XCheckRefreshWindows(display,windows);
13183 tile_image=NewImageList();
13184 switch (TileCommands[id])
13186 case TileLoadCommand:
13191 XCheckRefreshWindows(display,windows);
13192 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13194 (void) CopyMagickString(resource_info->image_info->filename,filename,
13196 tile_image=ReadImage(resource_info->image_info,exception);
13197 CatchException(exception);
13198 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13201 case TileNextCommand:
13204 Display next image.
13206 XClientMessage(display,windows->image.id,windows->im_protocols,
13207 windows->im_next_image,CurrentTime);
13210 case TileFormerCommand:
13213 Display former image.
13215 XClientMessage(display,windows->image.id,windows->im_protocols,
13216 windows->im_former_image,CurrentTime);
13219 case TileDeleteCommand:
13224 if (IsPathAccessible(filename) == MagickFalse)
13226 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13229 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13232 status=ShredFile(filename);
13233 if (status != MagickFalse )
13235 XNoticeWidget(display,windows,"Unable to delete image file:",
13240 case TileUpdateCommand:
13256 Ensure all the images exist.
13259 GetPixelInfo(image,&pixel);
13260 for (p=image->directory; *p != '\0'; p++)
13266 while ((*q != '\xff') && (*q != '\0'))
13268 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13270 if (IsPathAccessible(filename) != MagickFalse )
13276 Overwrite tile with background color.
13278 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13279 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13280 image_view=AcquireAuthenticCacheView(image,exception);
13281 (void) GetOneCacheViewVirtualPixelInfo(image_view,0,0,&pixel,exception);
13282 for (i=0; i < (int) height; i++)
13284 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13285 y_offset+i,width,1,exception);
13286 if (s == (Quantum *) NULL)
13288 for (j=0; j < (int) width; j++)
13290 SetPixelViaPixelInfo(image,&pixel,s);
13291 s+=GetPixelChannels(image);
13293 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13296 image_view=DestroyCacheView(image_view);
13299 windows->image.window_changes.width=(int) image->columns;
13300 windows->image.window_changes.height=(int) image->rows;
13301 XConfigureImageColormap(display,resource_info,windows,image,exception);
13302 (void) XConfigureImage(display,resource_info,windows,image,exception);
13308 XSetCursorState(display,windows,MagickFalse);
13309 return(tile_image);
13313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13317 + X T r a n s l a t e I m a g e %
13321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13323 % XTranslateImage() translates the image within an Image window by one pixel
13324 % as specified by the key symbol. If the image has a montage string the
13325 % translation is respect to the width and height contained within the string.
13327 % The format of the XTranslateImage method is:
13329 % void XTranslateImage(Display *display,XWindows *windows,
13330 % Image *image,const KeySym key_symbol)
13332 % A description of each parameter follows:
13334 % o display: Specifies a connection to an X server; returned from
13337 % o windows: Specifies a pointer to a XWindows structure.
13339 % o image: the image.
13341 % o key_symbol: Specifies a KeySym which indicates which side of the image
13345 static void XTranslateImage(Display *display,XWindows *windows,
13346 Image *image,const KeySym key_symbol)
13349 text[MagickPathExtent];
13360 User specified a pan position offset.
13362 x_offset=windows->image.width;
13363 y_offset=windows->image.height;
13364 if (image->montage != (char *) NULL)
13365 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13366 switch ((int) key_symbol)
13371 windows->image.x=(int) windows->image.width/2;
13372 windows->image.y=(int) windows->image.height/2;
13378 windows->image.x-=x_offset;
13385 windows->image.y-=y_offset;
13391 windows->image.x+=x_offset;
13398 windows->image.y+=y_offset;
13405 Check boundary conditions.
13407 if (windows->image.x < 0)
13408 windows->image.x=0;
13410 if ((int) (windows->image.x+windows->image.width) >
13411 windows->image.ximage->width)
13412 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13413 if (windows->image.y < 0)
13414 windows->image.y=0;
13416 if ((int) (windows->image.y+windows->image.height) >
13417 windows->image.ximage->height)
13418 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13420 Refresh Image window.
13422 (void) FormatLocaleString(text,MagickPathExtent," %ux%u%+d%+d ",
13423 windows->image.width,windows->image.height,windows->image.x,
13425 XInfoWidget(display,windows,text);
13426 XCheckRefreshWindows(display,windows);
13427 XDrawPanRectangle(display,windows);
13428 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13429 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13437 + X T r i m I m a g e %
13441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13443 % XTrimImage() trims the edges from the Image window.
13445 % The format of the XTrimImage method is:
13447 % MagickBooleanType XTrimImage(Display *display,
13448 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13449 % ExceptionInfo *exception)
13451 % A description of each parameter follows:
13453 % o display: Specifies a connection to an X server; returned from
13456 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13458 % o windows: Specifies a pointer to a XWindows structure.
13460 % o image: the image.
13462 % o exception: return any errors or warnings in this structure.
13465 static MagickBooleanType XTrimImage(Display *display,
13466 XResourceInfo *resource_info,XWindows *windows,Image *image,
13467 ExceptionInfo *exception)
13481 Trim edges from image.
13483 XSetCursorState(display,windows,MagickTrue);
13484 XCheckRefreshWindows(display,windows);
13486 Crop the left edge.
13488 background=XGetPixel(windows->image.ximage,0,0);
13489 trim_info.width=(size_t) windows->image.ximage->width;
13490 for (x=0; x < windows->image.ximage->width; x++)
13492 for (y=0; y < windows->image.ximage->height; y++)
13494 pixel=XGetPixel(windows->image.ximage,x,y);
13495 if (pixel != background)
13498 if (y < windows->image.ximage->height)
13501 trim_info.x=(ssize_t) x;
13502 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13504 XSetCursorState(display,windows,MagickFalse);
13505 return(MagickFalse);
13508 Crop the right edge.
13510 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13511 for (x=windows->image.ximage->width-1; x != 0; x--)
13513 for (y=0; y < windows->image.ximage->height; y++)
13515 pixel=XGetPixel(windows->image.ximage,x,y);
13516 if (pixel != background)
13519 if (y < windows->image.ximage->height)
13522 trim_info.width=(size_t) (x-trim_info.x+1);
13526 background=XGetPixel(windows->image.ximage,0,0);
13527 trim_info.height=(size_t) windows->image.ximage->height;
13528 for (y=0; y < windows->image.ximage->height; y++)
13530 for (x=0; x < windows->image.ximage->width; x++)
13532 pixel=XGetPixel(windows->image.ximage,x,y);
13533 if (pixel != background)
13536 if (x < windows->image.ximage->width)
13539 trim_info.y=(ssize_t) y;
13541 Crop the bottom edge.
13543 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13544 for (y=windows->image.ximage->height-1; y != 0; y--)
13546 for (x=0; x < windows->image.ximage->width; x++)
13548 pixel=XGetPixel(windows->image.ximage,x,y);
13549 if (pixel != background)
13552 if (x < windows->image.ximage->width)
13555 trim_info.height=(size_t) y-trim_info.y+1;
13556 if (((unsigned int) trim_info.width != windows->image.width) ||
13557 ((unsigned int) trim_info.height != windows->image.height))
13560 Reconfigure Image window as defined by the trimming rectangle.
13562 XSetCropGeometry(display,windows,&trim_info,image);
13563 windows->image.window_changes.width=(int) trim_info.width;
13564 windows->image.window_changes.height=(int) trim_info.height;
13565 (void) XConfigureImage(display,resource_info,windows,image,exception);
13567 XSetCursorState(display,windows,MagickFalse);
13568 return(MagickTrue);
13572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13576 + X V i s u a l D i r e c t o r y I m a g e %
13580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13582 % XVisualDirectoryImage() creates a Visual Image Directory.
13584 % The format of the XVisualDirectoryImage method is:
13586 % Image *XVisualDirectoryImage(Display *display,
13587 % XResourceInfo *resource_info,XWindows *windows,
13588 % ExceptionInfo *exception)
13590 % A description of each parameter follows:
13592 % o display: Specifies a connection to an X server; returned from
13595 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13597 % o windows: Specifies a pointer to a XWindows structure.
13599 % o exception: return any errors or warnings in this structure.
13602 static Image *XVisualDirectoryImage(Display *display,
13603 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13605 #define TileImageTag "Scale/Image"
13606 #define XClientName "montage"
13639 filename[MagickPathExtent] = "\0",
13640 filenames[MagickPathExtent] = "*";
13643 background_resources;
13646 Request file name from user.
13648 XFileBrowserWidget(display,windows,"Directory",filenames);
13649 if (*filenames == '\0')
13650 return((Image *) NULL);
13652 Expand the filenames.
13654 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13655 if (filelist == (char **) NULL)
13657 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
13659 return((Image *) NULL);
13662 filelist[0]=filenames;
13663 status=ExpandFilenames(&number_files,&filelist);
13664 if ((status == MagickFalse) || (number_files == 0))
13666 if (number_files == 0)
13667 ThrowXWindowException(ImageError,"NoImagesWereFound",filenames)
13669 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
13671 return((Image *) NULL);
13674 Set image background resources.
13676 background_resources=(*resource_info);
13677 background_resources.window_id=AcquireString("");
13678 (void) FormatLocaleString(background_resources.window_id,MagickPathExtent,
13679 "0x%lx",windows->image.id);
13680 background_resources.backdrop=MagickTrue;
13682 Read each image and convert them to a tile.
13684 backdrop=((windows->visual_info->klass == TrueColor) ||
13685 (windows->visual_info->klass == DirectColor)) ? MagickTrue : MagickFalse;
13686 read_info=CloneImageInfo(resource_info->image_info);
13687 (void) SetImageOption(read_info,"jpeg:size","120x120");
13688 (void) CloneString(&read_info->size,DefaultTileGeometry);
13689 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13691 images=NewImageList();
13692 XSetCursorState(display,windows,MagickTrue);
13693 XCheckRefreshWindows(display,windows);
13694 for (i=0; i < (int) number_files; i++)
13696 (void) CopyMagickString(read_info->filename,filelist[i],MagickPathExtent);
13697 filelist[i]=DestroyString(filelist[i]);
13698 *read_info->magick='\0';
13699 next_image=ReadImage(read_info,exception);
13700 CatchException(exception);
13701 if (next_image != (Image *) NULL)
13703 (void) DeleteImageProperty(next_image,"label");
13704 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13705 read_info,next_image,DefaultTileLabel,exception),exception);
13706 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13708 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13709 geometry.height,exception);
13710 if (thumbnail_image != (Image *) NULL)
13712 next_image=DestroyImage(next_image);
13713 next_image=thumbnail_image;
13717 (void) XDisplayBackgroundImage(display,&background_resources,
13718 next_image,exception);
13719 XSetCursorState(display,windows,MagickTrue);
13721 AppendImageToList(&images,next_image);
13722 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13727 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13728 (MagickSizeType) number_files);
13729 if (proceed == MagickFalse)
13734 filelist=(char **) RelinquishMagickMemory(filelist);
13735 if (images == (Image *) NULL)
13737 read_info=DestroyImageInfo(read_info);
13738 XSetCursorState(display,windows,MagickFalse);
13739 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
13740 return((Image *) NULL);
13743 Create the Visual Image Directory.
13745 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13746 montage_info->pointsize=10;
13747 if (resource_info->font != (char *) NULL)
13748 (void) CloneString(&montage_info->font,resource_info->font);
13749 (void) CopyMagickString(montage_info->filename,filename,MagickPathExtent);
13750 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13751 images),exception);
13752 images=DestroyImageList(images);
13753 montage_info=DestroyMontageInfo(montage_info);
13754 read_info=DestroyImageInfo(read_info);
13755 XSetCursorState(display,windows,MagickFalse);
13756 if (montage_image == (Image *) NULL)
13757 return(montage_image);
13758 XClientMessage(display,windows->image.id,windows->im_protocols,
13759 windows->im_next_image,CurrentTime);
13760 return(montage_image);
13764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13768 % X D i s p l a y B a c k g r o u n d I m a g e %
13772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13774 % XDisplayBackgroundImage() displays an image in the background of a window.
13776 % The format of the XDisplayBackgroundImage method is:
13778 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13779 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13781 % A description of each parameter follows:
13783 % o display: Specifies a connection to an X server; returned from
13786 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13788 % o image: the image.
13790 % o exception: return any errors or warnings in this structure.
13793 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13794 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13797 geometry[MagickPathExtent],
13798 visual_type[MagickPathExtent];
13811 static XStandardColormap
13815 *visual_info = (XVisualInfo *) NULL;
13836 Determine target window.
13838 assert(image != (Image *) NULL);
13839 assert(image->signature == MagickCoreSignature);
13840 if (image->debug != MagickFalse )
13841 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13842 resources=(*resource_info);
13843 window_info.id=(Window) NULL;
13844 root_window=XRootWindow(display,XDefaultScreen(display));
13845 if (LocaleCompare(resources.window_id,"root") == 0)
13846 window_info.id=root_window;
13849 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
13850 window_info.id=XWindowByID(display,root_window,
13851 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13852 if (window_info.id == (Window) NULL)
13853 window_info.id=XWindowByName(display,root_window,resources.window_id);
13855 if (window_info.id == (Window) NULL)
13857 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
13858 resources.window_id);
13859 return(MagickFalse);
13862 Determine window visual id.
13864 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13865 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13866 (void) CopyMagickString(visual_type,"default",MagickPathExtent);
13867 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13869 (void) FormatLocaleString(visual_type,MagickPathExtent,"0x%lx",
13870 XVisualIDFromVisual(window_attributes.visual));
13871 if (visual_info == (XVisualInfo *) NULL)
13874 Allocate standard colormap.
13876 map_info=XAllocStandardColormap();
13877 if (map_info == (XStandardColormap *) NULL)
13878 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13880 map_info->colormap=(Colormap) NULL;
13881 pixel.pixels=(unsigned long *) NULL;
13883 Initialize visual info.
13885 resources.map_type=(char *) NULL;
13886 resources.visual_type=visual_type;
13887 visual_info=XBestVisualInfo(display,map_info,&resources);
13888 if (visual_info == (XVisualInfo *) NULL)
13889 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13890 resources.visual_type);
13892 Initialize window info.
13894 window_info.ximage=(XImage *) NULL;
13895 window_info.matte_image=(XImage *) NULL;
13896 window_info.pixmap=(Pixmap) NULL;
13897 window_info.matte_pixmap=(Pixmap) NULL;
13900 Free previous root colors.
13902 if (window_info.id == root_window)
13903 (void) XDestroyWindowColors(display,root_window);
13905 Initialize Standard Colormap.
13907 resources.colormap=SharedColormap;
13908 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13911 Graphic context superclass.
13913 context_values.background=pixel.background_color.pixel;
13914 context_values.foreground=pixel.foreground_color.pixel;
13915 pixel.annotate_context=XCreateGC(display,window_info.id,
13916 (size_t) (GCBackground | GCForeground),&context_values);
13917 if (pixel.annotate_context == (GC) NULL)
13918 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13921 Initialize Image window attributes.
13923 window_info.name=AcquireString("\0");
13924 window_info.icon_name=AcquireString("\0");
13925 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13926 &resources,&window_info);
13928 Create the X image.
13930 window_info.width=(unsigned int) image->columns;
13931 window_info.height=(unsigned int) image->rows;
13932 if ((image->columns != window_info.width) ||
13933 (image->rows != window_info.height))
13934 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13936 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>",
13937 window_attributes.width,window_attributes.height);
13938 geometry_info.width=window_info.width;
13939 geometry_info.height=window_info.height;
13940 geometry_info.x=(ssize_t) window_info.x;
13941 geometry_info.y=(ssize_t) window_info.y;
13942 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13943 &geometry_info.width,&geometry_info.height);
13944 window_info.width=(unsigned int) geometry_info.width;
13945 window_info.height=(unsigned int) geometry_info.height;
13946 window_info.x=(int) geometry_info.x;
13947 window_info.y=(int) geometry_info.y;
13948 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13949 window_info.height,exception);
13950 if (status == MagickFalse)
13951 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13955 if (image->debug != MagickFalse )
13957 (void) LogMagickEvent(X11Event,GetMagickModule(),
13958 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13959 (double) image->columns,(double) image->rows);
13960 if (image->colors != 0)
13961 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13963 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13966 Adjust image dimensions as specified by backdrop or geometry options.
13968 width=(int) window_info.width;
13969 height=(int) window_info.height;
13970 if (resources.backdrop != MagickFalse )
13973 Center image on window.
13975 window_info.x=(window_attributes.width/2)-
13976 (window_info.ximage->width/2);
13977 window_info.y=(window_attributes.height/2)-
13978 (window_info.ximage->height/2);
13979 width=window_attributes.width;
13980 height=window_attributes.height;
13982 if ((resources.image_geometry != (char *) NULL) &&
13983 (*resources.image_geometry != '\0'))
13986 default_geometry[MagickPathExtent];
13996 User specified geometry.
13998 size_hints=XAllocSizeHints();
13999 if (size_hints == (XSizeHints *) NULL)
14000 ThrowXWindowFatalException(ResourceLimitFatalError,
14001 "MemoryAllocationFailed",image->filename);
14002 size_hints->flags=0L;
14003 (void) FormatLocaleString(default_geometry,MagickPathExtent,"%dx%d",
14005 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
14006 default_geometry,window_info.border_width,size_hints,&window_info.x,
14007 &window_info.y,&width,&height,&gravity);
14008 if (flags & (XValue | YValue))
14010 width=window_attributes.width;
14011 height=window_attributes.height;
14013 (void) XFree((void *) size_hints);
14016 Create the X pixmap.
14018 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14019 (unsigned int) height,window_info.depth);
14020 if (window_info.pixmap == (Pixmap) NULL)
14021 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14024 Display pixmap on the window.
14026 if (((unsigned int) width > window_info.width) ||
14027 ((unsigned int) height > window_info.height))
14028 (void) XFillRectangle(display,window_info.pixmap,
14029 window_info.annotate_context,0,0,(unsigned int) width,
14030 (unsigned int) height);
14031 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14032 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14033 window_info.width,(unsigned int) window_info.height);
14034 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14035 (void) XClearWindow(display,window_info.id);
14036 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14037 XDelay(display,delay == 0UL ? 10UL : delay);
14038 (void) XSync(display,MagickFalse);
14039 return(window_info.id == root_window ? MagickTrue : MagickFalse);
14043 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14047 + X D i s p l a y I m a g e %
14051 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14053 % XDisplayImage() displays an image via X11. A new image is created and
14054 % returned if the user interactively transforms the displayed image.
14056 % The format of the XDisplayImage method is:
14058 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14059 % char **argv,int argc,Image **image,size_t *state,
14060 % ExceptionInfo *exception)
14062 % A description of each parameter follows:
14064 % o nexus: Method XDisplayImage returns an image when the
14065 % user chooses 'Open Image' from the command menu or picks a tile
14066 % from the image directory. Otherwise a null image is returned.
14068 % o display: Specifies a connection to an X server; returned from
14071 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14073 % o argv: Specifies the application's argument list.
14075 % o argc: Specifies the number of arguments.
14077 % o image: Specifies an address to an address of an Image structure;
14079 % o exception: return any errors or warnings in this structure.
14082 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14083 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14085 #define MagnifySize 256 /* must be a power of 2 */
14086 #define MagickMenus 10
14087 #define MagickTitle "Commands"
14114 "Visual Directory...",
14160 "Contrast Stretch...",
14161 "Sigmoidal Contrast...",
14195 "Charcoal Draw...",
14209 "Region of Interest...",
14212 *MiscellanyMenu[] =
14227 "Browse Documentation",
14254 **Menus[MagickMenus] =
14292 VisualDirectoryCommand,
14306 OriginalSizeCommand,
14313 TransformCommands[] =
14319 RotateRightCommand,
14326 EnhanceCommands[] =
14334 ContrastStretchCommand,
14335 SigmoidalContrastCommand,
14343 EffectsCommands[] =
14347 ReduceNoiseCommand,
14367 CharcoalDrawCommand
14369 ImageEditCommands[] =
14380 RegionofInterestCommand
14382 MiscellanyCommands[] =
14386 ShowPreviewCommand,
14387 ShowHistogramCommand,
14396 BrowseDocumentationCommand,
14399 ShortCutsCommands[] =
14411 VirtualCommands[] =
14420 *Commands[MagickMenus] =
14430 MiscellanyCommands,
14435 command[MagickPathExtent],
14437 geometry[MagickPathExtent],
14438 resource_name[MagickPathExtent];
14465 working_directory[MagickPathExtent];
14471 *magick_windows[MaxXWindows];
14473 static unsigned int
14533 assert(image != (Image **) NULL);
14534 assert((*image)->signature == MagickCoreSignature);
14535 if ((*image)->debug != MagickFalse )
14536 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14537 display_image=(*image);
14538 warning_handler=(WarningHandler) NULL;
14539 windows=XSetWindows((XWindows *) ~0);
14540 if (windows != (XWindows *) NULL)
14545 if (*working_directory == '\0')
14546 (void) CopyMagickString(working_directory,".",MagickPathExtent);
14547 status=chdir(working_directory);
14549 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14550 "UnableToOpenFile","%s",working_directory);
14551 warning_handler=resource_info->display_warnings ?
14552 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14553 warning_handler=resource_info->display_warnings ?
14554 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14559 Allocate windows structure.
14561 resource_info->colors=display_image->colors;
14562 windows=XSetWindows(XInitializeWindows(display,resource_info));
14563 if (windows == (XWindows *) NULL)
14564 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14565 (*image)->filename);
14567 Initialize window id's.
14570 magick_windows[number_windows++]=(&windows->icon);
14571 magick_windows[number_windows++]=(&windows->backdrop);
14572 magick_windows[number_windows++]=(&windows->image);
14573 magick_windows[number_windows++]=(&windows->info);
14574 magick_windows[number_windows++]=(&windows->command);
14575 magick_windows[number_windows++]=(&windows->widget);
14576 magick_windows[number_windows++]=(&windows->popup);
14577 magick_windows[number_windows++]=(&windows->magnify);
14578 magick_windows[number_windows++]=(&windows->pan);
14579 for (i=0; i < (int) number_windows; i++)
14580 magick_windows[i]->id=(Window) NULL;
14585 Initialize font info.
14587 if (windows->font_info != (XFontStruct *) NULL)
14588 (void) XFreeFont(display,windows->font_info);
14589 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14590 if (windows->font_info == (XFontStruct *) NULL)
14591 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14592 resource_info->font);
14594 Initialize Standard Colormap.
14596 map_info=windows->map_info;
14597 icon_map=windows->icon_map;
14598 visual_info=windows->visual_info;
14599 icon_visual=windows->icon_visual;
14600 pixel=windows->pixel_info;
14601 icon_pixel=windows->icon_pixel;
14602 font_info=windows->font_info;
14603 icon_resources=windows->icon_resources;
14604 class_hints=windows->class_hints;
14605 manager_hints=windows->manager_hints;
14606 root_window=XRootWindow(display,visual_info->screen);
14607 nexus=NewImageList();
14608 if (display_image->debug != MagickFalse )
14610 (void) LogMagickEvent(X11Event,GetMagickModule(),
14611 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14612 (double) display_image->scene,(double) display_image->columns,
14613 (double) display_image->rows);
14614 if (display_image->colors != 0)
14615 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14616 display_image->colors);
14617 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14618 display_image->magick);
14620 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14621 map_info,pixel,exception);
14622 display_image->taint=MagickFalse;
14624 Initialize graphic context.
14626 windows->context.id=(Window) NULL;
14627 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14628 resource_info,&windows->context);
14629 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14630 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14631 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14632 manager_hints->flags=InputHint | StateHint;
14633 manager_hints->input=MagickFalse;
14634 manager_hints->initial_state=WithdrawnState;
14635 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14636 &windows->context);
14637 if (display_image->debug != MagickFalse )
14638 (void) LogMagickEvent(X11Event,GetMagickModule(),
14639 "Window id: 0x%lx (context)",windows->context.id);
14640 context_values.background=pixel->background_color.pixel;
14641 context_values.font=font_info->fid;
14642 context_values.foreground=pixel->foreground_color.pixel;
14643 context_values.graphics_exposures=MagickFalse;
14644 context_mask=(MagickStatusType)
14645 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14646 if (pixel->annotate_context != (GC) NULL)
14647 (void) XFreeGC(display,pixel->annotate_context);
14648 pixel->annotate_context=XCreateGC(display,windows->context.id,
14649 context_mask,&context_values);
14650 if (pixel->annotate_context == (GC) NULL)
14651 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14652 display_image->filename);
14653 context_values.background=pixel->depth_color.pixel;
14654 if (pixel->widget_context != (GC) NULL)
14655 (void) XFreeGC(display,pixel->widget_context);
14656 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14658 if (pixel->widget_context == (GC) NULL)
14659 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14660 display_image->filename);
14661 context_values.background=pixel->foreground_color.pixel;
14662 context_values.foreground=pixel->background_color.pixel;
14663 context_values.plane_mask=context_values.background ^
14664 context_values.foreground;
14665 if (pixel->highlight_context != (GC) NULL)
14666 (void) XFreeGC(display,pixel->highlight_context);
14667 pixel->highlight_context=XCreateGC(display,windows->context.id,
14668 (size_t) (context_mask | GCPlaneMask),&context_values);
14669 if (pixel->highlight_context == (GC) NULL)
14670 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14671 display_image->filename);
14672 (void) XDestroyWindow(display,windows->context.id);
14674 Initialize icon window.
14676 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14677 icon_resources,&windows->icon);
14678 windows->icon.geometry=resource_info->icon_geometry;
14679 XBestIconSize(display,&windows->icon,display_image);
14680 windows->icon.attributes.colormap=XDefaultColormap(display,
14681 icon_visual->screen);
14682 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14683 manager_hints->flags=InputHint | StateHint;
14684 manager_hints->input=MagickFalse;
14685 manager_hints->initial_state=IconicState;
14686 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14688 if (display_image->debug != MagickFalse )
14689 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14692 Initialize graphic context for icon window.
14694 if (icon_pixel->annotate_context != (GC) NULL)
14695 (void) XFreeGC(display,icon_pixel->annotate_context);
14696 context_values.background=icon_pixel->background_color.pixel;
14697 context_values.foreground=icon_pixel->foreground_color.pixel;
14698 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14699 (size_t) (GCBackground | GCForeground),&context_values);
14700 if (icon_pixel->annotate_context == (GC) NULL)
14701 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14702 display_image->filename);
14703 windows->icon.annotate_context=icon_pixel->annotate_context;
14705 Initialize Image window.
14707 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14709 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14710 if (resource_info->use_shared_memory == MagickFalse)
14711 windows->image.shared_memory=MagickFalse;
14712 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14717 title=InterpretImageProperties(resource_info->image_info,display_image,
14718 resource_info->title,exception);
14719 (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
14720 (void) CopyMagickString(windows->image.icon_name,title,MagickPathExtent);
14721 title=DestroyString(title);
14726 filename[MagickPathExtent];
14729 Window name is the base of the filename.
14731 GetPathComponent(display_image->magick_filename,TailPath,filename);
14732 if (display_image->scene == 0)
14733 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
14734 "%s: %s",MagickPackageName,filename);
14736 (void) FormatLocaleString(windows->image.name,MagickPathExtent,
14737 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14738 (double) display_image->scene,(double) GetImageListLength(
14740 (void) CopyMagickString(windows->image.icon_name,filename,
14743 if (resource_info->immutable)
14744 windows->image.immutable=MagickTrue;
14745 windows->image.use_pixmap=resource_info->use_pixmap;
14746 windows->image.geometry=resource_info->image_geometry;
14747 (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
14748 XDisplayWidth(display,visual_info->screen),
14749 XDisplayHeight(display,visual_info->screen));
14750 geometry_info.width=display_image->columns;
14751 geometry_info.height=display_image->rows;
14754 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14755 &geometry_info.width,&geometry_info.height);
14756 windows->image.width=(unsigned int) geometry_info.width;
14757 windows->image.height=(unsigned int) geometry_info.height;
14758 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14759 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14760 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14761 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14762 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14763 resource_info,&windows->backdrop);
14764 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14767 Initialize backdrop window.
14769 windows->backdrop.x=0;
14770 windows->backdrop.y=0;
14771 (void) CloneString(&windows->backdrop.name,"Backdrop");
14772 windows->backdrop.flags=(size_t) (USSize | USPosition);
14773 windows->backdrop.width=(unsigned int)
14774 XDisplayWidth(display,visual_info->screen);
14775 windows->backdrop.height=(unsigned int)
14776 XDisplayHeight(display,visual_info->screen);
14777 windows->backdrop.border_width=0;
14778 windows->backdrop.immutable=MagickTrue;
14779 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14781 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14782 StructureNotifyMask;
14783 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14784 manager_hints->icon_window=windows->icon.id;
14785 manager_hints->input=MagickTrue;
14786 manager_hints->initial_state=resource_info->iconic ? IconicState :
14788 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14789 &windows->backdrop);
14790 if (display_image->debug != MagickFalse )
14791 (void) LogMagickEvent(X11Event,GetMagickModule(),
14792 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14793 (void) XMapWindow(display,windows->backdrop.id);
14794 (void) XClearWindow(display,windows->backdrop.id);
14795 if (windows->image.id != (Window) NULL)
14797 (void) XDestroyWindow(display,windows->image.id);
14798 windows->image.id=(Window) NULL;
14801 Position image in the center the backdrop.
14803 windows->image.flags|=USPosition;
14804 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14805 (windows->image.width/2);
14806 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14807 (windows->image.height/2);
14809 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14810 manager_hints->icon_window=windows->icon.id;
14811 manager_hints->input=MagickTrue;
14812 manager_hints->initial_state=resource_info->iconic ? IconicState :
14814 if (windows->group_leader.id != (Window) NULL)
14819 manager_hints->flags|=WindowGroupHint;
14820 manager_hints->window_group=windows->group_leader.id;
14821 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14822 if (display_image->debug != MagickFalse )
14823 (void) LogMagickEvent(X11Event,GetMagickModule(),
14824 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14826 XMakeWindow(display,
14827 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14828 argv,argc,class_hints,manager_hints,&windows->image);
14829 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14830 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14831 if (windows->group_leader.id != (Window) NULL)
14832 (void) XSetTransientForHint(display,windows->image.id,
14833 windows->group_leader.id);
14834 if (display_image->debug != MagickFalse )
14835 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14836 windows->image.id);
14838 Initialize Info widget.
14840 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14842 (void) CloneString(&windows->info.name,"Info");
14843 (void) CloneString(&windows->info.icon_name,"Info");
14844 windows->info.border_width=1;
14847 windows->info.flags|=PPosition;
14848 windows->info.attributes.win_gravity=UnmapGravity;
14849 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14850 StructureNotifyMask;
14851 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14852 manager_hints->input=MagickFalse;
14853 manager_hints->initial_state=NormalState;
14854 manager_hints->window_group=windows->image.id;
14855 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14857 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14858 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14859 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14860 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14861 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14862 if (windows->image.mapped != MagickFalse )
14863 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14864 if (display_image->debug != MagickFalse )
14865 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14868 Initialize Command widget.
14870 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14871 resource_info,&windows->command);
14872 windows->command.data=MagickMenus;
14873 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14874 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.command",
14875 resource_info->client_name);
14876 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14877 resource_name,"geometry",(char *) NULL);
14878 (void) CloneString(&windows->command.name,MagickTitle);
14879 windows->command.border_width=0;
14880 windows->command.flags|=PPosition;
14881 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14882 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14883 OwnerGrabButtonMask | StructureNotifyMask;
14884 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14885 manager_hints->input=MagickTrue;
14886 manager_hints->initial_state=NormalState;
14887 manager_hints->window_group=windows->image.id;
14888 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14889 &windows->command);
14890 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14891 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14893 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14894 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14895 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14896 if (windows->command.mapped != MagickFalse )
14897 (void) XMapRaised(display,windows->command.id);
14898 if (display_image->debug != MagickFalse )
14899 (void) LogMagickEvent(X11Event,GetMagickModule(),
14900 "Window id: 0x%lx (command)",windows->command.id);
14902 Initialize Widget window.
14904 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14905 resource_info,&windows->widget);
14906 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.widget",
14907 resource_info->client_name);
14908 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14909 resource_name,"geometry",(char *) NULL);
14910 windows->widget.border_width=0;
14911 windows->widget.flags|=PPosition;
14912 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14913 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14914 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14915 StructureNotifyMask;
14916 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14917 manager_hints->input=MagickTrue;
14918 manager_hints->initial_state=NormalState;
14919 manager_hints->window_group=windows->image.id;
14920 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14922 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14923 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14924 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14925 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14926 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14927 if (display_image->debug != MagickFalse )
14928 (void) LogMagickEvent(X11Event,GetMagickModule(),
14929 "Window id: 0x%lx (widget)",windows->widget.id);
14931 Initialize popup window.
14933 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14934 resource_info,&windows->popup);
14935 windows->popup.border_width=0;
14936 windows->popup.flags|=PPosition;
14937 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14938 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14939 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14940 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14941 manager_hints->input=MagickTrue;
14942 manager_hints->initial_state=NormalState;
14943 manager_hints->window_group=windows->image.id;
14944 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14946 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14947 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14948 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14949 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14950 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14951 if (display_image->debug != MagickFalse )
14952 (void) LogMagickEvent(X11Event,GetMagickModule(),
14953 "Window id: 0x%lx (pop up)",windows->popup.id);
14955 Initialize Magnify window and cursor.
14957 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14958 resource_info,&windows->magnify);
14959 if (resource_info->use_shared_memory == MagickFalse)
14960 windows->magnify.shared_memory=MagickFalse;
14961 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.magnify",
14962 resource_info->client_name);
14963 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14964 resource_name,"geometry",(char *) NULL);
14965 (void) FormatLocaleString(windows->magnify.name,MagickPathExtent,"Magnify %uX",
14966 resource_info->magnify);
14967 if (windows->magnify.cursor != (Cursor) NULL)
14968 (void) XFreeCursor(display,windows->magnify.cursor);
14969 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14970 map_info->colormap,resource_info->background_color,
14971 resource_info->foreground_color);
14972 if (windows->magnify.cursor == (Cursor) NULL)
14973 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14974 display_image->filename);
14975 windows->magnify.width=MagnifySize;
14976 windows->magnify.height=MagnifySize;
14977 windows->magnify.flags|=PPosition;
14978 windows->magnify.min_width=MagnifySize;
14979 windows->magnify.min_height=MagnifySize;
14980 windows->magnify.width_inc=MagnifySize;
14981 windows->magnify.height_inc=MagnifySize;
14982 windows->magnify.data=resource_info->magnify;
14983 windows->magnify.attributes.cursor=windows->magnify.cursor;
14984 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14985 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14986 StructureNotifyMask;
14987 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14988 manager_hints->input=MagickTrue;
14989 manager_hints->initial_state=NormalState;
14990 manager_hints->window_group=windows->image.id;
14991 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14992 &windows->magnify);
14993 if (display_image->debug != MagickFalse )
14994 (void) LogMagickEvent(X11Event,GetMagickModule(),
14995 "Window id: 0x%lx (magnify)",windows->magnify.id);
14996 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14998 Initialize panning window.
15000 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
15001 resource_info,&windows->pan);
15002 (void) CloneString(&windows->pan.name,"Pan Icon");
15003 windows->pan.width=windows->icon.width;
15004 windows->pan.height=windows->icon.height;
15005 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.pan",
15006 resource_info->client_name);
15007 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
15008 resource_name,"geometry",(char *) NULL);
15009 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
15010 &windows->pan.width,&windows->pan.height);
15011 windows->pan.flags|=PPosition;
15012 windows->pan.immutable=MagickTrue;
15013 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15014 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15015 StructureNotifyMask;
15016 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15017 manager_hints->input=MagickFalse;
15018 manager_hints->initial_state=NormalState;
15019 manager_hints->window_group=windows->image.id;
15020 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15022 if (display_image->debug != MagickFalse )
15023 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15025 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15026 if (windows->info.mapped != MagickFalse )
15027 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15028 if ((windows->image.mapped == MagickFalse) ||
15029 (windows->backdrop.id != (Window) NULL))
15030 (void) XMapWindow(display,windows->image.id);
15032 Set our progress monitor and warning handlers.
15034 if (warning_handler == (WarningHandler) NULL)
15036 warning_handler=resource_info->display_warnings ?
15037 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15038 warning_handler=resource_info->display_warnings ?
15039 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15042 Initialize Image and Magnify X images.
15044 windows->image.x=0;
15045 windows->image.y=0;
15046 windows->magnify.shape=MagickFalse;
15047 width=(unsigned int) display_image->columns;
15048 height=(unsigned int) display_image->rows;
15049 if ((display_image->columns != width) || (display_image->rows != height))
15050 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15051 display_image->filename);
15052 status=XMakeImage(display,resource_info,&windows->image,display_image,
15053 width,height,exception);
15054 if (status == MagickFalse)
15055 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15056 display_image->filename);
15057 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15058 windows->magnify.width,windows->magnify.height,exception);
15059 if (status == MagickFalse)
15060 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15061 display_image->filename);
15062 if (windows->magnify.mapped != MagickFalse )
15063 (void) XMapRaised(display,windows->magnify.id);
15064 if (windows->pan.mapped != MagickFalse )
15065 (void) XMapRaised(display,windows->pan.id);
15066 windows->image.window_changes.width=(int) display_image->columns;
15067 windows->image.window_changes.height=(int) display_image->rows;
15068 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15069 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15070 (void) XSync(display,MagickFalse);
15074 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15075 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15077 if (resource_info->update != MagickFalse )
15083 Determine when file data was last modified.
15085 status=GetPathAttributes(display_image->filename,&attributes);
15086 if (status != MagickFalse )
15087 update_time=attributes.st_mtime;
15089 *state&=(~FormerImageState);
15090 *state&=(~MontageImageState);
15091 *state&=(~NextImageState);
15095 Handle a window event.
15097 if (windows->image.mapped != MagickFalse )
15098 if ((display_image->delay != 0) || (resource_info->update != 0))
15100 if (timer < time((time_t *) NULL))
15102 if (resource_info->update == MagickFalse)
15103 *state|=NextImageState | ExitState;
15110 Determine if image file was modified.
15112 status=GetPathAttributes(display_image->filename,&attributes);
15113 if (status != MagickFalse )
15114 if (update_time != attributes.st_mtime)
15119 (void) FormatLocaleString(
15120 resource_info->image_info->filename,MagickPathExtent,
15121 "%s:%s",display_image->magick,
15122 display_image->filename);
15123 nexus=ReadImage(resource_info->image_info,exception);
15124 if (nexus != (Image *) NULL)
15125 *state|=NextImageState | ExitState;
15127 delay=display_image->delay/MagickMax(
15128 display_image->ticks_per_second,1L);
15129 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15132 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15135 Do not block if delay > 0.
15137 XDelay(display,SuspendTime << 2);
15141 timestamp=time((time_t *) NULL);
15142 (void) XNextEvent(display,&event);
15143 if ((windows->image.stasis == MagickFalse) ||
15144 (windows->magnify.stasis == MagickFalse))
15146 if ((time((time_t *) NULL)-timestamp) > 0)
15148 windows->image.stasis=MagickTrue;
15149 windows->magnify.stasis=MagickTrue;
15152 if (event.xany.window == windows->command.id)
15155 Select a command from the Command widget.
15157 id=XCommandWidget(display,windows,CommandMenu,&event);
15160 (void) CopyMagickString(command,CommandMenu[id],MagickPathExtent);
15161 command_type=CommandMenus[id];
15162 if (id < MagickMenus)
15165 Select a command from a pop-up menu.
15167 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15171 (void) CopyMagickString(command,Menus[id][entry],MagickPathExtent);
15172 command_type=Commands[id][entry];
15174 if (command_type != NullCommand)
15175 nexus=XMagickCommand(display,resource_info,windows,command_type,
15176 &display_image,exception);
15179 switch (event.type)
15183 if (display_image->debug != MagickFalse )
15184 (void) LogMagickEvent(X11Event,GetMagickModule(),
15185 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15186 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15187 if ((event.xbutton.button == Button3) &&
15188 (event.xbutton.state & Mod1Mask))
15191 Convert Alt-Button3 to Button2.
15193 event.xbutton.button=Button2;
15194 event.xbutton.state&=(~Mod1Mask);
15196 if (event.xbutton.window == windows->backdrop.id)
15198 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15199 event.xbutton.time);
15202 if (event.xbutton.window == windows->image.id)
15204 switch (event.xbutton.button)
15208 if (resource_info->immutable)
15211 Select a command from the Virtual menu.
15213 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15216 nexus=XMagickCommand(display,resource_info,windows,
15217 VirtualCommands[entry],&display_image,exception);
15221 Map/unmap Command widget.
15223 if (windows->command.mapped != MagickFalse )
15224 (void) XWithdrawWindow(display,windows->command.id,
15225 windows->command.screen);
15228 (void) XCommandWidget(display,windows,CommandMenu,
15230 (void) XMapRaised(display,windows->command.id);
15237 User pressed the image magnify button.
15239 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15240 &display_image,exception);
15241 XMagnifyImage(display,windows,&event,exception);
15246 if (resource_info->immutable)
15249 Select a command from the Virtual menu.
15251 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15254 nexus=XMagickCommand(display,resource_info,windows,
15255 VirtualCommands[entry],&display_image,exception);
15258 if (display_image->montage != (char *) NULL)
15261 Open or delete a tile from a visual image directory.
15263 nexus=XTileImage(display,resource_info,windows,
15264 display_image,&event,exception);
15265 if (nexus != (Image *) NULL)
15266 *state|=MontageImageState | NextImageState | ExitState;
15267 vid_info.x=(short int) windows->image.x;
15268 vid_info.y=(short int) windows->image.y;
15272 Select a command from the Short Cuts menu.
15274 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15277 nexus=XMagickCommand(display,resource_info,windows,
15278 ShortCutsCommands[entry],&display_image,exception);
15286 XTranslateImage(display,windows,*image,XK_Up);
15294 XTranslateImage(display,windows,*image,XK_Down);
15302 if (event.xbutton.window == windows->magnify.id)
15322 MagnifyCommands[] =
15335 Select a magnify factor from the pop-up menu.
15337 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15339 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15343 if (event.xbutton.window == windows->pan.id)
15345 switch (event.xbutton.button)
15352 XTranslateImage(display,windows,*image,XK_Up);
15360 XTranslateImage(display,windows,*image,XK_Down);
15365 XPanImage(display,windows,&event,exception);
15371 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15373 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15376 case ButtonRelease:
15378 if (display_image->debug != MagickFalse )
15379 (void) LogMagickEvent(X11Event,GetMagickModule(),
15380 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15381 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15384 case ClientMessage:
15386 if (display_image->debug != MagickFalse )
15387 (void) LogMagickEvent(X11Event,GetMagickModule(),
15388 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15389 event.xclient.message_type,event.xclient.format,(unsigned long)
15390 event.xclient.data.l[0]);
15391 if (event.xclient.message_type == windows->im_protocols)
15393 if (*event.xclient.data.l == (long) windows->im_update_widget)
15395 (void) CloneString(&windows->command.name,MagickTitle);
15396 windows->command.data=MagickMenus;
15397 (void) XCommandWidget(display,windows,CommandMenu,
15401 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15404 Update graphic context and window colormap.
15406 for (i=0; i < (int) number_windows; i++)
15408 if (magick_windows[i]->id == windows->icon.id)
15410 context_values.background=pixel->background_color.pixel;
15411 context_values.foreground=pixel->foreground_color.pixel;
15412 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15413 context_mask,&context_values);
15414 (void) XChangeGC(display,magick_windows[i]->widget_context,
15415 context_mask,&context_values);
15416 context_values.background=pixel->foreground_color.pixel;
15417 context_values.foreground=pixel->background_color.pixel;
15418 context_values.plane_mask=context_values.background ^
15419 context_values.foreground;
15420 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15421 (size_t) (context_mask | GCPlaneMask),
15423 magick_windows[i]->attributes.background_pixel=
15424 pixel->background_color.pixel;
15425 magick_windows[i]->attributes.border_pixel=
15426 pixel->border_color.pixel;
15427 magick_windows[i]->attributes.colormap=map_info->colormap;
15428 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15429 (unsigned long) magick_windows[i]->mask,
15430 &magick_windows[i]->attributes);
15432 if (windows->pan.mapped != MagickFalse )
15434 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15435 windows->pan.pixmap);
15436 (void) XClearWindow(display,windows->pan.id);
15437 XDrawPanRectangle(display,windows);
15439 if (windows->backdrop.id != (Window) NULL)
15440 (void) XInstallColormap(display,map_info->colormap);
15443 if (*event.xclient.data.l == (long) windows->im_former_image)
15445 *state|=FormerImageState | ExitState;
15448 if (*event.xclient.data.l == (long) windows->im_next_image)
15450 *state|=NextImageState | ExitState;
15453 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15455 *state|=RetainColorsState;
15458 if (*event.xclient.data.l == (long) windows->im_exit)
15465 if (event.xclient.message_type == windows->dnd_protocols)
15483 Display image named by the Drag-and-Drop selection.
15485 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15487 selection=XInternAtom(display,"DndSelection",MagickFalse);
15488 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15489 MagickPathExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15490 &length,&after,&data);
15491 if ((status != Success) || (length == 0))
15493 if (*event.xclient.data.l == 2)
15498 (void) CopyMagickString(resource_info->image_info->filename,
15499 (char *) data,MagickPathExtent);
15506 if (strncmp((char *) data, "file:", 5) != 0)
15508 (void) XFree((void *) data);
15511 (void) CopyMagickString(resource_info->image_info->filename,
15512 ((char *) data)+5,MagickPathExtent);
15514 nexus=ReadImage(resource_info->image_info,exception);
15515 CatchException(exception);
15516 if (nexus != (Image *) NULL)
15517 *state|=NextImageState | ExitState;
15518 (void) XFree((void *) data);
15522 If client window delete message, exit.
15524 if (event.xclient.message_type != windows->wm_protocols)
15526 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15528 (void) XWithdrawWindow(display,event.xclient.window,
15529 visual_info->screen);
15530 if (event.xclient.window == windows->image.id)
15535 if (event.xclient.window == windows->pan.id)
15538 Restore original image size when pan window is deleted.
15540 windows->image.window_changes.width=windows->image.ximage->width;
15541 windows->image.window_changes.height=windows->image.ximage->height;
15542 (void) XConfigureImage(display,resource_info,windows,
15543 display_image,exception);
15547 case ConfigureNotify:
15549 if (display_image->debug != MagickFalse )
15550 (void) LogMagickEvent(X11Event,GetMagickModule(),
15551 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15552 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15553 event.xconfigure.y,event.xconfigure.send_event);
15554 if (event.xconfigure.window == windows->image.id)
15557 Image window has a new configuration.
15559 if (event.xconfigure.send_event != 0)
15565 Position the transient windows relative of the Image window.
15567 if (windows->command.geometry == (char *) NULL)
15568 if (windows->command.mapped == MagickFalse)
15570 windows->command.x=event.xconfigure.x-
15571 windows->command.width-25;
15572 windows->command.y=event.xconfigure.y;
15573 XConstrainWindowPosition(display,&windows->command);
15574 window_changes.x=windows->command.x;
15575 window_changes.y=windows->command.y;
15576 (void) XReconfigureWMWindow(display,windows->command.id,
15577 windows->command.screen,(unsigned int) (CWX | CWY),
15580 if (windows->widget.geometry == (char *) NULL)
15581 if (windows->widget.mapped == MagickFalse)
15583 windows->widget.x=event.xconfigure.x+
15584 event.xconfigure.width/10;
15585 windows->widget.y=event.xconfigure.y+
15586 event.xconfigure.height/10;
15587 XConstrainWindowPosition(display,&windows->widget);
15588 window_changes.x=windows->widget.x;
15589 window_changes.y=windows->widget.y;
15590 (void) XReconfigureWMWindow(display,windows->widget.id,
15591 windows->widget.screen,(unsigned int) (CWX | CWY),
15594 if (windows->magnify.geometry == (char *) NULL)
15595 if (windows->magnify.mapped == MagickFalse)
15597 windows->magnify.x=event.xconfigure.x+
15598 event.xconfigure.width+25;
15599 windows->magnify.y=event.xconfigure.y;
15600 XConstrainWindowPosition(display,&windows->magnify);
15601 window_changes.x=windows->magnify.x;
15602 window_changes.y=windows->magnify.y;
15603 (void) XReconfigureWMWindow(display,windows->magnify.id,
15604 windows->magnify.screen,(unsigned int) (CWX | CWY),
15607 if (windows->pan.geometry == (char *) NULL)
15608 if (windows->pan.mapped == MagickFalse)
15610 windows->pan.x=event.xconfigure.x+
15611 event.xconfigure.width+25;
15612 windows->pan.y=event.xconfigure.y+
15613 windows->magnify.height+50;
15614 XConstrainWindowPosition(display,&windows->pan);
15615 window_changes.x=windows->pan.x;
15616 window_changes.y=windows->pan.y;
15617 (void) XReconfigureWMWindow(display,windows->pan.id,
15618 windows->pan.screen,(unsigned int) (CWX | CWY),
15622 if ((event.xconfigure.width == (int) windows->image.width) &&
15623 (event.xconfigure.height == (int) windows->image.height))
15625 windows->image.width=(unsigned int) event.xconfigure.width;
15626 windows->image.height=(unsigned int) event.xconfigure.height;
15627 windows->image.x=0;
15628 windows->image.y=0;
15629 if (display_image->montage != (char *) NULL)
15631 windows->image.x=vid_info.x;
15632 windows->image.y=vid_info.y;
15634 if (windows->image.mapped != MagickFalse &&
15635 windows->image.stasis != MagickFalse )
15638 Update image window configuration.
15640 windows->image.window_changes.width=event.xconfigure.width;
15641 windows->image.window_changes.height=event.xconfigure.height;
15642 (void) XConfigureImage(display,resource_info,windows,
15643 display_image,exception);
15646 Update pan window configuration.
15648 if ((event.xconfigure.width < windows->image.ximage->width) ||
15649 (event.xconfigure.height < windows->image.ximage->height))
15651 (void) XMapRaised(display,windows->pan.id);
15652 XDrawPanRectangle(display,windows);
15655 if (windows->pan.mapped != MagickFalse )
15656 (void) XWithdrawWindow(display,windows->pan.id,
15657 windows->pan.screen);
15660 if (event.xconfigure.window == windows->magnify.id)
15666 Magnify window has a new configuration.
15668 windows->magnify.width=(unsigned int) event.xconfigure.width;
15669 windows->magnify.height=(unsigned int) event.xconfigure.height;
15670 if (windows->magnify.mapped == MagickFalse)
15673 while ((int) magnify <= event.xconfigure.width)
15675 while ((int) magnify <= event.xconfigure.height)
15678 if (((int) magnify != event.xconfigure.width) ||
15679 ((int) magnify != event.xconfigure.height))
15681 window_changes.width=(int) magnify;
15682 window_changes.height=(int) magnify;
15683 (void) XReconfigureWMWindow(display,windows->magnify.id,
15684 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15688 if (windows->magnify.mapped != MagickFalse &&
15689 windows->magnify.stasis != MagickFalse )
15691 status=XMakeImage(display,resource_info,&windows->magnify,
15692 display_image,windows->magnify.width,windows->magnify.height,
15694 XMakeMagnifyImage(display,windows,exception);
15698 if (windows->magnify.mapped != MagickFalse &&
15699 (event.xconfigure.window == windows->pan.id))
15702 Pan icon window has a new configuration.
15704 if (event.xconfigure.send_event != 0)
15706 windows->pan.x=event.xconfigure.x;
15707 windows->pan.y=event.xconfigure.y;
15709 windows->pan.width=(unsigned int) event.xconfigure.width;
15710 windows->pan.height=(unsigned int) event.xconfigure.height;
15713 if (event.xconfigure.window == windows->icon.id)
15716 Icon window has a new configuration.
15718 windows->icon.width=(unsigned int) event.xconfigure.width;
15719 windows->icon.height=(unsigned int) event.xconfigure.height;
15724 case DestroyNotify:
15727 Group leader has exited.
15729 if (display_image->debug != MagickFalse )
15730 (void) LogMagickEvent(X11Event,GetMagickModule(),
15731 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15732 if (event.xdestroywindow.window == windows->group_leader.id)
15742 Selectively install colormap.
15744 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15745 if (event.xcrossing.mode != NotifyUngrab)
15746 XInstallColormap(display,map_info->colormap);
15751 if (display_image->debug != MagickFalse )
15752 (void) LogMagickEvent(X11Event,GetMagickModule(),
15753 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15754 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15757 Refresh windows that are now exposed.
15759 if ((event.xexpose.window == windows->image.id) &&
15760 windows->image.mapped != MagickFalse )
15762 XRefreshWindow(display,&windows->image,&event);
15763 delay=display_image->delay/MagickMax(
15764 display_image->ticks_per_second,1L);
15765 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15768 if ((event.xexpose.window == windows->magnify.id) &&
15769 windows->magnify.mapped != MagickFalse)
15771 XMakeMagnifyImage(display,windows,exception);
15774 if (event.xexpose.window == windows->pan.id)
15776 XDrawPanRectangle(display,windows);
15779 if (event.xexpose.window == windows->icon.id)
15781 XRefreshWindow(display,&windows->icon,&event);
15792 Respond to a user key press.
15794 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15795 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15796 *(command+length)='\0';
15797 if (display_image->debug != MagickFalse )
15798 (void) LogMagickEvent(X11Event,GetMagickModule(),
15799 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15800 key_symbol,command);
15801 if (event.xkey.window == windows->image.id)
15803 command_type=XImageWindowCommand(display,resource_info,windows,
15804 event.xkey.state,key_symbol,&display_image,exception);
15805 if (command_type != NullCommand)
15806 nexus=XMagickCommand(display,resource_info,windows,command_type,
15807 &display_image,exception);
15809 if (event.xkey.window == windows->magnify.id)
15810 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15812 if (event.xkey.window == windows->pan.id)
15814 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15815 (void) XWithdrawWindow(display,windows->pan.id,
15816 windows->pan.screen);
15818 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15819 XTextViewWidget(display,resource_info,windows,MagickFalse,
15820 "Help Viewer - Image Pan",ImagePanHelp);
15822 XTranslateImage(display,windows,*image,key_symbol);
15824 delay=display_image->delay/MagickMax(
15825 display_image->ticks_per_second,1L);
15826 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15832 Respond to a user key release.
15834 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15835 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15836 if (display_image->debug != MagickFalse )
15837 (void) LogMagickEvent(X11Event,GetMagickModule(),
15838 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15844 Selectively uninstall colormap.
15846 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15847 if (event.xcrossing.mode != NotifyUngrab)
15848 XUninstallColormap(display,map_info->colormap);
15853 if (display_image->debug != MagickFalse )
15854 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15855 event.xmap.window);
15856 if (event.xmap.window == windows->backdrop.id)
15858 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15860 windows->backdrop.mapped=MagickTrue;
15863 if (event.xmap.window == windows->image.id)
15865 if (windows->backdrop.id != (Window) NULL)
15866 (void) XInstallColormap(display,map_info->colormap);
15867 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15869 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15870 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15872 if (((int) windows->image.width < windows->image.ximage->width) ||
15873 ((int) windows->image.height < windows->image.ximage->height))
15874 (void) XMapRaised(display,windows->pan.id);
15875 windows->image.mapped=MagickTrue;
15878 if (event.xmap.window == windows->magnify.id)
15880 XMakeMagnifyImage(display,windows,exception);
15881 windows->magnify.mapped=MagickTrue;
15882 (void) XWithdrawWindow(display,windows->info.id,
15883 windows->info.screen);
15886 if (event.xmap.window == windows->pan.id)
15888 XMakePanImage(display,resource_info,windows,display_image,
15890 windows->pan.mapped=MagickTrue;
15893 if (event.xmap.window == windows->info.id)
15895 windows->info.mapped=MagickTrue;
15898 if (event.xmap.window == windows->icon.id)
15904 Create an icon image.
15906 taint=display_image->taint;
15907 XMakeStandardColormap(display,icon_visual,icon_resources,
15908 display_image,icon_map,icon_pixel,exception);
15909 (void) XMakeImage(display,icon_resources,&windows->icon,
15910 display_image,windows->icon.width,windows->icon.height,
15912 display_image->taint=taint;
15913 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15914 windows->icon.pixmap);
15915 (void) XClearWindow(display,windows->icon.id);
15916 (void) XWithdrawWindow(display,windows->info.id,
15917 windows->info.screen);
15918 windows->icon.mapped=MagickTrue;
15921 if (event.xmap.window == windows->command.id)
15923 windows->command.mapped=MagickTrue;
15926 if (event.xmap.window == windows->popup.id)
15928 windows->popup.mapped=MagickTrue;
15931 if (event.xmap.window == windows->widget.id)
15933 windows->widget.mapped=MagickTrue;
15938 case MappingNotify:
15940 (void) XRefreshKeyboardMapping(&event.xmapping);
15945 case PropertyNotify:
15961 if (display_image->debug != MagickFalse )
15962 (void) LogMagickEvent(X11Event,GetMagickModule(),
15963 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15964 event.xproperty.atom,event.xproperty.state);
15965 if (event.xproperty.atom != windows->im_remote_command)
15968 Display image named by the remote command protocol.
15970 status=XGetWindowProperty(display,event.xproperty.window,
15971 event.xproperty.atom,0L,(long) MagickPathExtent,MagickFalse,(Atom)
15972 AnyPropertyType,&type,&format,&length,&after,&data);
15973 if ((status != Success) || (length == 0))
15975 if (LocaleCompare((char *) data,"-quit") == 0)
15977 XClientMessage(display,windows->image.id,windows->im_protocols,
15978 windows->im_exit,CurrentTime);
15979 (void) XFree((void *) data);
15982 (void) CopyMagickString(resource_info->image_info->filename,
15983 (char *) data,MagickPathExtent);
15984 (void) XFree((void *) data);
15985 nexus=ReadImage(resource_info->image_info,exception);
15986 CatchException(exception);
15987 if (nexus != (Image *) NULL)
15988 *state|=NextImageState | ExitState;
15991 case ReparentNotify:
15993 if (display_image->debug != MagickFalse )
15994 (void) LogMagickEvent(X11Event,GetMagickModule(),
15995 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15996 event.xreparent.window);
16001 if (display_image->debug != MagickFalse )
16002 (void) LogMagickEvent(X11Event,GetMagickModule(),
16003 "Unmap Notify: 0x%lx",event.xunmap.window);
16004 if (event.xunmap.window == windows->backdrop.id)
16006 windows->backdrop.mapped=MagickFalse;
16009 if (event.xunmap.window == windows->image.id)
16011 windows->image.mapped=MagickFalse;
16014 if (event.xunmap.window == windows->magnify.id)
16016 windows->magnify.mapped=MagickFalse;
16019 if (event.xunmap.window == windows->pan.id)
16021 windows->pan.mapped=MagickFalse;
16024 if (event.xunmap.window == windows->info.id)
16026 windows->info.mapped=MagickFalse;
16029 if (event.xunmap.window == windows->icon.id)
16031 if (map_info->colormap == icon_map->colormap)
16032 XConfigureImageColormap(display,resource_info,windows,
16033 display_image,exception);
16034 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16036 windows->icon.mapped=MagickFalse;
16039 if (event.xunmap.window == windows->command.id)
16041 windows->command.mapped=MagickFalse;
16044 if (event.xunmap.window == windows->popup.id)
16046 if (windows->backdrop.id != (Window) NULL)
16047 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16049 windows->popup.mapped=MagickFalse;
16052 if (event.xunmap.window == windows->widget.id)
16054 if (windows->backdrop.id != (Window) NULL)
16055 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16057 windows->widget.mapped=MagickFalse;
16064 if (display_image->debug != MagickFalse )
16065 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16070 } while (!(*state & ExitState));
16071 if ((*state & ExitState) == 0)
16072 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16073 &display_image,exception);
16075 if (resource_info->confirm_edit != MagickFalse )
16078 Query user if image has changed.
16080 if ((resource_info->immutable == MagickFalse) &&
16081 display_image->taint != MagickFalse)
16086 status=XConfirmWidget(display,windows,"Your image changed.",
16087 "Do you want to save it");
16089 *state&=(~ExitState);
16092 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16093 &display_image,exception);
16096 if ((windows->visual_info->klass == GrayScale) ||
16097 (windows->visual_info->klass == PseudoColor) ||
16098 (windows->visual_info->klass == DirectColor))
16101 Withdraw pan and Magnify window.
16103 if (windows->info.mapped != MagickFalse )
16104 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16105 if (windows->magnify.mapped != MagickFalse )
16106 (void) XWithdrawWindow(display,windows->magnify.id,
16107 windows->magnify.screen);
16108 if (windows->command.mapped != MagickFalse )
16109 (void) XWithdrawWindow(display,windows->command.id,
16110 windows->command.screen);
16112 if (windows->pan.mapped != MagickFalse )
16113 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16114 if (resource_info->backdrop == MagickFalse)
16115 if (windows->backdrop.mapped)
16117 (void) XWithdrawWindow(display,windows->backdrop.id,
16118 windows->backdrop.screen);
16119 (void) XDestroyWindow(display,windows->backdrop.id);
16120 windows->backdrop.id=(Window) NULL;
16121 (void) XWithdrawWindow(display,windows->image.id,
16122 windows->image.screen);
16123 (void) XDestroyWindow(display,windows->image.id);
16124 windows->image.id=(Window) NULL;
16126 XSetCursorState(display,windows,MagickTrue);
16127 XCheckRefreshWindows(display,windows);
16128 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16129 *state&=(~ExitState);
16130 if (*state & ExitState)
16133 Free Standard Colormap.
16135 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16136 if (resource_info->map_type == (char *) NULL)
16137 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16141 if (resource_info->copy_image != (Image *) NULL)
16143 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16144 resource_info->copy_image=NewImageList();
16146 DestroyXResources();
16148 (void) XSync(display,MagickFalse);
16150 Restore our progress monitor and warning handlers.
16152 (void) SetErrorHandler(warning_handler);
16153 (void) SetWarningHandler(warning_handler);
16155 Change to home directory.
16157 directory=getcwd(working_directory,MagickPathExtent);
16163 if (*resource_info->home_directory == '\0')
16164 (void) CopyMagickString(resource_info->home_directory,".",MagickPathExtent);
16165 status=chdir(resource_info->home_directory);
16167 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16168 "UnableToOpenFile","%s",resource_info->home_directory);
16170 *image=display_image;
16176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16180 + D i s p l a y I m a g e s %
16184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16186 % DisplayImages() displays an image sequence to any X window screen. It
16187 % returns a value other than 0 if successful. Check the exception member
16188 % of image to determine the reason for any failure.
16190 % The format of the DisplayImages method is:
16192 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16193 % Image *images,ExceptionInfo *exception)
16195 % A description of each parameter follows:
16197 % o image_info: the image info.
16199 % o image: the image.
16201 % o exception: return any errors or warnings in this structure.
16204 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16205 Image *image,ExceptionInfo *exception)
16207 assert(image_info != (const ImageInfo *) NULL);
16208 assert(image_info->signature == MagickCoreSignature);
16209 assert(image != (Image *) NULL);
16210 assert(image->signature == MagickCoreSignature);
16212 if (image->debug != MagickFalse )
16213 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16214 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16215 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
16216 return(MagickFalse);
16220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16224 + R e m o t e D i s p l a y C o m m a n d %
16228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16230 % RemoteDisplayCommand() encourages a remote display program to display the
16231 % specified image filename.
16233 % The format of the RemoteDisplayCommand method is:
16235 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16236 % const char *window,const char *filename,ExceptionInfo *exception)
16238 % A description of each parameter follows:
16240 % o image_info: the image info.
16242 % o window: Specifies the name or id of an X window.
16244 % o filename: the name of the image filename to display.
16246 % o exception: return any errors or warnings in this structure.
16249 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16250 const char *window,const char *filename,ExceptionInfo *exception)
16252 assert(image_info != (const ImageInfo *) NULL);
16253 assert(image_info->signature == MagickCoreSignature);
16254 assert(filename != (char *) NULL);
16256 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16257 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16258 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
16259 return(MagickFalse);